SSL Sertifika Hataları: Bağlantı Güvenliği Sorunlarını Giderme

Bir gün production sunucunuzdan “SSL_ERROR_RX_RECORD_TOO_LONG” hatası geldiğinde ve arkasında yüzlerce kullanıcı bağlanamıyorsa, o anın panikini yaşayan herkes bilir. SSL sertifika hataları, sistem yöneticilerinin en sık karşılaştığı ve aynı zamanda en fazla zaman kaybettiren sorunların başında gelir. Çünkü bu hatalar hem sunucu tarafında hem istemci tarafında hem de ağın ortasında oluşabilir. Bu yazıda SSL/TLS hatalarını gerçek dünya senaryolarıyla ele alacağız, sorunları nasıl teşhis edeceğimizi ve nasıl çözeceğimizi adım adım inceleyeceğiz.

SSL/TLS Neden Bu Kadar Karmaşık?

SSL ve TLS, sadece “sertifika var mı yok mu” meselesi değil. El sıkışma süreci (handshake), sertifika zinciri doğrulaması, cipher suite uyumu, sertifika geçerlilik tarihleri, SNI desteği… Bunların hepsi ayrı ayrı sorun kaynağı olabilir. Bir bağlantı hatası aldığınızda “sertifika süresi dolmuş” diye atlamak yerine sistematik bir teşhis süreci izlemek şart.

Önce temel kavramları netleştirelim:

  • Sertifika (Certificate): Sunucunun kimliğini kanıtlayan dijital belge
  • CA (Certificate Authority): Sertifikayı imzalayan ve güvenilir kabul edilen kurum
  • Sertifika Zinciri: Sunucu sertifikasından kök CA’ya kadar uzanan güven zinciri
  • Handshake: İstemci ile sunucu arasında şifreli bağlantı kurulmadan önceki müzakere süreci
  • SNI (Server Name Indication): Aynı IP’de birden fazla SSL sertifikası barındırmayı sağlayan uzantı

Temel Teşhis Araçları

openssl Komutu ile Sertifika Analizi

Sistematik teşhisin ilk durağı her zaman openssl olmalı. Bu araç olmadan SSL sorunlarını çözmek, gözü kapalı araba sürmek gibi.

# Uzak sunucunun sertifikasını incele
openssl s_client -connect example.com:443 -servername example.com

# Sadece sertifika bilgilerini göster
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -text

# Sertifika geçerlilik tarihlerini hızlıca kontrol et
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

# Tam sertifika zincirini göster
openssl s_client -connect example.com:443 -showcerts -servername example.com 2>/dev/null

Bu komutların çıktısında dikkat etmeniz gereken alanlar:

  • Verify return code: 0 ise her şey yolunda, başka bir sayı ise sorun var
  • subject: Sertifikanın kime ait olduğu
  • issuer: Sertifikayı kimin imzaladığı
  • notBefore / notAfter: Geçerlilik tarihleri

curl ile Hızlı Test

# SSL hatalarını detaylı görmek için verbose mod
curl -vvv https://example.com 2>&1 | head -50

# SSL doğrulamasını atlayarak bağlantı testı (geçici debug için!)
curl -k https://example.com

# Belirli bir CA bundle kullanarak test
curl --cacert /etc/ssl/certs/ca-certificates.crt https://example.com

# Hangi TLS versiyonu ve cipher kullanıldığını görmek
curl -vvv --tlsv1.2 https://example.com 2>&1 | grep -E "SSL|TLS|cipher"

Uyarı: -k parametresini sadece debug amaçlı kullanın, production ortamında asla.

Yaygın SSL Hata Tipleri ve Çözümleri

1. Sertifika Süresi Dolmuş (Certificate Expired)

En klasik ve en çok başa çıkılan hata. “certificate has expired or is not yet valid” mesajını görünce önce panik, sonra sertifika yenileme süreci başlar.

Teşhis:

# Sertifikanın ne zaman dolduğunu kontrol et
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null 
  | openssl x509 -noout -enddate

# Kaç gün kaldığını hesapla
echo | openssl s_client -connect example.com:443 2>/dev/null 
  | openssl x509 -noout -checkend 0
# Çıktı: "Certificate will not expire" veya "Certificate has expired"

# 30 gün içinde dolacak mı?
echo | openssl s_client -connect example.com:443 2>/dev/null 
  | openssl x509 -noout -checkend 2592000

Let’s Encrypt kullananlar için sertifika yenileme süreci:

# Let's Encrypt sertifikasını manuel yenile
certbot renew --cert-name example.com

# Dry-run ile test et (gerçekten yenilemeden simüle eder)
certbot renew --dry-run

# Belirli bir domain için force renewal
certbot certonly --force-renewal -d example.com -d www.example.com

# Yenileme sonrası nginx'i reload et
certbot renew --post-hook "systemctl reload nginx"

Otomatik yenileme için cron ayarı:

# /etc/cron.d/certbot dosyasına ekle
0 3 * * * root certbot renew --quiet --post-hook "systemctl reload nginx"

2. Güvenilmeyen Sertifika (Untrusted Certificate)

“SSL certificate problem: unable to get local issuer certificate” hatası genellikle iki nedenden kaynaklanır: ya ara CA sertifikaları (intermediate certificates) eksik, ya da sistem CA store’u güncel değil.

Sertifika zinciri kontrolü:

# Sertifika zincirini detaylı incele
openssl s_client -connect example.com:443 -showcerts 2>/dev/null 
  | grep -E "BEGIN CERTIFICATE|END CERTIFICATE|subject|issuer"

# Yerel sertifika dosyasının zincirini doğrula
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /path/to/cert.pem

# Ara sertifikayla birlikte doğrula
openssl verify -CAfile ca-bundle.crt -untrusted intermediate.pem server.pem

Nginx’te sertifika zinciri düzgün yapılandırılmamışsa şu şekilde düzeltebilirsiniz:

# Tam zincir dosyası oluştur (sunucu sertifikası + intermediate)
cat server.crt intermediate.crt > fullchain.pem

# Nginx konfigürasyonunda
# ssl_certificate /etc/ssl/certs/fullchain.pem;
# ssl_certificate_key /etc/ssl/private/server.key;

# Konfigürasyonu test et
nginx -t

# Reload
systemctl reload nginx

3. Alan Adı Uyuşmazlığı (Hostname Mismatch)

“SSL: certificate subject name ‘oldname.example.com’ does not match target host name ‘newname.example.com'” Bu hata özellikle server migration sonrası veya subdomain değişikliklerinde ortaya çıkar.

Teşhis:

# Sertifikanın hangi domain'ler için geçerli olduğunu gör
echo | openssl s_client -connect example.com:443 2>/dev/null 
  | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

# CN (Common Name) kontrolü
echo | openssl s_client -connect example.com:443 2>/dev/null 
  | openssl x509 -noout -subject

Eğer wildcard sertifika kullanıyorsanız, *.example.com sertifikası sub.sub.example.com için geçerli değildir. Bu sık yapılan bir hatadır.

4. SNI Sorunları

Bir IP’de birden fazla SSL sitesi barındırıyorsanız SNI kritik önem taşır. Eski istemciler veya yanlış yapılandırılmış ters proxy’ler SNI bilgisini göndermeyebilir.

# SNI ile ve SNI olmadan bağlantı karşılaştırması
# SNI ile:
openssl s_client -connect 192.168.1.100:443 -servername app.example.com 2>/dev/null 
  | openssl x509 -noout -subject

# SNI olmadan (IP ile):
openssl s_client -connect 192.168.1.100:443 2>/dev/null 
  | openssl x509 -noout -subject

# Eğer iki komut farklı sertifika döndürüyorsa SNI çalışıyor demektir
# Eğer aynı (ve yanlış) sertifikayı döndürüyorsa SNI yapılandırmasına bakın

Gerçek Dünya Senaryosu: Production’da Ani SSL Hatası

Sabah 08:30, monitoring sistemi alarm veriyor. Bir e-ticaret sitesinin ödeme sayfası SSL hatası fırlatıyor. Kullanıcılar ödeme yapamıyor. İşte bu durumda izlenecek adımlar:

Adım 1: Hızlı durum tespiti

# Önce bağlantının açık olup olmadığını kontrol et
curl -I https://payment.example.com

# SSL handshake detayını gör
openssl s_client -connect payment.example.com:443 -servername payment.example.com 
  < /dev/null 2>&1 | head -30

# Sunucu loglarını kontrol et
tail -f /var/log/nginx/error.log | grep -i ssl
journalctl -u nginx --since "1 hour ago" | grep -i ssl

Adım 2: Sertifika durumunu kontrol et

# Sertifika geçerlilik tarihi
echo | openssl s_client -connect payment.example.com:443 2>/dev/null 
  | openssl x509 -noout -dates

# Sertifika fingerprint'i (değişmiş mi?)
echo | openssl s_client -connect payment.example.com:443 2>/dev/null 
  | openssl x509 -noout -fingerprint -sha256

Adım 3: Load balancer veya CDN katmanını atla

# Direkt sunucu IP'sine bağlan (CDN veya LB bypass)
curl -H "Host: payment.example.com" https://10.0.1.50 -k -I

# Hangi sunucu yanıt veriyor?
openssl s_client -connect 10.0.1.50:443 -servername payment.example.com 2>/dev/null 
  | openssl x509 -noout -subject -dates

Böyle bir senaryoda genellikle suçlu ya süresi dolan bir sertifika, ya Let’s Encrypt’in otomatik yenileme cron’unun çalışmaması ya da CDN’de önbelleğe alınmış eski sertifikadır.

TLS Versiyon ve Cipher Suite Sorunları

Güvenlik güncellemeleri sonrası bazı eski TLS versiyonları devre dışı bırakılabilir. Bu durum eski istemcileri etkiler.

# Hangi TLS versiyonlarını desteklediğini test et
for version in ssl2 ssl3 tls1 tls1_1 tls1_2 tls1_3; do
  echo -n "$version: "
  result=$(echo | openssl s_client -connect example.com:443 
    -$version 2>&1 | grep -E "CONNECTED|handshake failure|wrong version")
  echo $result
done

# Desteklenen cipher suite'leri listele
nmap --script ssl-enum-ciphers -p 443 example.com

# Belirli bir cipher ile bağlanmayı test et
openssl s_client -connect example.com:443 
  -cipher "ECDHE-RSA-AES256-GCM-SHA384" -servername example.com

Nginx’te TLS konfigürasyonu şu şekilde olmalı:

# /etc/nginx/conf.d/ssl.conf veya site konfigürasyonunda
# Güvenli TLS konfigürasyonu örneği
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...
# ssl_prefer_server_ciphers off;

# Konfigürasyonun aktif cipher suite'lerini görmek için
nginx -T | grep ssl_ciphers

# Apache için aktif SSL ayarlarını listele
apache2ctl -M | grep ssl

Sertifika İzleme ve Uyarı Sistemi Kurma

Reaktif olmak yerine proaktif olmak bu işin özü. Sertifika süresi dolmadan uyarı sistemi kurmak şart.

#!/bin/bash
# ssl_check.sh - Sertifika sona erme kontrolü

DOMAINS=("example.com" "api.example.com" "payment.example.com")
WARN_DAYS=30
ALERT_EMAIL="[email protected]"

for domain in "${DOMAINS[@]}"; do
  expiry=$(echo | openssl s_client -connect ${domain}:443 
    -servername ${domain} 2>/dev/null 
    | openssl x509 -noout -enddate 2>/dev/null 
    | cut -d= -f2)

  expiry_epoch=$(date -d "${expiry}" +%s)
  now_epoch=$(date +%s)
  days_left=$(( (expiry_epoch - now_epoch) / 86400 ))

  if [ ${days_left} -lt ${WARN_DAYS} ]; then
    echo "UYARI: ${domain} sertifikası ${days_left} gün sonra doluyor!" 
      | mail -s "SSL Sertifika Uyarısı: ${domain}" ${ALERT_EMAIL}
    echo "WARN: ${domain} - ${days_left} gün kaldı"
  else
    echo "OK: ${domain} - ${days_left} gün kaldı"
  fi
done

Bu scripti cron’a ekleyin:

# Her gün sabah 07:00'de çalıştır
0 7 * * * /usr/local/bin/ssl_check.sh >> /var/log/ssl_check.log 2>&1

Özel CA (Internal CA) Ortamında Sorunlar

Kurumsal ortamlarda özel CA kullanımı yaygındır. Bu durumda dışarıdan gelen uygulamalar veya yeni kurulan sunucular iç sertifikaları tanımayabilir.

# Özel CA sertifikasını sisteme ekle (Ubuntu/Debian)
cp internal-ca.crt /usr/local/share/ca-certificates/
update-ca-certificates

# Red Hat/CentOS için
cp internal-ca.crt /etc/pki/ca-trust/source/anchors/
update-ca-trust

# CA'nın sisteme eklenip eklenmediğini doğrula
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt internal-server.crt

# Hangi CA'ların yüklü olduğunu listele
awk -v cmd='openssl x509 -noout -subject' 
  '/BEGIN CERT/{close(cmd)};{print | cmd}' 
  /etc/ssl/certs/ca-certificates.crt 2>/dev/null | head -20

Python veya Java uygulamaları kendi certificate store’larını kullandığı için sistem store’una ekleme her zaman yetmeyebilir:

# Java keystore'una CA ekle
keytool -import -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts 
  -storepass changeit -noprompt 
  -alias "internal-ca" -file internal-ca.crt

# Python requests kütüphanesi için
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
# veya uygulama içinde:
# requests.get('https://...', verify='/path/to/ca-bundle.crt')

Hata Mesajları Sözlüğü

Karşılaşılan hata mesajlarını anlamak teşhis sürecini hızlandırır:

  • SSL_ERROR_RX_RECORD_TOO_LONG: Genellikle HTTP portuna (80) HTTPS bağlantısı yapmaya çalışmak. Port konfigürasyonunu kontrol edin.
  • certificate verify failed (unable to get local issuer certificate): Ara CA sertifikaları eksik veya sistem CA store’u güncel değil.
  • certificate has expired: Sertifika süresi dolmuş, hemen yenileme gerekiyor.
  • hostname mismatch: Sertifika farklı bir domain için düzenlenmiş. SAN (Subject Alternative Name) alanını kontrol edin.
  • handshake failure: TLS versiyonu veya cipher suite uyumsuzluğu. Her iki tarafın desteklediği ortak nokta bulunamıyor.
  • self signed certificate: Kendi kendine imzalanmış sertifika, CA tarafından doğrulanmamış. Test ortamları için normal ama production için kabul edilemez.
  • OCSP stapling error: OCSP responder’a ulaşılamıyor. Nginx konfigürasyonunda ssl_stapling ayarını gözden geçirin.
  • no shared cipher: Sunucu ve istemci arasında ortak cipher suite yok. Cipher listesini genişletmeniz gerekebilir.

Reverse Proxy Arkasındaki SSL Sorunları

HAProxy, Nginx veya Traefik gibi reverse proxy kullanıyorsanız SSL terminasyonu konusunda dikkatli olmanız gerekir.

# HAProxy SSL durumunu kontrol et
echo "show info" | socat stdio /var/run/haproxy/admin.sock | grep -i ssl

# Nginx'in SSL oturumlarını istatistiksel olarak gör
nginx -T | grep -E "ssl_|listen.*ssl"

# Traefik'te sertifika durumunu API üzerinden kontrol et
curl http://localhost:8080/api/rawdata | python3 -m json.tool | grep -A5 "tls"

# Backend'e SSL geçip geçmediğini kontrol et
# Nginx'te upstream SSL
# proxy_pass https://backend;
# proxy_ssl_verify on;
# proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;

Reverse proxy’nin backend’e HTTP mi HTTPS mi bağlandığı da kritik. Bazı durumlarda proxy’nin kendi sertifikası geçerli olsa bile backend bağlantısında sorun yaşanabilir.

Sonuç

SSL sertifika sorunları kaçınılmaz. Önemli olan bu sorunları hızlı teşhis edip çözebilmek ve tekrar yaşanmasını önlemek. Bu yazıda anlattıklarından hareketle birkaç pratik öneri:

  • Sertifika envanteri tutun: Hangi sunucuda hangi sertifika var, ne zaman doluyor? Bunu bir spreadsheet’te bile olsa kayıt altına alın.
  • Otomatik izleme kurun: Paylaştığım bash scripti veya Prometheus blackbox exporter gibi araçlarla sertifika sürelerini izleyin.
  • Let’s Encrypt’i tercih edin: 90 günlük ömrü kısa gibi görünse de otomatik yenileme ile bu bir avantaja dönüşür, sizi disiplinli tutar.
  • Sertifika zincirini her zaman tam gönderin: En çok karşılaşılan hataların başında ara CA sertifikalarının eksikliği gelir.
  • Staging’de test edin: Production’da ilk kez sertifika konfigürasyonu denemek yerine staging ortamında doğrulayın.
  • Hata mesajlarını okuyun: openssl s_client çıktısı size doğrudan ne olduğunu söyler. Loglara bakmadan atlamayın.

Bir SSL hatası aldığınızda önce openssl s_client ile bağlanın, Verify return code değerine bakın, sertifika tarihlerini kontrol edin, zinciri doğrulayın. Bu adımları sistematik olarak izlerseniz çoğu sorunu 5 dakika içinde teşhis edebilirsiniz.

Benzer Konular

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir