iframe “bağlanmayı reddetti” hatası: X-Frame-Options çözümü
Önemli bilgi
Bir iframe içindeki “bağlanmayı reddetti” mesajı bir ağ hatası değildir. Gömülen site, tarayıcınıza kendisini başka bir sayfanın içinde göstermemesini söyleyen bir X-Frame-Options ya da CSP frame-ancestors başlığı gönderdi. Çözüm, gömülen sitenin sunucusundadır; iframe etiketinizde asla: tüm sitede SAMEORIGIN'i koruyun ve tek bir gömme yolunu frame-ancestors * ile açın.
Şimdi kontrol edin

Okumaya başlayın
- Bir iframe içindeki “bağlanmayı reddetti” gerçekte ne demek?
- X-Frame-Options nasıl çalışır?
- DENY mi SAMEORIGIN mi: hangisini göndermeli?
- ALLOW-FROM öldü — kullanmayın
- frame-ancestors: Onun yerini alan CSP yönergesi
- İki başlık da ayarlıysa ne olur?
- Adım 1: Sizi engelleyen başlığı bulun
- Adım 2: Sayfayı kimin çerçeveleyebileceğine karar verin
- Doğru kalıp: Siteyi kilitleyin, tek bir gömme yolunu açın
- Nginx (ve add_
header tuzağı) - Apache
- Next.js ve Express
- Üçüncü taraf widget'ı güvenle gömme
- sandbox: Hesap makinesi widget'ı için nelere izin verilmeli
- Gömen tarafta neden çözüm yok?
- Her değişiklikten sonra başlıkları doğrulayın
- Belirti → Neden → Çözüm
- Sıkça Sorulan Sorular
Bir iframe içindeki “bağlanmayı reddetti” gerçekte ne demek?
Başka bir siteye işaret eden bir <iframe> ekliyorsunuz, sayfayı yeniliyorsunuz ve sayfa yerine üzgün yüz simgeli gri bir kutu görüyorsunuz; üzerine gelince example.com bağlanmayı reddetti. yazıyor. İlk tepkiniz ağ sorunundan şüphelenmek oluyor, çünkü Chrome ölü bir sunucu için tam olarak bunu gösterir. Ama DevTools'u açın; konsol farklı bir hikâye anlatıyor:
Refused to display 'https://emicalcs.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.Ağda hiçbir şey başarısız olmadı. DNS çözüldü, TCP bağlantısı açıldı, TLS tamamlandı ve sunucu gayet düzgün bir 200 döndürdü. Tarayıcı sayfayı indirdi, tek bir yanıt başlığını okudu ve sonra sayfayı sizin sayfanızın içinde çizmeyi bilerek reddetti. Bu başlık X-Frame-Options'tır ve clickjacking'i engellemek için vardır: kötü niyetli bir sayfanın görünmez bir iframe içine bir giriş ya da ödeme formu yükleyip ziyaretçileri göremedikleri düğmelere tıklamaya kandırdığı saldırı.
Bu, sorunu nasıl gidereceğiniz açısından önemlidir. Gerçek bir bağlantı hatası — URL'yi doğrudan bir sekmede açtığınızda ERR_CONNECTION_REFUSED — sunucu ya da güvenlik duvarı sorunudur ve ERR_CONNECTION_REFUSED yazısında ele alınır. iframe sürümü yalnızca sayfa bir çerçeve içinde olduğunda görünür ve aynı URL kendi sekmesinde sorunsuz çalışır. Site doğrudan yükleniyor ama çerçevenizde yüklenmiyorsa karşınızdaki şey bir kesinti değil, bir çerçeveleme politikasıdır.
Bir sayfanın X-Frame-Options ve CSP başlıklarını görün
X-Frame-Options nasıl çalışır?
X-Frame-Options, ilk kez RFC 7034'te tanımlanan bir HTTP yanıt başlığıdır; bu bilgilendirici RFC'nin yerini artık HTML standardı almıştır ve Internet Explorer 8'den beri tüm tarayıcılar destekler. Sunucu bunu bir sayfaya ekler; tarayıcı işlemeden önce okur ve sayfanın başka bir sayfadaki <frame>, <iframe>, <embed> ya da <object> içinde görünüp görünemeyeceğine karar verir.
Hâlâ önemli olan iki değeri ve artık önemi kalmamış bir değeri alır:
| Değer | Sayfayı kim çerçeveleyebilir | Tipik kullanım |
|---|---|---|
DENY | Hiç kimse — aynı site bile | Giriş sayfaları, yönetim panelleri, oturum taşıyan her şey |
SAMEORIGIN | Yalnızca tam olarak aynı kökene (şema + ana makine + port) ait sayfalar | Çoğu site için makul varsayılan; kendi sayfalarınızı çerçevelemenize izin verir |
ALLOW-FROM https://a.com | Eski — tüm modern tarayıcılar yok sayar | Kullanmayın; aşağıya bakın |
Başlık site başına değil, yanıt başına geçerlidir. Çoğu rehberin atladığı ve bu yazıdaki çözümü mümkün kılan ayrıntı budur: bir sunucu sayfalarının %99'unda SAMEORIGIN gönderirken, gömülmek üzere tasarlanmış tek yolda farklı bir politika gönderebilir.
DENY mi SAMEORIGIN mi: hangisini göndermeli?
Bir nedeniniz yoksa SAMEORIGIN gönderin. Üçüncü taraf çerçevelerin hepsini engeller, kendi sitenizin kendi sayfalarını çerçevelemesine ise izin verir — yardım widget'ları, önizlemeler, başka iç sayfaları yükleyen paneller.
Çerçevelemenin meşru bir amacı olmayan ve zararın ağır olacağı sayfalarda DENY gönderin: giriş formları, ödeme sayfaları, “hesabı sil” gibi tek tıkla yapılan işlemler. DENY ayrıca ince bir durumu da kapsar: bir saldırganın kendi sayfalarınızdan birine çerçeve enjekte etmeyi başarması — SAMEORIGIN ile bu enjekte edilmiş çerçeve yine de izinli olurdu.
Hangisini seçerseniz seçin, hata sayfaları ve statik dosyalar dahil her yanıtı kapsaması için web sunucusu ya da CDN düzeyinde bir kez tanımlayın. Uygulama kodunda ayarlanan başlıklar 404 ve bakım sayfasını kaçırmaya eğilimlidir; bunları tüm yanıtların geçtiği yerde ayarlayın.
ALLOW-FROM öldü — kullanmayın
Eski yazılar hâlâ tek bir gömen siteye izin vermek için X-Frame-Options: ALLOW-FROM https://partner.com önerir. Chrome ve Safari'de hiç çalışmadı, Firefox ise sürüm 70'te (Ekim 2019) kaldırdı. Daha kötüsü, ALLOW-FROM gören modern bir tarayıcı başlığın tamamını geçersiz sayar ve tümüyle yok sayar; bu da sayfayı herkesin çerçeveleyebileceği hâle getirir — niyetinizin tam tersi.
Belirli sitelere izin vermeniz gerekiyorsa cevap, sonraki bölümde anlatılan CSP frame-ancestors'tır. X-Frame-Options yalnızca “hiç kimse” ya da “sadece ben” diyebilir.
frame-ancestors: Onun yerini alan CSP yönergesi
Content Security Policy Seviye 2, X-Frame-Options'ın yaptığı her şeyi yapan ve onun yapamadığı şeyi ekleyen bir yönerge olan frame-ancestors'ı getirdi: gerçek bir izin listesi. Standart Content-Security-Policy başlığının içinde taşınır ve bir ya da daha fazla kaynak kabul eder:
# Nobody may frame this (same as X-Frame-Options: DENY)
Content-Security-Policy: frame-ancestors 'none'
# Only my own origin (same as SAMEORIGIN)
Content-Security-Policy: frame-ancestors 'self'
# My origin plus two named partners, one with a subdomain wildcard
Content-Security-Policy: frame-ancestors 'self' https://partner.example https://*.trusted.example
# Anyone may frame this — for a public embed endpoint only
Content-Security-Policy: frame-ancestors *Geçiş yapmadan önce bilmeye değer üç ayrıntı:
- Yalnızca ebeveyni değil, tüm atalarını kontrol eder. A sayfası B'yi, B de sizin sayfanızı çerçeveliyorsa hem A hem B'nin izinli olması gerekir (CSP). HTML standardı artık
X-Frame-Options'ı da tüm atalara uygular (WHATWG), ancak eski tarayıcılar yalnızca ebeveyni ya da en üst sayfayı kontrol ederdi. - Yalnızca HTTP başlığı olarak çalışır. CSP bir
<meta http-equiv>etiketiyle iletildiğindeframe-ancestorsaçıkça yok sayılır — tarayıcının belgeyi işleyip işlemeyeceğine karar vermeden önce politikayı bilmesi gerekir. AynısıX-Frame-Optionsiçin de geçerlidir. İkisi de HTML içinden ayarlanamaz. - Joker karakterler ana makine başınadır, genel değil.
https://*.example.comtek bir sitenin herhangi bir alt alan adıyla eşleşir; çıplak bir*internetteki her kökenle eşleşir. Bir hesap makinesi widget'ı için uygun, oturum taşıyan her şey için yanlış.
İki başlık da ayarlıysa ne olur?
Çoğu site geçiş sırasında ikisini birden göndermeye başlar ve öncelik tanımlıdır: frame-ancestors varsa tarayıcı onu uygular ve X-Frame-Options'ı yok sayar. CSP Seviye 2 şartnamesi bunu açıkça söyler; Chrome, Firefox, Safari ve Edge de buna uyar.
Bu, güvenli geçiş yolunu basitleştirir. CSP 2'den önceki birkaç çok eski istemci için X-Frame-Options: SAMEORIGIN'i koruyun, yanına Content-Security-Policy: frame-ancestors 'self' ekleyin; tüm modern tarayıcılar CSP kuralını kullanır. İkisi yalnızca farklı şeyler söylemelerini sağlarsanız sorun çıkarır — örneğin X-Frame-Options: DENY ile frame-ancestors * yan yana — o durumda modern tarayıcılar çerçevelemeye izin verir ve yalnızca çok eski olanlar engeller. Tutarlı tutarsanız hata ayıklanacak bir şey kalmaz.
Adım 1: Sizi engelleyen başlığı bulun
Bir şeyi değiştirmeden önce hangi politikanın devrede olduğunu doğrulayın. Konsol başlığın adını zaten söyledi; curl ise sunucunun gönderdiği tam değeri gösterir. Bu örnek, aşağıdaki uygulamalı örnekteki siteyi kullanıyor — ana sayfaları bilerek kilitli:
curl -sI https://emicalcs.com/ | grep -i -E 'x-frame-options|content-security-policy'
# Output:
# x-frame-options: SAMEORIGINÜç şeyden biri döner:
x-frame-options: SAMEORIGINya daDENY— klasik çerçeveleme politikası. Yalnızca o sunucudaki bir değişiklik bunu kaldırabilir.content-security-policy: … frame-ancestors …— bir CSP politikası. Kaynak listesini okuyun; kökeniniz orada yoksa engellenmişsiniz demektir. Yönerge çoğunluklascript-srcve benzerlerinin yanında uzun bir CSP başlığının içine gömülüdür; bu yüzden değerin tamamını okuyun.- İki başlık da yok: gömülen site çerçeveye izin veriyor ve “bağlanmayı reddetti” başka bir nedenden kaynaklanıyor: kilitli olan bir sayfaya yönlendirme (çoğu zaman bir giriş sayfası;
curl -sILile izleyin) ya da kendi sayfanızdaki, katılmayan her çerçeveyi engelleyen ve aynı gri kutuyu gösteren birCross-Origin-Embedder-Policy: require-corpbaşlığı.
Adım 2: Sayfayı kimin çerçeveleyebileceğine karar verin
Bundan sonrası tek bir soruya bağlı: çerçevelenen siteyi siz mi yönetiyorsunuz?
Hayırsa burada durun. İstemci tarafında bir çözüm yok — ne bir sandbox özniteliği, ne farklı bir src, ne de ziyaretçilerinizin sahip olacağı bir tarayıcı ayarı. Site sahibi sayfasının gömülmemesine karar verdi ve tarayıcı bu kararı onun adına uyguluyor. Seçenekleriniz sayfaya bağlantı vermek, sahibine bir gömme uç noktası sunup sunmadığını sormak ya da varsa resmî bir widget kullanmaktır. Ana sitesini kilitleyen birçok hizmet bir tane sunar; sonraki bölümdeki örnek bunun nasıl göründüğünü gösteriyor.
Siteyi siz yönetiyorsanız başlığı tüm siteden kaldırma isteğine direnin. Bu, tek bir sayfadaki gömmeyi düzeltmek için oturum ve form taşıyanlar dahil her sayfada clickjacking'i yeniden açar. Bunun yerine hangi belirli yolların çerçevelenmesi gerektiğine ve kim tarafından çerçevelenmesi gerektiğine karar verin:
| Durum | O yolda gönderilecek başlık |
|---|---|
| Kendi panonuz tarafından çerçevelenen iç araç | frame-ancestors 'self' (artı X-Frame-Options: SAMEORIGIN) |
| Birkaç bilinen ortak tarafından gömülen widget | frame-ancestors 'self' https://partner-a.com https://partner-b.com |
| Herkese açık gömülebilir widget (hesap makinesi, harita, oynatıcı) | yalnızca gömme yolunda frame-ancestors * |
| Geri kalan her şey | frame-ancestors 'self' artı X-Frame-Options: SAMEORIGIN |
Doğru kalıp: Siteyi kilitleyin, tek bir gömme yolunu açın
Bu kalıbın karşılaştığım en temiz gerçek örneği, diğer sitelerin gömmesine davet edildiği, kredi taksiti, SIP, gelir vergisi, GST gibi 45 Hint finans hesap makinesinden oluşan ücretsiz bir koleksiyon olan EMICalcs. Ana site kilitli; özel bir /embed/ yolu açık. İkisinin başlıklarını karşılaştırın:
# The calculator page a visitor normally uses — locked
curl -sI https://emicalcs.com/income-tax-calculator/ | grep -i -E 'x-frame|frame-ancestors'
# x-frame-options: SAMEORIGIN
# The same calculator on its embed path — open to any site
curl -sI https://emicalcs.com/embed/income-tax-calculator/ | grep -i -E 'x-frame|frame-ancestors'
# content-security-policy: frame-ancestors *Gömme yanıtının neyi içermediğine dikkat edin: /embed/ üzerinde hiç X-Frame-Options başlığı yok. Bu kasıtlı. CSP yönergesi öncelikli olduğu için SAMEORIGIN'i bırakmak modern tarayıcılarda zararsız olurdu — ama başlıkları okuyacak bir sonraki mühendisin kafasını karıştırır ve yalnızca X-Frame-Options anlayan birkaç eski istemciyi yine de engellerdi. Gömme yolu tek bir politika gönderir ve o politika tek bir şey söyler.
Sitenin geri kalanı SAMEORIGIN'i korur; böylece ana sayfa, makale sayfaları ve tam hesap makinesi sayfaları clickjacking'e karşı korunmuş kalır. Gömme sürümleri gezinmesiz ve ele geçirmeye değer hiçbir şey içermeyen sadeleştirilmiş belgelerdir; bu yüzden onları *'a açmak makul bir takastır.
Kendi widget'ınızı yayımlıyorsanız onların gömme rehberi bir şablon olarak okumaya değer: hesap makinesi başına tek bir kalıcı URL, çoğuna uyan sabit bir yükseklik, kod parçasında loading="lazy" ve emekli edilen gömme URL'lerinin 404 vermek yerine yönlendirileceği sözü — çünkü sizi gömen her site URL'nizin çalışmaya devam edeceğine güveniyor.
Nginx (ve add_header tuzağı)
Çoğu sitenin başlık ayarladığı üç yerde aynı kalıp. Her durumda site genelindeki bir kural her şeyi kilitler, daha dar bir kural gömme yolunda onu geçersiz kılar. Bir tuzağı olduğu için önce Nginx:
# Site-wide default (server block)
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
add_header X-Content-Type-Options "nosniff" always;
location /embed/ {
# WARNING: any add_header here stops ALL add_header inheritance from the
# server block — re-declare every header you still want on this path.
add_header Content-Security-Policy "frame-ancestors *" always;
add_header X-Content-Type-Options "nosniff" always;
}Yorum satırı isteğe bağlı okuma değil. add_header seviyeler arasında birleştirilmez: bir location bloğu herhangi bir add_header tanımladığı anda server bloğundaki tüm add_header'ları miras almayı bırakır. Ekipler gömme yolunda HSTS ya da nosniff başlıklarını böyle kaybeder ve aylar sonra bir güvenlik taramasında fark eder. İhtiyacınız olanları yeniden tanımlayın ve yolun tek bir net politika göndermesi için X-Frame-Options'ı gömme bloğunun dışında bırakın. nginx 1.29.3'ten beri add_header_inherit merge mirası geri açabilir (nginx), ama gömme bloğunda kullanmayın: site genelindeki X-Frame-Options ve frame-ancestors 'self' başlıklarını o yola geri ekler ve iki CSP başlığı olduğunda tarayıcı ikisini de uyguladığı için çerçeve engellenmiş kalır.
Apache
Apache'nin Header yönergesi kapsamlar arasında birleşir; bu yüzden varsayılanı bir kez tanımlayıp gömme yolunda değişen yalnızca iki başlığa dokunabilirsiniz:
# Site-wide default (needs mod_headers)
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy "frame-ancestors 'self'"
<LocationMatch "^/embed/">
Header always unset X-Frame-Options
Header always set Content-Security-Policy "frame-ancestors *"
</LocationMatch>Next.js ve Express
Next.js'te başlıklar next.config.js içinde tanımlanır. İki kural aynı yolla eşleşip aynı başlığı ayarladığında sonraki kural kazanır — ancak yalnızca önceki kuralın ayarladığı bir başlık yine de uygulanır. X-Frame-Options'ı gömme yolundan tamamen uzak tutmak için onu site genelindeki kuraldan negatif ileri bakışla (negative lookahead) hariç tutun:
// next.config.js
module.exports = {
async headers() {
return [
{
// Every path EXCEPT /embed/... gets the locked defaults
source: '/((?!embed/).*)',
headers: [
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'Content-Security-Policy', value: "frame-ancestors 'self'" },
],
},
{
source: '/embed/:path*',
headers: [
{ key: 'Content-Security-Policy', value: 'frame-ancestors *' },
],
},
]
},
}Express'te popüler helmet ara yazılımı varsayılan olarak zaten X-Frame-Options: SAMEORIGIN ve frame-ancestors 'self' içeren bir CSP gönderir. Onu genel olarak bağlayın, ardından gömme router'ında res.removeHeader('X-Frame-Options') çağırın ve işlemeden önce Content-Security-Policy'yi frame-ancestors * olarak ayarlayın. Sıra önemlidir: geçersiz kılmanız helmet'ten sonra çalışmalı, yoksa helmet onu ezer.
Üçüncü taraf widget'ı güvenle gömme
Şimdi çitin öbür tarafı: gömen site sizsiniz, sağlayıcının açık bir gömme yolu var ve çerçevenin düzgün davranmasını istiyorsunuz. İyi yapılmış bir widget kod parçası şöyle görünür; EMICalcs'in her hesap makinesi sayfasında yayımladığı budur:
<iframe src="https://emicalcs.com/embed/income-tax-calculator/"
title="Income Tax Calculator FY 2026-27 — EMICalcs"
width="100%" height="760"
style="max-width:680px;border:0;border-radius:16px;overflow:hidden"
loading="lazy"></iframe>
<p>Free <a href="https://emicalcs.com/income-tax-calculator/" target="_blank" rel="noopener">Income Tax Calculator FY 2026-27</a> by EMICalcs</p>Her özniteliğin bir görevi var:
title— çerçeveye ekran okuyucular için ad verir. Onsuz yardımcı teknoloji yalnızca “çerçeve” der ve erişilebilirlik denetimleri sayfayı başarısız sayar.styleiçindemax-widthilewidth="100%"— mobilde dar sütunları doldurur, masaüstünde geniş sütunlardan taşmaz.- Sabit bir
height— gömen sayfa, başka kökenden bir çerçevenin içerik yüksekliğini okuyamaz; bu yüzden sabit bir değer, yüklenirken yerleşim kaymasını önlemenin tek yoludur. Widget başına bir kez ayarlayın. loading="lazy"— isteği çerçeve görünür alana yaklaşana kadar erteler; böylece uzun bir makalenin sonundaki widget ilk yüklemede hiçbir şeye mal olmaz.border:0; border-radius; overflow:hidden— varsayılan çökük kenarlığı kaldırır ve köşeleri keser; widget sayfanıza özgü görünür.
Kredi satırı bilerek iframe'in dışında durur. Çerçevenin içindeki her şey gömülen belgeye aittir — bağlantıları sağlayıcının bağlantılarıdır, sağlayıcının URL'sindedir — bu yüzden çerçeve içindeki bir bağlantı, okurlarınız ya da bir arama motoru tarayıcısı için sayfanızın parçası değildir. Kaynağa atıf yapmak istiyorsanız ya da sağlayıcı istiyorsa yukarıdaki gibi, kendi HTML'inizde çerçevenin yanına düz bir paragraf koyun.
sandbox: Hesap makinesi widget'ı için nelere izin verilmeli
sandbox özniteliği gömen tarafın kendi korumasıdır. Değersiz eklerseniz çerçevelenen sayfa hiçbir şey alamaz: betik yok, form yok, açılır pencere yok, pencerenizi yönlendirme yok ve kendi çerezlerini ve depolamasını devre dışı bırakan opak bir köken. Sonra yalnızca widget'ın ihtiyacı olanı geri ekleyin:
<iframe src="https://emicalcs.com/embed/loan-emi-calculator/"
sandbox="allow-scripts allow-forms allow-same-origin allow-popups"
title="Loan EMI Calculator — EMICalcs"
width="100%" height="760" loading="lazy"></iframe>allow-scripts ve allow-forms, etkileşimli her şey için asgari düzeydir. allow-same-origin, çerçevelenen sayfanın kendi kökenini korumasına izin verir; böylece depolaması ve çerezleri çalışır — başka kökenden bir gömmede bu güvenlidir, çünkü “onun kökeni” hâlâ sizin değil sağlayıcınındır. allow-popups yalnızca widget bağlantıları yeni sekmede açıyorsa gerekir; EMICalcs gömmesindeki kredi bağlantısının yaptığı gibi.
Yapmamanız gereken şey, kendi kökeninize işaret eden bir çerçevede allow-scripts ile allow-same-origin'i birleştirmektir. Çerçevelenen betik o zaman yukarı çıkıp kendi sandbox özniteliğini kaldırabilir ve hiçbir şeyi yalıtmamış olursunuz.
Gömen tarafta neden çözüm yok?
“refused to connect iframe” aramasında üç popüler geçici çözüm çıkar. Hepsi kötü ve nedenini tam olarak bilmek yararlı.
X-Frame-Options'ı silen tarayıcı eklentileri — yalnızca kendi tarayıcınızda çalışır. Sitenizin her ziyaretçisi hâlâ gri kutuyu görür ve bu arada ziyaret ettiğiniz her sitede clickjacking korumasını kapatmış olursunuz.- Sayfayı kendi sunucunuzdan geçirmek — üçüncü tarafın HTML'ini sunucu tarafında alıp kendi kökeninizden sunarsınız; böylece başlık tarayıcıya hiç ulaşmaz. Bu, göreli bağlantıları, çerezleri, girişleri ve betikle çalışan her şeyi bozar; sizi onların içeriğinden sorumlu kılar; ve genellikle sağlayıcının şartlarını ihlal eder. Sizi yakalayan siteler sunucunuzun IP'sini engeller.
- Ekran görüntüsü ya da “web'den görsele” hizmetleri — çalışan bir sayfa değil, statik bir resim alırsınız. Önizleme küçük resmi için uygun, hesap makinesi için işe yaramaz.
Başlık, site sahibinin sayfasına ne olabileceğine dair, tarayıcı tarafından uygulanan bir beyanıdır. Meşru yollar daha önce ele alınan ikisidir: sahibi bir gömme yolu açar ya da siz bağlantı verirsiniz. Gömülmek isteyen sağlayıcılar bunu kolaylaştırır — iyileri bir kod parçası yayımlar, URL'yi kalıcı tutar ve yalnızca açması güvenli olan yolu açar.
Her değişiklikten sonra başlıkları doğrulayın
Çerçeveleme başlıkları bir yapılandırma dosyasında ayarlanıp unutulur; bir CDN, bir ters proxy ya da iyi niyetli bir güvenlik eklentisi bunları istediği an ekleyebilir, silebilir ya da çoğaltabilir. Yayına aldıktan sonra ağınızın dışından kontrol edin:
# The locked pages should show SAMEORIGIN and/or frame-ancestors 'self'
curl -sI https://example.com/ | grep -i -E 'x-frame-options|content-security-policy'
# The embed path should show ONLY frame-ancestors, with the sources you intended
curl -sI https://example.com/embed/widget/ | grep -i -E 'x-frame-options|content-security-policy'
# Error pages should carry the header too
curl -sI https://example.com/this-does-not-exist | grep -i -E 'x-frame-options|content-security-policy'Sonra bir tarayıcının yaptığı gibi test edin: gömme URL'sini farklı bir kökenden sunulan bir sayfadaki <iframe> içine koyun — yerel bir file:// sayfası işe yaramaz, çünkü tarayıcılar onu özel olarak ele alır — ve konsolu açın. Temiz bir yükleme, Refused to display ya da Refused to frame satırının olmaması demektir.
Site Cloudflare ya da başka bir CDN'in arkasındaysa önbellekteki bir kopya veya bir uç kuralı, kaynağınızdan farklı başlıklar taşıyabilir. HTTP Başlık Kontrolü URL'yi tarayıcınızın ve ağınızın dışından, sunucumuzdan ister ve X-Frame-Options ile Content-Security-Policy'yi bir çerçeveleme kararıyla (SAMEORIGIN ya da DENY, CSP frame-ancestors üzerinden ya da gönderilmedi) gösterir: gömme yolunuza sessizce SAMEORIGIN'i geri ekleyen bir CDN kuralını yakalamanın hızlı yolu.
Belirti → Neden → Çözüm
Rehberin tamamını yeniden okumak yerine doğrudan çözüme atlamak için bunu kullanın:
| Ne görüyorsunuz | Ne anlama geliyor | Çözüm |
|---|---|---|
| Gri kutuda “bağlanmayı reddetti”, ama URL bir sekmede yükleniyor | X-Frame-Options ya da frame-ancestors çerçeveyi engelledi | Yalnızca site sahibi değiştirebilir — onun gömme yolunu kullanın ya da bağlantı verin |
Konsol: Refused to display … 'X-Frame-Options' to 'sameorigin' | Klasik başlık; yalnızca aynı kökenden çerçevelere izin var | Çerçevelenen sitede gömme yolunu frame-ancestors * ya da bir ortak listesiyle açın |
Konsol: Refused to frame … violates … frame-ancestors | CSP izin listesi kökeninizi içermiyor | Kökeninizi çerçevelenen sitenin frame-ancestors kaynaklarına ekleyin |
| Dün çalışıyordu, bugün bozuk, kod değişikliği yok | Bir CDN ya da güvenlik eklentisi SAMEORIGIN enjekte etmeye başladı | curl ile kontrol edin; CDN ya da eklenti kuralında gömme yolunu hariç tutun |
| Kendi panonuz kendi sayfanızı çerçeveleyemiyor | Alt alan adı ya da şema uyuşmazlığı (www ve kök alan adı, http ve https) | frame-ancestors 'self' https://example.com https://*.example.com kullanın (joker karakter çıplak alan adını kapsamaz) |
Gömme çalışıyor ama o yolda HSTS ya da nosniff kayboldu | Nginx add_header mirası bunları düşürdü | location bloğunun içinde her başlığı yeniden tanımlayın |
URL'yi doğrudan açınca ERR_CONNECTION_REFUSED | Gerçek bir ağ hatası, çerçeveleme politikası değil | ERR_CONNECTION_REFUSED yazısına ve port kontrolcüsüne bakın |
URL kendi sekmesinde de başarısız oluyorsa çerçeve yanıltıcı bir ipucudur. Herhangi bir çerçeveleme başlığına dokunmadan önce ağ katmanlarını sırayla — DNS, port, TLS, başlıklar — herkese açık API uç noktası test rehberiyle gözden geçirin.
Bir URL'nin gönderdiği tüm güvenlik başlıklarını görün
Herhangi bir sayfa için X-Frame-Options, Content-Security-Policy, HSTS ve gerisini kontrol edin; sunucularımızdan alındığı için bir tarayıcı eklentisi ya da kendi ağınızdaki bir proxy gördüklerinizi değiştiremez. Ücretsiz, kayıt gerekmez.
Kaynaklar
Sıkça Sorulan Sorular
X-Frame-Options eskidi mi?
X-Frame-Options: DENY ne demek?
DENY ile SAMEORIGIN arasındaki fark nedir?
Bir siteyi gömmek için X-Frame-Options'ı nasıl aşarım?
X-Frame-Options'ı DENY olarak nasıl ayarlarım?
Site yeni sekmede çalışırken iframe'im neden “bağlanmayı reddetti” diyor?
X-Frame-Options ya da frame-ancestors'ı meta etiketinde ayarlayabilir miyim?
frame-ancestors * sitemi güvensiz yapar mı?
X-Frame-Options: ALLOW-FROM neden çalışmıyor?
X-Frame-Options ve frame-ancestors ikisi de ayarlıysa hangi başlık kazanır?
İlgili Makaleler
İlgili Araçlar
HTTP Başlık Kontrolü
HTTP yanıt başlıklarını ve güvenlik başlıkları derecelendirmesini analiz edin
Port Kontrolü
Port bağlantısını ve servis kullanılabilirliğini test edin
SSL Sertifika Kontrolü
SSL sertifika geçerliliğini ve güvenlik ayrıntılarını doğrulayın
DNS Sorgulama
Tüm DNS kayıtları alan adının kendi ad sunucularından, Google ve Cloudflare önbelleğiyle yan yana



