Ana içeriğe geç

HTTPS Zorla: HTTP'den HTTPS'ye Yönlendirme

HTTPS Zorla: HTTP'den HTTPS'ye Yönlendirme - Güvenlik Rehberi

SSL sertifikası kurulduktan sonra çoğu kişi işin bittiğini düşünür. Oysa asıl problem çoğu zaman bundan sonra başlar. Site hem HTTP hem HTTPS üzerinden açılmaya devam ediyorsa arama motoru iki farklı sürüm görebilir, kullanıcı eski bağlantılardan güvensiz protokole düşebilir ve tarayıcı bir kısmı güvenli, bir kısmı güvensiz kaynak içeren karışık bir yapı üretir. Bu durum hem güvenlik algısını bozar hem de URL standardını dağıtır.

HTTPS zorlama tam olarak bu noktada devreye girer. Amaç, gelen her HTTP isteğini tek adımda HTTPS sürümüne çevirmektir. Apache tabanlı yapılarda bu iş genellikle .htaccess dosyasında bir yönlendirme kuralı ile çözülür. Kulağa basit gelir, gerçekten de basittir; fakat kuralın sırası, status kodu, reverse proxy varlığı, WWW tercihi ve mevcut yönlendirmeler hesaba katılmazsa redirect loop ya da zincir üretmek çok kolaydır.

Sağlam kurulumun ölçüsü, kuralın yazılmış olması değil sorunsuz çalışmasıdır. Kullanıcı yalnızca bir kez yönlenmeli, hedef URL tek ve kanonik olmalı, sertifika o host için geçerli kalmalı ve sayfanın içindeki eski HTTP çağrıları temizlenmiş olmalıdır. Eğer kuralı elle yazmak yerine kontrollü üretmek istiyorsanız yönlendirme kurgusunu görsel arayüzle hazırlamak özellikle ilk kurulumda hata payını düşürür.

HTTPS zorlama neden yalnızca güvenlik meselesi değildir?

İlk katman elbette şifrelemedir. HTTP üzerinden giden veri açık metin olarak taşınır; HTTPS ise TLS ile paketleri korur. Giriş formu, oturum çerezi, ödeme adımı ya da yönetim paneli gibi alanlarda bunun önemi tartışılmaz. Fakat konu yalnızca veri gizliliği değildir. URL standardizasyonu da aynı derecede kritiktir.

Bir sayfanın hem http://site.com hem de https://site.com üzerinden açılabildiğini düşünün. İçerik aynı olsa bile teknik olarak iki ayrı adres vardır. Canonical etiketi bunu kısmen yönlendirir ama en temiz çözüm, HTTP sürümünü hiç açık bırakmamaktır. Arama motoruna “doğru adres budur” demenin en net yolu 301 yönlendirmedir.

Burada performans boyutu da devreye girer. Kötü kurulmuş HTTPS zorlama çoğu zaman tek yönlendirme yerine iki ya da üç aşamalı zincir üretir: HTTP → HTTPS → WWW ya da HTTP → non-WWW → HTTPS gibi. Her ek adım mobil ağda 150-300 ms civarı maliyet çıkarabilir. Yani güvenlik için yaptığınız iş, yanlış sırada yazılmışsa hız tarafında ters etki üretir. Bu yüzden yönlendirme zincirlerini daha sonra gerçek sayfa yükleme etkisiyle birlikte ölçmek gerekir.

Bir başka pratik fayda da kullanıcı tarafındadır. Tarayıcı adres çubuğunda “güvenli değil” uyarısı göründüğünde kullanıcı çoğu zaman teknik ayrıntıya bakmaz; sayfayı riskli sayar. Form tamamlama oranı, login tamamlama davranışı ve marka güveni bundan doğrudan etkilenir. HTTPS zorlama bu yüzden yalnızca altyapı temizliği değil, görünür kullanıcı deneyimi parçasıdır.

Burada küçük ama önemli bir eşik vardır: eğer kritik bir form ekranı ilk istekte HTTP açılıyor, sonra HTTPS’ye gidiyorsa teknik olarak son durumda güvenli görünse bile ilk temas yanlıştır. Kullanıcı önce güvensiz sürümü görmüş olur. İyi yapı, tarayıcıyı en baştan doğru protokole düşürür. Özellikle ödeme, üyelik ve panel giriş sayfalarında bu fark yalnızca kozmetik değil, davranışsal güven katmanıdır.

Apache içinde doğru 301 kuralı nasıl yazılır?

Temel kurulumun omurgası çoğu projede üç satırlık bir mod_rewrite kuralıdır:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Bu yapıda ilk satır rewrite motorunu açar. İkinci satır, isteğin HTTPS olmadığını kontrol eder. Üçüncü satır ise aynı host ve aynı path ile güvenli sürüme 301 yönlendirme yapar. Buradaki 301 kalıcı yönlendirme anlamına gelir. 302 kullanırsanız tarayıcı ve arama motoru bu geçişi “geçici” okuyabilir; bu da kanonik işaretin gücünü zayıflatır.

Çoğu projede tek başına bu kural yeterli görünür. Fakat mevcut sistemde zaten bir WWW yönlendirmesi, trailing slash kuralı ya da eski URL taşıması varsa sırayı yeniden düşünmek gerekir. Amaç, kullanıcıyı tek sıçramada nihai adrese ulaştırmaktır. Eğer hedefiniz https://www.site.com ise önce HTTP’den HTTPS’ye, sonra WWW’ye gitmek yerine ikisini tek kuralla birleştirmek daha temizdir.

Kural sırası bu yüzden önemlidir. Apache, dosyayı yukarıdan aşağı okur. Önce daha genel, sonra daha özel kuralları koymak bazen mantıklı görünür; ama yönlendirme tarafında çoğu zaman tam tersi gerekir. Nihai hedefi tanımlayan kural önce gelmeli, onu bozacak alt kurallar daha sonra düşünülmelidir. Aksi halde bir kuralın ürettiği URL’yi alt satırdaki başka bir kural tekrar dönüştürür ve zincir uzar.

WWW tercihi ile birlikte düşünmek gerekir

En sık yapılan hatalardan biri, HTTPS zorlamayı ayrı, WWW tercih kuralını ayrı yazıp istemeden zincir üretmektir. Daha temiz yaklaşım şu olabilir:

RewriteEngine On

RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.siteadi\.com$ [NC]
RewriteRule ^(.*)$ https://www.siteadi.com/$1 [L,R=301]

Bu kural iki şeyi birden yapar: HTTPS değilse ya da host beklenen biçimde değilse kullanıcıyı tek seferde nihai URL’ye taşır. Böylece hem kanonik yapı netleşir hem de gereksiz ikinci sıçrama ortadan kalkar. Yönlendirme kurallarının kalitesi çoğu zaman bu noktada ölçülür. Kural çalışıyor olabilir ama birden fazla kez çalışıyorsa iyi yazılmış sayılmaz.

Elinizde çok sayıda eski URL varsa bu kuralları elle yazarak ilerlemek zorlaşır. Özellikle HTTPS, WWW ve tekil 301 geçişleri birlikte yönetilecekse aynı mantığı tekrar tekrar elle kurmak yerine rewrite ve redirect bloklarını tek akışta üretmek daha savunulabilir bir yöntemdir.

En sık hangi hatalar zincir ve loop üretir?

İlk hata, kuralın mevcut kurallarla çakışmasını fark etmemektir. Diyelim ki üstte HTTPS zorlaması, altta da ayrı bir non-WWW kuralı var. Eğer ikisi birbirini tekrar tetikliyorsa kullanıcı bir URL’den diğerine pinpon gibi taşınabilir. Tarayıcı sonunda “too many redirects” hatası verir. Sorun SSL’de değil, kuralların birbirini tekrar ateşlemesindedir.

Bu tür hatalar özellikle eski projelerde sık görülür. Çünkü yıllar içinde farklı ekipler farklı amaçlarla yeni kural ekler. Bir satır kampanya URL’si için, bir satır dil yönlendirmesi için, bir satır cache için yazılmıştır. Sonra HTTPS kuralı bunların en üstüne eklenir ve kimse bütün akışı baştan okumaz. .htaccess dosyalarının “küçük ama tehlikeli” sayılmasının nedeni tam da budur: her satır tek başına basit, toplam davranış ise bazen şaşırtıcı derecede karmaşıktır.

İkinci hata reverse proxy veya CDN arkasındaki kurulumlardır. Cloudflare, load balancer ya da ters proxy kullanıyorsanız Apache bazen kendisine gelen iç isteği HTTP sanır. Kullanıcı aslında HTTPS üzerinden geliyordur ama arka tarafta Apache’ye düz HTTP taşınıyordur. Bu durumda %{HTTPS} off koşulu sürekli doğru görünür ve sonsuz döngü oluşabilir. Böyle yapılarda X-Forwarded-Proto başlığı ya da proxy ayarı hesaba katılmalıdır.

Üçüncü hata status kodunu yanlış seçmektir. 302 veya meta refresh ile çözüm üretmek kısa vadede çalışıyor gibi görünür ama kalıcı protokol standardı kurmaz. Özellikle site taşıma ya da SSL geçişi yaptıysanız 301 daha doğrudur. Bunun istisnası, geçici bakım akışları ya da kontrollü test geçişleri olabilir. Fakat “HTTPS artık kalıcı adresim” diyorsanız geçici yönlendirme mantıklı değildir.

Dördüncü hata mixed content tarafını unutmak olur. Sayfa HTTPS’ye yönlenmiş olabilir; ama içindeki CSS, JS, resim ya da font çağrıları hâlâ HTTP ise tarayıcı uyarı üretir ya da bu kaynakların bir kısmını yüklemez. Yani yönlendirme kuralı tek başına yetmez. Sayfa içindeki mutlak bağlantıların da temizlenmesi gerekir. İçerikte ya da HTML çıktısında kalan eski HTTP adreslerini yakalamak için sayfadaki bağlantıları topluca kontrol etmek bu yüzden faydalıdır.

Beşinci hata da uygulama içi hard-coded URL’leri gözden kaçırmaktır. Özellikle eski PHP uygulamalarında, e-posta şablonlarında ya da JS config bloklarında tam adres elle yazılmış olabilir. Siz .htaccess tarafında doğru yönlendirmeyi kurarsınız ama uygulama yine http:// ile link üretmeye devam eder. Kullanıcı her seferinde yönlendirilir, sistem çalışıyor sanılır; oysa gereksiz istek maliyeti ve bazen içerik uyumsuzluğu devam eder.

Bir başka ince hata da önceden tarayıcıya cache olmuş 301 kayıtlarıdır. Kuralı düzeltseniz bile tarayıcı eski yönlendirmeyi tutmaya devam edebilir. Bu yüzden testlerde gizli pencere, curl isteği ya da bağımsız başlık kontrolü kullanmak daha güvenilir olur. Tarayıcı geçmişini referans alarak kuralın doğru çalıştığına karar vermek yanıltıcıdır.

Proxy, CDN ve SSL modu devreye girince ne değişir?

Sunucu doğrudan internete açıkysa klasik HTTPS kuralı çoğu zaman yeterlidir. Fakat Cloudflare, Nginx reverse proxy, AWS ALB ya da benzeri katmanlar araya girdiğinde Apache’nin gördüğü protokol ile kullanıcının yaşadığı protokol farklı olabilir. Bu durumda “HTTPS kapalıysa yönlendir” kuralı teoride doğru, pratikte yanlış sonuç üretebilir.

Örneğin Cloudflare Flexible SSL modunda tarayıcı ile Cloudflare arasındaki trafik HTTPS, Cloudflare ile origin sunucu arasındaki trafik HTTP olabilir. Apache yalnızca arka taraftaki HTTP isteği gördüğü için kullanıcıyı tekrar HTTPS’ye zorlar; Cloudflare yeniden origin’e HTTP ile döner; loop başlar. Bu senaryoda kuralı düzeltmek kadar SSL modunu doğru seçmek de gerekir. Full ya da Full (Strict) yapı daha temizdir.

Proxy arkasında çalışıyorsanız şu soru net olmalıdır: “Apache gerçek istemci protokolünü hangi header ya da environment üzerinden anlayacak?” Eğer bu cevap belirsizse kural üretmek yerine önce teslimat topolojisini netleştirmek gerekir. Sertifikanın doğru hostta yayınlandığını, DNS tarafında beklenmedik yönlenme olmadığını ve proxy katmanının gerçekten istediğiniz sürümü servis ettiğini görmek için DNS ve sertifika görünümünü birlikte kontrol etmek faydalı olur.

Burada bir trade-off daha vardır. Uygulama tarafında daha akıllı kurallar yazabilirsiniz, fakat altyapı tarafı karışık kalırsa hata ayıklama zorlaşır. Daha sade kural + daha net proxy ayarı çoğu zaman daha iyi sonuç verir. .htaccess içinde tüm problemi çözmeye çalışmak yerine, doğru katmanda doğru ayarı yapmak daha sürdürülebilir yaklaşımdır.

HSTS de bu tabloya dahil edilebilir ama aceleyle eklenmemelidir. HTTP Strict Transport Security, tarayıcıya “bu hostu bir daha HTTP ile açma” der. Bu güçlü bir katmandır; ancak alt alan adları, preload listesi ve geri dönüş planı hesaba katılmadan verilirse test ortamlarında ya da henüz tam taşınmamış yapılarda can sıkabilir. Önce yönlendirme temiz çalışmalı, sertifika tüm hedef hostları kapsamalı, mixed content kalmamalı; HSTS kararı bundan sonra düşünülmelidir.

Kural yazıldıktan sonra hangi kontroller yapılmalı?

İlk kontrol, yönlendirmenin gerçekten tek sıçrama ile bitip bitmediğidir. http://site.com, http://www.site.com, https://site.com ve hedeflediğiniz nihai sürüm ayrı ayrı test edilmelidir. Hepsi aynı son adrese, tercihen tek 301 üzerinden düşmelidir. İki aşamalı dönüş varsa kural çalışıyor olsa bile optimize değildir.

Ardından farklı istemci davranışlarına bakılmalıdır. Masaüstü tarayıcı, mobil tarayıcı, bot isteği ve proxy arkasından gelen istek bazen aynı sonucu üretmeyebilir. Özellikle güvenlik eklentileri ya da WAF katmanı devredeyse, sizin gördüğünüz ile botun gördüğü yanıt farklı olabilir. Redirect kuralı çalışıyor sanmanız, arama motorunun da aynı şeyi gördüğü anlamına gelmez.

Sonraki kontrol başlık seviyesindedir. Nihai cevap 200 dönmeli, geçişler 301 olmalı ve loop üretmemelidir. Üçüncü kontrol, sertifikanın hedef host için gerçekten geçerli olup olmadığıdır. Özellikle WWW eklediğinizde wildcard ya da SAN kapsamı eksikse kullanıcı güvenlik uyarısı görür. Dördüncü kontrol ise sayfa içi mixed content taramasıdır. En sık unutulan kısım budur.

Beşinci kontrol performans tarafıdır. Yönlendirme zinciri temizlenmiş mi, ilk bayta kadar geçen süre nasıl değişmiş, HTTPS geçişiyle birlikte HSTS ya da cache davranışı ne olmuş? Bunlar yalnızca sunucu logundan değil, gerçek sayfa raporundan da okunmalıdır. Çünkü teoride temiz görünen kural, pratikte ekstra gecikme üretebilir.

Son olarak canonical, sitemap ve uygulama içi mutlak URL üretimi birlikte gözden geçirilmelidir. 301 yönlendirme nihai otoriteyi belirler; ama içerik hâlâ eski protokolü işaret ediyorsa sistem yarım kalır. Güçlü kurulum, yönlendirme kuralı ile içerik üretiminin aynı adresi işaret ettiği kurulumdur. Aksi halde her istek doğru yere düşse bile altyapı sürekli eski alışkanlığın yükünü taşır.

Kontrol Beklenen durum Uyarı işareti
HTTP → HTTPS geçişi Tek 301 ile biter İki veya daha fazla sıçrama
WWW standardı Tüm varyasyonlar tek hosta iner www ve non-www ayrı açılır
Sertifika Hedef host için geçerli Tarayıcı güvenlik uyarısı
Mixed content Tüm kaynaklar HTTPS HTTP görsel, script ya da CSS kalıntısı

Hızlı doğrulama için pratik yaklaşım

Yönlendirme kurallarını yalnızca tarayıcıya bakarak test etmek çoğu zaman yetmez. Çünkü tarayıcı cache tutar, eklentiler devreye girer ve bazı yönlendirmeler geçmişten etkilenir. Daha temiz kontrol için başlık seviyesinde bakmak gerekir. Curl ya da benzeri istemciler bu yüzden değerlidir:

curl -I http://siteadi.com
curl -I http://www.siteadi.com
curl -I https://siteadi.com

Beklenen tablo şudur: ilk iki komut 301 dönmeli ve hedef olarak nihai HTTPS adresini göstermelidir; son komut ise 200 ile yanıt vermelidir. Eğer ilk komutta HTTP’den HTTPS’ye, ikinci adımda da WWW standardına gidiyorsanız hâlâ zincir var demektir. Eğer son komut da 301 dönüyorsa nihai URL tercihi henüz tam net değildir. Bu küçük test, çoğu .htaccess hatasını tarayıcı açmadan yakalamanızı sağlar.

Testi yalnızca ana sayfada bırakmamak da önemlidir. Parametreli URL, alt klasör, eski kampanya adresi ve canonical verdiğiniz içerik sayfaları da aynı disiplinle kontrol edilmelidir. Çünkü bazı kurallar kökte düzgün çalışırken alt path altında farklı davranabilir. Sağlam yönlendirme kurgusu, yalnızca / isteğini değil tüm URL ailesini tutarlı biçimde yönetir. Bu ayrıntı özellikle büyük sitelerde oldukça net fark yaratır.

HTTPS zorlama küçük görünür, ama doğru protokol ve host standardını sessizce kurduğu için etkisi büyüktür. Hedef adresi tek adımda belirleyin, proxy varsa kurala dahil edin, mixed content ve sertifika kapsamını ayrıca test edin. İyi yönlendirme, yalnızca çalışan kural değil, her isteği tek sıçrama ile doğru adrese götüren kuraldır.