Wildcard SSL Sertifikası Nedir ve Nasıl Kurulur?

Bir web altyapısı yönetiyorsunuz ve onlarca subdomain’iniz var: app.sirket.com, api.sirket.com, mail.sirket.com, dev.sirket.com… Her biri için ayrı SSL sertifikası almak hem pahalı hem de yönetimi kabusa çeviren bir süreç. İşte tam bu noktada wildcard SSL sertifikaları hayat kurtarıcı oluyor. Tek bir sertifika ile bir domain’in tüm alt domainlerini kapsayabiliyorsunuz. Bu yazıda wildcard SSL’i derinlemesine inceleyecek, Let’s Encrypt ile ücretsiz nasıl alabileceğinizi ve production ortamında nasıl kuracağınızı adım adım göstereceğim.

Wildcard SSL Sertifikası Nedir?

Standart bir SSL sertifikası yalnızca belirtilen domain için geçerlidir. sirket.com için aldığınız sertifika www.sirket.com için de çalışabilir ama api.sirket.com için artık geçersiz sayılır. Wildcard sertifikaları ise *.sirket.com şeklinde tanımlanarak o domain’in bir seviye altındaki tüm subdomain’leri kapsar.

Önemli bir nokta: Wildcard sertifikası yalnızca bir seviye derinliği kapsar. Yani *.sirket.com sertifikası şunları kapsar:

  • app.sirket.com
  • api.sirket.com
  • mail.sirket.com
  • dev.sirket.com
  • staging.sirket.com

Ama şunları kapsamaz:

  • sirket.com (apex domain, ayrıca eklenmelidir)
  • v2.api.sirket.com (iki seviye derinlik)
  • test.app.sirket.com (iki seviye derinlik)

Bu sınırlamayı göz önünde bulundurarak altyapınızı planlamanız gerekiyor. Eğer iç içe subdomain yapınız varsa, o seviye için ayrı bir wildcard sertifikası (*.api.sirket.com gibi) almanız gerekecek.

Let’s Encrypt ile Ücretsiz Wildcard Sertifika

Let’s Encrypt, 2018’den itibaren wildcard sertifikalarını destekliyor. Ancak standart HTTP doğrulaması (HTTP-01 challenge) wildcard için çalışmıyor. Bunun yerine DNS-01 challenge kullanmanız zorunlu.

DNS-01 challenge mantığı şu şekilde: Sertifika otoritesi size bir token veriyor, siz bu token’ı DNS TXT kaydı olarak ekliyorsunuz, CA da DNS’i sorgulayarak domain sahibi olduğunuzu doğruluyor.

Certbot Kurulumu

Ubuntu/Debian sistemlerde:

sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflare -y

# Versiyonu kontrol et
certbot --version

CentOS/RHEL sistemlerde:

sudo dnf install epel-release -y
sudo dnf install certbot python3-certbot-dns-cloudflare -y

Manuel DNS Doğrulama ile Wildcard Sertifika Alma

DNS sağlayıcınızın Certbot plugin’i yoksa manuel yöntemi kullanabilirsiniz. Bu yöntem otomatik yenileme için uygun değil ama kavramı anlamak için mükemmel:

sudo certbot certonly 
  --manual 
  --preferred-challenges dns 
  -d "sirket.com" 
  -d "*.sirket.com"

Bu komutu çalıştırdığınızda Certbot size şöyle bir çıktı verecek:

Please deploy a DNS TXT record under the name:
_acme-challenge.sirket.com
with the following value:
xK3mN9pQ2rT5vW8yB1cE4hJ7nM0sR3uV6wA9bD2fG5iL

DNS paneline gidip bu TXT kaydını ekliyorsunuz, sonra Enter’a basıyorsunuz. Birkaç dakika beklemek gerekebilir çünkü DNS propagasyonu zaman alıyor.

Cloudflare DNS Plugin ile Otomatik Wildcard Sertifika

Production ortamı için otomatik yenileme şart. Cloudflare kullanıyorsanız bu işi çok temiz yapabilirsiniz:

# Cloudflare API token için credentials dosyası oluştur
sudo mkdir -p /etc/letsencrypt/cloudflare
sudo nano /etc/letsencrypt/cloudflare/credentials.ini

Dosya içeriği:

# Cloudflare API token (önerilen yöntem)
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN_HERE

Güvenlik için dosya izinlerini kısıtlayın:

sudo chmod 600 /etc/letsencrypt/cloudflare/credentials.ini
sudo chown root:root /etc/letsencrypt/cloudflare/credentials.ini

Şimdi sertifikayı alın:

sudo certbot certonly 
  --dns-cloudflare 
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini 
  --dns-cloudflare-propagation-seconds 30 
  -d "sirket.com" 
  -d "*.sirket.com" 
  --email [email protected] 
  --agree-tos 
  --non-interactive

Başarılı bir çıktı şöyle görünür:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/sirket.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/sirket.com/privkey.pem
This certificate expires on 2024-06-15.
These files will be updated when the certificate renews.

Nginx’te Wildcard SSL Yapılandırması

Sertifikayı aldıktan sonra web sunucunuza entegre etmeniz gerekiyor. Gerçek hayatta sıkça gördüğüm senaryo şu: Birden fazla subdomain farklı backend servislere proxy geçiyor.

Temel Nginx SSL Bloğu

sudo nano /etc/nginx/conf.d/sirket.com.conf
# HTTP'den HTTPS'e yönlendirme
server {
    listen 80;
    server_name sirket.com *.sirket.com;
    return 301 https://$host$request_uri;
}

# Ana domain
server {
    listen 443 ssl http2;
    server_name sirket.com;

    ssl_certificate /etc/letsencrypt/live/sirket.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sirket.com/privkey.pem;

    # Modern TLS ayarları
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_stapling on;
    ssl_stapling_verify on;

    # HSTS başlığı
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    root /var/www/sirket.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

# API subdomain - Node.js backend'e proxy
server {
    listen 443 ssl http2;
    server_name api.sirket.com;

    ssl_certificate /etc/letsencrypt/live/sirket.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sirket.com/privkey.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

Yapılandırmayı test edip yükleyin:

sudo nginx -t
sudo systemctl reload nginx

Wildcard Subdomain ile Dinamik Proxy

Daha gelişmiş bir senaryo: Subdomain adına göre otomatik routing yapan bir yapı. Örneğin bir SaaS ürününde her müşterinin kendi subdomaini var.

# Dinamik subdomain routing
server {
    listen 443 ssl http2;
    server_name ~^(?P<tenant>[^.]+).sirket.com$;

    ssl_certificate /etc/letsencrypt/live/sirket.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sirket.com/privkey.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header X-Tenant-ID $tenant;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Bu yapıda musteri1.sirket.com ve musteri2.sirket.com gibi tüm subdomain’ler aynı backend’e gidiyor, ama X-Tenant-ID header’ı sayesinde backend hangi müşteriyle konuştuğunu biliyor.

Apache’de Wildcard SSL Yapılandırması

Apache kullanan sistemler için de temel yapılandırmayı görelim:

sudo nano /etc/apache2/sites-available/sirket.com-ssl.conf
<VirtualHost *:80>
    ServerName sirket.com
    ServerAlias *.sirket.com
    Redirect permanent / https://sirket.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName sirket.com
    DocumentRoot /var/www/sirket.com

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/sirket.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/sirket.com/privkey.pem

    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    SSLHonorCipherOrder off
    SSLSessionTickets off

    Header always set Strict-Transport-Security "max-age=63072000"
</VirtualHost>

<VirtualHost *:443>
    ServerName api.sirket.com

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/sirket.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/sirket.com/privkey.pem

    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/
</VirtualHost>
sudo a2enmod ssl headers proxy proxy_http
sudo a2ensite sirket.com-ssl.conf
sudo apache2ctl configtest
sudo systemctl reload apache2

Otomatik Yenileme Kurulumu

Let’s Encrypt sertifikaları 90 günde bir yenilenmesi gerekiyor. Bunu otomatik hale getirmek için systemd timer veya cron kullanabilirsiniz.

Systemd Timer ile Otomatik Yenileme

Modern Linux sistemlerde certbot kurulumu zaten bir systemd timer ekliyor. Durumunu kontrol edin:

sudo systemctl status certbot.timer
sudo systemctl list-timers | grep certbot

Timer aktif değilse etkinleştirin:

sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

Yenileme sonrası nginx’i otomatik reload etmek için hook ekleyin:

sudo nano /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
#!/bin/bash
# Sertifika yenilendikten sonra nginx'i yeniden yükle
systemctl reload nginx
echo "$(date): Nginx reloaded after certificate renewal" >> /var/log/certbot-renewal.log
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh

Yenileme Testini Yapın

# Dry-run ile test et (gerçekten yenilemez, sadece simüle eder)
sudo certbot renew --dry-run

# Çıktıyı kontrol et
sudo certbot certificates

Sertifika Doğrulama ve Test

Kurulumun doğru çalıştığını birkaç farklı şekilde kontrol edebilirsiniz.

Komut Satırından Test

# Temel SSL bağlantı testi
openssl s_client -connect sirket.com:443 -servername sirket.com

# Sertifika bilgilerini görüntüle
echo | openssl s_client -connect sirket.com:443 -servername sirket.com 2>/dev/null | openssl x509 -noout -text | grep -E "Subject|DNS:|Not Before|Not After"

# Wildcard'ın subdomain için geçerli olduğunu test et
echo | openssl s_client -connect api.sirket.com:443 -servername api.sirket.com 2>/dev/null | openssl x509 -noout -subject -dates

# TLS versiyonunu kontrol et
openssl s_client -connect sirket.com:443 -tls1_2
openssl s_client -connect sirket.com:443 -tls1_3

SSL Labs ile Kapsamlı Test

Production’a almadan önce Qualys SSL Labs üzerinden test yapmanızı şiddetle öneririm. A+ rating almak için şu kontrolleri yapın:

# HSTS başlığını kontrol et
curl -sI https://sirket.com | grep -i strict

# Sertifika zincirini doğrula
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /etc/letsencrypt/live/sirket.com/fullchain.pem

# Sertifika son kullanma tarihini izle
echo | openssl s_client -connect sirket.com:443 2>/dev/null | openssl x509 -noout -enddate

Yaygın Sorunlar ve Çözümleri

DNS Propagasyon Sorunu

En sık karşılaşılan sorun, DNS TXT kaydı henüz yayılmadan doğrulama girişiminde bulunmak. Cloudflare plugin kullanıyorsanız --dns-cloudflare-propagation-seconds değerini 60’a çıkarabilirsiniz:

sudo certbot certonly 
  --dns-cloudflare 
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini 
  --dns-cloudflare-propagation-seconds 60 
  -d "sirket.com" 
  -d "*.sirket.com"

Rate Limit Sorunu

Let’s Encrypt’in haftalık rate limitleri var. Test sürecinde aynı domain için çok fazla deneme yaptıysanız bir hafta beklemeniz gerekebilir. Bu yüzden geliştirme ve test aşamasında her zaman --staging parametresini kullanın:

sudo certbot certonly 
  --dns-cloudflare 
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini 
  -d "sirket.com" 
  -d "*.sirket.com" 
  --staging

Sertifika Dosyası İzin Sorunları

Nginx veya Apache’nin sertifika dosyalarına erişememesi durumunda:

# Dosya izinlerini kontrol et
ls -la /etc/letsencrypt/live/sirket.com/
ls -la /etc/letsencrypt/archive/sirket.com/

# Archive dizini için gerekli izinler
sudo chmod 755 /etc/letsencrypt/live/
sudo chmod 755 /etc/letsencrypt/archive/
sudo chmod 644 /etc/letsencrypt/archive/sirket.com/fullchain*.pem
sudo chmod 600 /etc/letsencrypt/archive/sirket.com/privkey*.pem

Ticari Wildcard Sertifika Kullanımı

Let’s Encrypt her senaryoda uygun olmayabilir. Özellikle organizasyonel doğrulama (OV) veya genişletilmiş doğrulama (EV) gerektiren durumlarda ticari sertifika satın almanız gerekir. Bu durumda CSR (Certificate Signing Request) oluşturmanız gerekiyor:

# Private key oluştur
openssl genrsa -out sirket.com.key 4096

# Wildcard için CSR oluştur
openssl req -new 
  -key sirket.com.key 
  -out sirket.com.csr 
  -subj "/C=TR/ST=Istanbul/L=Istanbul/O=Sirket AS/OU=IT/CN=*.sirket.com"

# CSR içeriğini kontrol et
openssl req -text -noout -verify -in sirket.com.csr

# CSR içeriğini kopyalamak için
cat sirket.com.csr

Bu CSR dosyasının içeriğini sertifika sağlayıcınızın paneline yapıştırıyorsunuz. Sağlayıcı size sertifika dosyalarını gönderdikten sonra Nginx/Apache yapılandırmanıza ekliyorsunuz.

Sertifika İzleme ve Uyarı Sistemi

Production ortamında sertifika son kullanma tarihlerini izlemek kritik. Basit bir script ile bunu otomatize edebilirsiniz:

sudo nano /usr/local/bin/ssl-check.sh
#!/bin/bash
# SSL sertifika son kullanma tarihi kontrolü
# Cron ile günlük çalıştırın: 0 9 * * * /usr/local/bin/ssl-check.sh

DOMAINS=("sirket.com" "api.sirket.com" "app.sirket.com")
ALERT_DAYS=30
EMAIL="[email protected]"
LOG="/var/log/ssl-check.log"

echo "$(date): SSL check started" >> $LOG

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)
    
    if [ -z "$expiry" ]; then
        echo "$(date): WARNING - Could not check ${domain}" >> $LOG
        continue
    fi
    
    expiry_epoch=$(date -d "$expiry" +%s)
    current_epoch=$(date +%s)
    days_left=$(( (expiry_epoch - current_epoch) / 86400 ))
    
    echo "$(date): ${domain} expires in ${days_left} days" >> $LOG
    
    if [ $days_left -lt $ALERT_DAYS ]; then
        echo "UYARI: ${domain} sertifikası ${days_left} gün sonra sona eriyor!" | 
        mail -s "SSL Sertifika Uyarisi: ${domain}" $EMAIL
        echo "$(date): Alert sent for ${domain}" >> $LOG
    fi
done

echo "$(date): SSL check completed" >> $LOG
sudo chmod +x /usr/local/bin/ssl-check.sh

# Cron'a ekle
echo "0 9 * * * root /usr/local/bin/ssl-check.sh" | sudo tee /etc/cron.d/ssl-check

Sonuç

Wildcard SSL sertifikaları, birden fazla subdomain yöneten herkes için vazgeçilmez bir araç. Let’s Encrypt ile bu işi sıfır maliyetle, Cloudflare gibi DNS provider’ların API’leri sayesinde de tamamen otomatize edilmiş şekilde yapabiliyorsunuz.

Özetlemek gerekirse dikkat etmeniz gereken kritik noktalar şunlar:

  • Wildcard sertifikası yalnızca bir seviye alt domain kapsar, derin hiyerarşiler için ayrı sertifika gerekir
  • DNS-01 challenge wildcard için zorunludur, HTTP-01 çalışmaz
  • Otomatik yenileme hook’larını mutlaka kurun, unutulmuş sertifika production’da büyük sorun demek
  • Staging ortamında test ederek rate limit’e takılmaktan kaçının
  • Sertifika izleme scriptleri ile erken uyarı sistemi kurun

Altyapınızda onlarca subdomain yönetiyorsanız wildcard sertifika hem operasyonel yükü azaltıyor hem de tutarlı bir güvenlik yapısı sunuyor. Özellikle SaaS ürünleri veya çok kiracılı mimariler için bu yapı neredeyse olmazsa olmaz hale geliyor.

Yorum yapın