Cloudflare ile Otomatik HTTPS Yönlendirme Nasıl Yapılır?

Cloudflare kullanan bir sistem yöneticisi olarak en sık aldığım sorulardan biri şu: “Site HTTP’de açılıyor, HTTPS’e nasıl yönlendiririm?” Kulağa basit geliyor, ama yanlış yapıldığında sonsuz yönlendirme döngüleri, kırık sayfalar ve SEO kayıpları yaşanabiliyor. Bu yazıda Cloudflare üzerinden otomatik HTTPS yönlendirmeyi tüm detaylarıyla ele alacağım; hem Cloudflare arayüzünden hem de API üzerinden, hem de sunucu tarafında yapılması gerekenleri konuşacağız.

HTTPS Yönlendirme Neden Önemli?

2023 itibarıyla Google, HTTP üzerinden erişilen siteleri arama sonuçlarında geri sıralıyor. Tarayıcılar “Güvenli Değil” uyarısı gösteriyor. Kullanıcılar siteyi terk ediyor. Bunların hepsi bilinen şeyler. Ama sysadmin perspektifinden bakınca asıl mesele şu: HTTPS yönlendirmeyi nerede yapacağınız kritik.

Üç farklı katmanda HTTPS yönlendirmesi yapılabilir:

  • Cloudflare katmanı: En hızlı ve en kolay yol. Sunucuya istek gitmeden Cloudflare edge’de yönlendirme yapılır.
  • Web sunucusu katmanı: Nginx veya Apache seviyesinde 301/302 yönlendirmesi.
  • Uygulama katmanı: PHP, Node.js, Django gibi uygulama kodunda yapılan yönlendirme.

İdeal dünyada her üç katmanı da doğru yapılandırırsınız. Ama gerçek hayatta bazen sadece Cloudflare’i kontrol edebilirsiniz, bazen sadece sunucuyu. Bu yazıda tüm senaryoları işleyeceğiz.

Cloudflare SSL/TLS Modu Seçimi

HTTPS yönlendirmesine geçmeden önce SSL/TLS modunun doğru ayarlandığından emin olmanız gerekiyor. Bu adımı atlayan çoğu sysadmin sonradan sonsuz yönlendirme döngüsüyle karşılaşıyor.

Cloudflare kontrol panelinde SSL/TLS > Overview bölümüne gidin. Dört mod var:

  • Off: HTTPS hiç yok. Kullanmayın.
  • Flexible: Ziyaretçi ile Cloudflare arası HTTPS, Cloudflare ile sunucu arası HTTP. Geçici çözüm, production’da kullanmayın.
  • Full: Cloudflare ile sunucu arasında da HTTPS var, ama sertifika doğrulanmıyor. Self-signed sertifika yeterli.
  • Full (Strict): Sertifika geçerli ve doğrulanmış olmalı. Tavsiye edilen mod bu.

Flexible modunun tehlikesi şudur: Sunucunuzda da HTTPS yönlendirmesi varsa, Cloudflare HTTP ile sunucuya bağlanır, sunucu HTTPS’e yönlendirir, Cloudflare tekrar HTTP ile bağlanır… Sonsuz döngü. Bunu yaşadıysanız ilk bakacağınız yer burasıdır.

# Mevcut SSL modunu Cloudflare API ile kontrol etmek
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/ssl" 
  -H "Authorization: Bearer API_TOKEN" 
  -H "Content-Type: application/json"
# SSL modunu Full Strict olarak ayarlamak
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/ssl" 
  -H "Authorization: Bearer API_TOKEN" 
  -H "Content-Type: application/json" 
  --data '{"value":"full_strict"}'

Zone ID’nizi Cloudflare kontrol panelinde sağ alt köşede, API Token’ı ise My Profile > API Tokens altında oluşturabilirsiniz.

Cloudflare Üzerinden Otomatik HTTPS Yönlendirme

Always Use HTTPS Özelliği

En basit yöntem bu. Cloudflare kontrol panelinde SSL/TLS > Edge Certificates bölümüne gidin. “Always Use HTTPS” toggle’ını açın. Bu kadar.

Bu özelliği açtığınızda Cloudflare, HTTP’ye gelen tüm istekleri otomatik olarak HTTPS’e 301 yönlendirmesiyle gönderir. Edge seviyesinde çalıştığı için sunucunuza ekstra yük bindirmez.

API üzerinden aynı işlemi yapmak için:

# Always Use HTTPS özelliğini etkinleştirme
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/always_use_https" 
  -H "Authorization: Bearer API_TOKEN" 
  -H "Content-Type: application/json" 
  --data '{"value":"on"}'
# Mevcut durumu kontrol etme
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/always_use_https" 
  -H "Authorization: Bearer API_TOKEN" 
  -H "Content-Type: application/json"

Yanıt olarak şöyle bir JSON dönmeli:

{
  "result": {
    "id": "always_use_https",
    "value": "on",
    "modified_on": "2024-01-15T10:30:00.000000Z",
    "editable": true
  },
  "success": true
}

HSTS (HTTP Strict Transport Security) Ayarı

Always Use HTTPS tek başına yeterli değil. Tarayıcının her seferinde Cloudflare’e HTTP isteği atıp yönlendirme beklemesi yerine, HSTS başlığı sayesinde tarayıcı direkt HTTPS’e gider. Bu hem güvenlik hem de performans açısından kritik.

Cloudflare’de SSL/TLS > Edge Certificates > HTTP Strict Transport Security (HSTS) bölümünden HSTS’yi etkinleştirebilirsiniz. Ayarlar:

  • Max Age: Ne kadar süre HTTPS kullanılacağını belirtir. Başlangıç için 6 ay (15768000 saniye) öneririm. Sonra 1 yıla çıkarabilirsiniz.
  • Include Subdomains: Tüm alt alan adlarını kapsasın mı? Dikkatli kullanın, tüm subdomain’lerde HTTPS olduğundan emin olun.
  • Preload: Tarayıcının HSTS preload listesine girmek için. Geri alınması çok zor, acele etmeyin.
  • No-Sniff: X-Content-Type-Options başlığını ekler.
# HSTS ayarını API ile yapılandırma
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/security_header" 
  -H "Authorization: Bearer API_TOKEN" 
  -H "Content-Type: application/json" 
  --data '{
    "value": {
      "strict_transport_security": {
        "enabled": true,
        "max_age": 15768000,
        "include_subdomains": true,
        "nosniff": true
      }
    }
  }'

Page Rules ile Gelişmiş Yönlendirme

Bazı durumlarda tüm siteniz için değil, belirli URL’ler için HTTPS yönlendirmesi yapmanız gerekebilir. Ya da HTTP’den HTTPS’e yönlendirirken URL yapısını değiştirmek isteyebilirsiniz. İşte burada Cloudflare Page Rules devreye giriyor.

SSL/TLS > Page Rules bölümünden yeni kural oluşturun. Ücretsiz planda 3 Page Rule hakkınız var.

Örnek senaryo: http://example.com/* adresine gelen her isteği https://example.com/$1 adresine yönlendirmek için:

  • URL Pattern: http://example.com/*
  • Setting: Always Use HTTPS

Daha gelişmiş senaryo, www’suz adresi hem HTTPS’e hem de www’lu versiyona yönlendirmek:

# Page Rule oluşturma - HTTP'yi HTTPS'e yönlendirme
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/pagerules" 
  -H "Authorization: Bearer API_TOKEN" 
  -H "Content-Type: application/json" 
  --data '{
    "targets": [
      {
        "target": "url",
        "constraint": {
          "operator": "matches",
          "value": "http://example.com/*"
        }
      }
    ],
    "actions": [
      {
        "id": "always_use_https"
      }
    ],
    "priority": 1,
    "status": "active"
  }'

Cloudflare Rules (Yeni Nesil Kural Motoru)

Page Rules artık yavaş yavaş Cloudflare Rules’a geçiyor. Yeni projelerde doğrudan Rules kullanmanızı öneririm. Rules > Redirect Rules bölümünden yeni kural oluşturabilirsiniz.

# Cloudflare Ruleset API ile HTTPS yönlendirmesi
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/rulesets" 
  -H "Authorization: Bearer API_TOKEN" 
  -H "Content-Type: application/json" 
  --data '{
    "name": "HTTP to HTTPS Redirect",
    "kind": "zone",
    "phase": "http_request_dynamic_redirect",
    "rules": [
      {
        "expression": "http.request.uri.scheme eq "http"",
        "action": "redirect",
        "action_parameters": {
          "from_value": {
            "status_code": 301,
            "target_url": {
              "expression": "concat("https://", http.request.full_uri)"
            },
            "preserve_query_string": true
          }
        },
        "description": "Redirect HTTP to HTTPS"
      }
    ]
  }'

Sunucu Tarafında HTTPS Yönlendirmesi

Cloudflare’i bypass eden veya doğrudan sunucu IP’sine ulaşan istekler için sunucu tarafında da yönlendirme yapmanız gerekiyor. Bu “defense in depth” yaklaşımının bir parçası.

Nginx Konfigürasyonu

# /etc/nginx/sites-available/example.com
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    
    # Cloudflare IP'lerinden gelen isteklerde CF-Visitor başlığını kontrol et
    # Diğer durumlarda direkt HTTPS'e yönlendir
    if ($http_cf_visitor ~* '"scheme":"http"') {
        return 301 https://$host$request_uri;
    }
    
    # Doğrudan HTTP isteği gelirse yönlendir
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    ssl_certificate /etc/ssl/cloudflare/cert.pem;
    ssl_certificate_key /etc/ssl/cloudflare/key.pem;
    
    # HSTS başlığı (Cloudflare zaten ekliyor ama ekstra güvenlik için)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    root /var/www/example.com;
    index index.html index.php;
}

Apache Konfigürasyonu

# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    
    # Cloudflare üzerinden gelen HTTP isteklerini yönlendir
    RewriteEngine On
    RewriteCond %{HTTP:X-Forwarded-Proto} =http
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
    # Doğrudan HTTP isteği
    RewriteCond %{HTTP:X-Forwarded-Proto} =""
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    
    SSLEngine on
    SSLCertificateFile /etc/ssl/cloudflare/cert.pem
    SSLCertificateKeyFile /etc/ssl/cloudflare/key.pem
    
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    
    DocumentRoot /var/www/example.com
</VirtualHost>

Gerçek Dünya Senaryoları ve Sorun Giderme

Senaryo 1: Sonsuz Yönlendirme Döngüsü

Bir müşterinin sitesini Cloudflare’e taşırken klasik hatayı yaşadık. Cloudflare SSL modu Flexible, Nginx’te de HTTP’den HTTPS’e yönlendirme vardı. Tarayıcı “ERR_TOO_MANY_REDIRECTS” hatası veriyordu.

Çözüm:

# Önce Cloudflare SSL modunu kontrol et
curl -sI http://example.com | grep -i location

# Flexible moddan Full'a geç
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/ssl" 
  -H "Authorization: Bearer TOKEN" 
  -H "Content-Type: application/json" 
  --data '{"value":"full"}'

Ya da Nginx tarafında Cloudflare’den gelen istekleri tanımlayıp sadece doğrudan HTTP isteklerini yönlendirin. Cloudflare IP aralıklarını /etc/nginx/cloudflare_ips.conf dosyasına koyun:

# Cloudflare IP listesini çekme scripti
#!/bin/bash
CLOUDFLARE_IPS_V4=$(curl -s https://www.cloudflare.com/ips-v4)
CLOUDFLARE_IPS_V6=$(curl -s https://www.cloudflare.com/ips-v6)

echo "# Cloudflare IPv4" > /etc/nginx/cloudflare_ips.conf
for ip in $CLOUDFLARE_IPS_V4; do
    echo "set_real_ip_from $ip;" >> /etc/nginx/cloudflare_ips.conf
done

echo "# Cloudflare IPv6" >> /etc/nginx/cloudflare_ips.conf
for ip in $CLOUDFLARE_IPS_V6; do
    echo "set_real_ip_from $ip;" >> /etc/nginx/cloudflare_ips.conf
done

echo "real_ip_header CF-Connecting-IP;" >> /etc/nginx/cloudflare_ips.conf

nginx -t && systemctl reload nginx
echo "Cloudflare IP listesi güncellendi"

Bu scripti crontab’a ekleyerek haftalık güncelleyebilirsiniz:

# Crontab'a ekle
0 0 * * 0 /usr/local/bin/update_cloudflare_ips.sh >> /var/log/cloudflare_ips.log 2>&1

Senaryo 2: Subdomain’lerde HTTPS Sorunları

Ana domain’de HTTPS çalışıyor ama api.example.com veya staging.example.com gibi subdomain’lerde sorun yaşanıyor. DNS kayıtlarını kontrol edin:

# DNS propagasyonunu kontrol etme
dig api.example.com +short
nslookup api.example.com 1.1.1.1

# Cloudflare proxy durumunu kontrol etme (orange cloud)
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records?name=api.example.com" 
  -H "Authorization: Bearer TOKEN" 
  -H "Content-Type: application/json" | python3 -m json.tool | grep -A2 '"proxied"'

Subdomain için Cloudflare proxy (orange cloud) kapalıysa, HTTPS yönlendirmesi Cloudflare tarafından yapılmaz. Ya proxy’yi açın ya da sunucu tarafında yönlendirmeyi yapılandırın.

Senaryo 3: Mixed Content Sorunları

HTTPS’e geçtiniz ama sayfada hala HTTP kaynaklara (resim, CSS, JS) referans var. Tarayıcı mixed content uyarısı veriyor.

Cloudflare’in Automatic HTTPS Rewrites özelliği bu sorunu çözüyor:

# Automatic HTTPS Rewrites etkinleştirme
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/automatic_https_rewrites" 
  -H "Authorization: Bearer TOKEN" 
  -H "Content-Type: application/json" 
  --data '{"value":"on"}'

Bu özellik, HTML içindeki HTTP referanslarını otomatik olarak HTTPS’e çeviriyor. Ancak inline JavaScript ile dinamik olarak oluşturulan URL’ler için çalışmıyor, onları kod tarafında düzeltmeniz gerekiyor.

Cloudflare Origin Sertifikası Kurulumu

Full Strict modu için sunucunuzda geçerli bir sertifika olması gerekiyor. Let’s Encrypt kullanabilirsiniz ama Cloudflare’in kendi Origin Certificate’i daha pratik. 15 yıla kadar geçerli, yenileme derdi yok.

Cloudflare SSL/TLS > Origin Server > Create Certificate bölümünden sertifika oluşturun. Sonra sunucuya yükleyin:

# Sertifika dosyalarını oluştur
mkdir -p /etc/ssl/cloudflare
chmod 700 /etc/ssl/cloudflare

# Cloudflare'den kopyaladığınız sertifikayı kaydedin
nano /etc/ssl/cloudflare/cert.pem
nano /etc/ssl/cloudflare/key.pem

chmod 600 /etc/ssl/cloudflare/key.pem
chmod 644 /etc/ssl/cloudflare/cert.pem

# Nginx ile test
nginx -t
systemctl reload nginx

# SSL bağlantısını doğrula
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | 
  openssl x509 -noout -subject -dates

Yönlendirme Doğrulama ve Monitoring

Kurulumu tamamladıktan sonra her şeyin doğru çalıştığından emin olun:

# HTTP'den HTTPS'e yönlendirme kontrolü
curl -sI http://example.com | head -5

# www'suz ve www'lu adresleri test et
for url in "http://example.com" "http://www.example.com" "https://www.example.com"; do
    echo "=== Testing: $url ==="
    curl -sI -L "$url" | grep -E "HTTP/|Location:"
    echo ""
done

# SSL sertifika geçerlilik kontrolü
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | 
  openssl x509 -noout -checkend 2592000 && 
  echo "Sertifika en az 30 gün geçerli" || 
  echo "UYARI: Sertifika 30 gün icinde sona eriyor!"

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

Monitoring için basit bir script yazabilirsiniz:

#!/bin/bash
# /usr/local/bin/check_https_redirect.sh

DOMAIN="example.com"
LOG_FILE="/var/log/https_check.log"
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")

# HTTP isteği yap ve yönlendirmeyi kontrol et
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "http://$DOMAIN")
REDIRECT_URL=$(curl -sI --max-time 10 "http://$DOMAIN" | grep -i "location:" | awk '{print $2}' | tr -d 'r')

if [ "$HTTP_CODE" = "301" ] && [[ "$REDIRECT_URL" == https://* ]]; then
    echo "$TIMESTAMP - OK: HTTP->HTTPS yonlendirme calisiyor (301)" >> $LOG_FILE
else
    echo "$TIMESTAMP - HATA: Yonlendirme calismıyor! HTTP kodu: $HTTP_CODE, Yonlendirme: $REDIRECT_URL" >> $LOG_FILE
    # Alarm gonder
    mail -s "HTTPS Yonlendirme Sorunu: $DOMAIN" [email protected] < $LOG_FILE
fi

Sonuç

Cloudflare ile HTTPS yönlendirmesi birkaç tıklamayla yapılabilen basit bir işlem gibi görünse de, doğru yapmak için birkaç katmanı birlikte düşünmek gerekiyor. Özetlemek gerekirse:

  • SSL/TLS modunu Full Strict olarak ayarlayın. Flexible modu production ortamında kullanmayın.
  • Always Use HTTPS ve Automatic HTTPS Rewrites özelliklerini etkinleştirin.
  • HSTS’yi yapılandırın ama preload’a acele etmeyin.
  • Sunucu tarafında da yönlendirme yapılandırın, Cloudflare’in bypass edildiği senaryolara karşı korunun.
  • Cloudflare Origin Certificate kullanarak hem güvenli hem de yenileme derdi olmayan bir kurulum elde edin.
  • Her değişiklikten sonra yönlendirme zincirini curl ile doğrulayın.

En çok karşılaşılan hata olan sonsuz yönlendirme döngüsü, genellikle Flexible SSL modu ile sunucu tarafı HTTPS yönlendirmesinin çakışmasından kaynaklanıyor. Bunu aklınızda tutarsanız sorun giderme süreciniz çok daha hızlı olacaktır.

HTTPS altyapısını bir kez doğru kurduğunuzda, hem kullanıcı güvenliğini hem SEO’yu hem de site performansını artırıyorsunuz. Değer.

Bir yanıt yazın

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