Rehber
DNS Sızıntısı Rehberi: WebRTC, Header ve DNS Leak Nasıl Kapanır
DNS sızıntısı, WebRTC adayı ve header leak çıkış IP’sinden önce gerçek adresi ele verir. socks5h, ICE dökümü ve echo testi ile kanalı kapatın.
DNS sızıntısı, hedef host adının proxy tünelinden önce istemcinin kendi çözümleyicisine gitmesidir. HTTP isteği gw.weproxy.com.tr üzerinden çıksa bile sorgu ofis DNS’ine, ev yönlendiricisine veya tarayıcının DoH uç noktasına düşerse kayıtta gerçek istemci IP’si ve ziyaret edilen ad görünür. WebRTC ICE adayları ile Forwarded başlıkları aynı oturumda ikinci ve üçüncü kanalı açar.
Bu rehber TCP el sıkışması ile çözümleme sırasını, socks5h ile yerel DNS farkını ve tarayıcı UDP’sinin neden çoğu HTTP proxy profilinde dışarıda kaldığını ayırır. Örnekler cURL, Python ve Node.js içindir. Amaç, çıkış IP’si ile kimlik düzlemini (DNS, ICE, header) aynı hizaya getirmektir. Temiz bir çıkış, sızıntı varken tek başına yetmez.
DNS sızıntısı çıkış IP’sinden önce oluşur
Bir istemci https://example.com açmak istediğinde iki ayrı iş vardır. Birincisi ad çözümleme: example.com hangi adrese gider? İkincisi taşıma: TCP (ve TLS) o adrese nasıl bağlanır? Proxy çoğu ekipte yalnızca ikinci işi üstlenir. Birinci iş istemcide kalırsa DNS sızıntısı oluşur.
Çözümleyici şunları görür: sorguyu gönderen IP, sorulan tam ad (QNAME) ve sorgu tipi (A, AAAA, HTTPS). Sayfa gövdesi proxy’den çıksa bile bu kayıt, ofis ağınızın veya ev ISS’nizin çözümleyicisinde durur. Hedef site bu kaydı görmez; çözümleyici ve onu işleten kuruluş görür. Log toplama, şeffaflık raporları veya yanlış yapılandırılmış bir yönlendirici bu izi operasyonel riske çevirir.
Tarayıcıda DNS over HTTPS (DoH) bu sorunu kendiliğinden kapatmaz. DoH sorgusu da bir HTTPS isteğidir. Bu istek proxy profilinin dışındaysa, çözümleyici hâlâ gerçek istemci IP’sini görür; üstüne QNAME’i de görür. DoH trafiği proxy içinden giderse çözümleyici proxy çıkışını görür. Kontrol edilmesi gereken şey “şifreli DNS var mı” değil, “sorgu hangi IP’den çıkıyor” sorusudur.
Pratik test şudur. Yalnızca sizin kontrolünüzdeki bir alt alan adı seçin (probe-20261008.example.com gibi). İstemciyi proxy’ye alın, bu ada tek bir istek atın ve yetkili DNS logunda sorgunun hangi kaynak IP’den geldiğine bakın. Kaynak, beklenen çıkış IP’si değilse DNS sızıntısı vardır. Üçüncü taraf “DNS leak test” sayfaları aynı fikri görselleştirir; karar için kendi logunuz daha kesindir, çünkü hangi çözümleyicinin cevap verdiğini siz görürsünüz.
TCP el sıkışması ve çözümleme sırası
TCP three-way handshake (SYN, SYN-ACK, ACK) ancak hedef adres bilindikten sonra başlar. Proxy senaryosunda “hedef” her zaman origin değildir. HTTP proxy’de istemci önce proxy’ye TCP açar, sonra CONNECT ile origin’e tünel ister. SOCKS5’te de kontrol kanalı önce proxy’ye kurulur. Origin ile handshake, tünel hazır olduktan sonra tünelin içinde yürür.
Sıra kabaca şöyledir:
-
İstemci proxy adresini çözer (
gw.weproxy.com.tr). Bu sorgu yerel kalabilir; gateway adıdır, hedef site değildir. -
İstemci proxy’ye TCP bağlantısı açar ve kimlik doğrular.
-
İstemci ya host adını proxy’ye verir ya da önce kendisi IP’ye çevirir.
-
Proxy origin’e TCP açar (3. adım host adıysa çözümleme proxy tarafındadır).
-
İstemci, tünelin içinde TLS ClientHello gönderir. SNI burada origin adını taşır; bu, DNS’ten ayrı bir metadata kanalıdır.
-
adım yerel çözümlemeye düşerse DNS sızıntısı, handshake’ten önce tamamlanmış olur. TLS’i “proxy üzerinden” görmek bu kaydı silmez.
HTTP CONNECT host adını proxy’ye bırakır
HTTP proxy, HTTPS için CONNECT yöntemi ile çalışır. İstemci CONNECT example.com:443 HTTP/1.1 gönderir. Host adı proxy’ye gider; sağlıklı bir istemci bu adımı kendi A kaydına çevirmeden yapar. Proxy origin’e TCP açar, 200 Connection Established döner, istemci tünelin içinde TLS el sıkışmasını tamamlar.
Bu modelde hedefe ait DNS sorgusu istemcinin çözümleyicisine düşmemelidir. Düşüyorsa kütüphane CONNECT’ten önce getaddrinfo çağırıyordur. Bazı eski HTTP istemcileri, “proxy var” deyip yine de yerel DNS yapar. Bunu log ile doğrulayın; protokol adına güvenmeyin.
Düz HTTP (TLS’siz) istekte istemci proxy’ye mutlak URL gönderir: GET http://example.com/path. Çözümleme yine proxy’dedir. Günlük işlerin çoğu TLS’li CONNECT yoludur.
WeProxy gateway’i kullanıcı adı ve parola ile dinler: gw.weproxy.com.tr:8989. Parolada @, :, / gibi karakterler varsa URL içinde yüzde kodlaması gerekir. Aksi halde istemci kullanıcıyı host sanır ve CONNECT hiç kurulmaz; bu bir sızıntı değil, bağlantı hatasıdır, ama ekipler ikisini karıştırır.
SOCKS5, yerel DNS ve socks5h
SOCKS5 uygulama verisine bakmaz. RFC 1928 hedefi üç biçimde taşır: IPv4 (ATYP 0x01), alan adı (ATYP 0x03) ve IPv6 (ATYP 0x04). Alan adı giderse proxy çözer. IPv4 giderse istemci çoktan çözmüştür.
socks5h ayrı bir protokol değildir. curl ve birçok kütüphanenin “hostname’i proxy’ye ver” şemasıdır. curl’de --socks5 yerel çözer; --socks5-hostname ve socks5h:// ATYP 0x03 kullanır. Aynı parola, aynı port, farklı DNS yolu.
UDP burada karışmasın. DNS’in klasik hali UDP/53’tür, fakat SOCKS5 üzerinden uzak DNS için UDP ASSOCIATE şart değildir: istemci sorguyu kendisi üretmez, host adını kontrol kanalında taşır, proxy kendi çözümleyicisini kullanır. UDP ASSOCIATE; oyun, VoIP ve bazı STUN yolları içindir. Ayrım için UDP proxy rehberi ve HTTP ile SOCKS5 karşılaştırması yeterlidir.
Türkiye’deki statik residential paketler HTTP ve düz SOCKS5 sunar; UDP ASSOCIATE bu paketlerde yoktur. Bu, socks5h ile uzak DNS’i engellemez. UDP’siz SOCKS5, host adını yine ATYP 0x03 ile taşıyabilir. UDP gerektiren işlerde lokasyon matrisine bakın; DNS sızıntısı testini UDP rozetine bağlamak yanlış negatif üretir.
WebRTC leak neden proxy’yi baypas eder
WebRTC, tarayıcının medya için aday IP toplamasıdır. RTCPeerConnection yerel arayüzlerden host adayı, STUN ile server-reflexive aday ve TURN ile relay adayı üretir. Host ve server-reflexive adaylar, sayfanın HTTP proxy’sinden bağımsız UDP soketleridir. Proxy “tüm tarayıcı trafiği” dese bile birçok profil yalnızca TCP 80/443’ü tünele alır.
Sonuç: sayfa çıkış IP’si residential görünürken ICE satırında ev veya ofis IP’si durur. Karşı taraf (veya sayfanın kendi betiği) bu adayı okuyabilir. MDN’deki RTCPeerConnection aday türlerini tanımlar; bu bir hata değil, API’nin tasarımıdır.
Teşhis için bir profilde şunu çalıştırın. Çıktıdaki typ host ve typ srflx satırları, proxy çıkışınızla aynı değilse WebRTC leak vardır.
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
})
pc.createDataChannel('leak-check')
pc.onicecandidate = (event) => {
if (event.candidate) console.log(event.candidate.candidate)
}
const offer = await pc.createOffer()
await pc.setLocalDescription(offer)
Kapatma tarafı politikadır, eklenti sloganı değildir. Chromium WebRtcIPHandlingPolicy değerini disable_non_proxied_udp yapmak, proxy üzerinden gitmeyen UDP adaylarını keser. Kurumsal politika veya kısayol bayrağı (--force-webrtc-ip-handling-policy=disable_non_proxied_udp) aynı işi görür. Politikayı uyguladıktan sonra testi tekrarlayın; aday listesi boşalmalı veya yalnız relay kalmalıdır. Bayrağı “açtım” demek, ICE satırını okumadan kanıt sayılmaz.
Anti-detect tarayıcılar bu politikayı profile gömebilir. Yine de her profil için bir kez ICE dökümü alın. Profil kopyalanırken bayrak düşebiliyor.
Header sızıntısı ve IPv6 yan yolu
DNS ve WebRTC istemcinin kim olduğunu ağ katmanında ele verir. Header sızıntısı ise proxy’nin veya istemcinin, origin’e giden istekte istemci IP’sini yazmasıdır. İyi bir forward proxy istemci adresini origin’e eklemez. Ters proxy (nginx, CDN) ile forward proxy’yi karıştırmayın: ters proxy’nin X-Forwarded-For eklemesi kendi mimarisidir; sizin çıkış proxy’nizin bunu origin’e iletmesi ayrı bir hatadır.
Forwarded ve X-Forwarded-For
Bakılacak başlıklar: X-Forwarded-For, Forwarded (RFC 7239), X-Real-IP, Via, Client-IP. Test, proxy üzerinden bir echo uç noktasına gitmektir. Gövde veya başlık yansımasında ofis IP’niz, tarayıcı profilinizden farklı bir iç IP veya proxy’nin eklediği Via zinciri varsa not edin.
curl -sS -x "http://USER:[email protected]:8989" \
"https://httpbin.org/headers"
USER ve PASSWORD paneldeki kimlik bilgilerinizdir. Yanıtta bu başlıklar yoksa bu istek için header sızıntısı görünmüyor demektir. Varsa, başlığı sizin kodunuz mu ekliyor (axios interceptor, tarayıcı eklentisi) yoksa ara katman mı, ayırın. Kütüphane varsayılanı “yardımcı olsun” diye X-Forwarded-For: 10.x yazabiliyor; origin bunu gerçekmiş gibi işler.
Happy Eyeballs ve IPv6
İstemcinin çalışan bir IPv6 yolu varsa ve proxy profili yalnız IPv4 ise, RFC 8305 Happy Eyeballs AAAA ile A’yı yarıştırabilir. IPv6 doğrudan ISS’ye çıkarsa proxy hiç devreye girmez. Belirti: IPv4 echo proxy IP’sini gösterir, IPv6 echo ev ön ekinizi gösterir.
Bunu IPv6 kontrol aracı ile profil açık ve kapalıyken karşılaştırın. İş IPv6 istemiyorsa istemcide IPv6’yı o profil için kapatmak en dar düzeltmedir. İş IPv6 istiyorsa çıkışın da IPv6 olması gerekir; aksi halde “proxy açık” sandığınız trafik yarı yarıya doğrudan gider. IPv6 proxy çıkışları bu ikinci durum içindir, IPv4 sızıntısını tek başına kapatmaz.
Sızıntı kanallarını karşılaştırın
| Kanal | Ne sızar | Tipik neden | Kapanış |
|---|---|---|---|
| DNS | Gerçek IP + QNAME | SOCKS5’te yerel çözümleme, proxy dışı DoH | socks5h / --socks5-hostname, DoH’u tünele almak |
| WebRTC | Host ve srflx IP | Tarayıcı UDP’si proxy dışında | disable_non_proxied_udp, ICE dökümü |
| Header | İstemci IP’si origin’de | X-Forwarded-For, Forwarded, Via | Echo testi, istemci interceptor temizliği |
| IPv6 | ISS ön eki | Happy Eyeballs, proxy yalnız IPv4 | Profilde IPv6 kapatmak veya IPv6 çıkış |
| SNI | Origin adı (IP değil) | TLS ClientHello | Ayrı metadata; DNS ile karıştırmayın |
SNI’yi DNS sızıntısı sanmayın. SNI, tünelin içindeki TLS’te origin adını taşır; hedef sunucu zaten bu adı bekler. Asıl problem, hedefin görmediği bir çözümleyicinin aynı adı sizin gerçek IP’nizle kaydetmesidir.
cURL, Python ve Node.js ile adım adım test
Aşağıdaki komutlarda kimlik bilgisi yer tutucudur. Önce My IP aracı ile proxy’siz adresinizi not edin. Sonra aynı aracı veya api.ipify.org çağrısını proxy ile tekrarlayın. İki adres aynıysa tünel kurulmamış demektir; DNS testine geçmeyin.
cURL
# HTTP proxy: CONNECT host adını taşır
curl -sS -x "http://USER:[email protected]:8989" https://api.ipify.org
echo
# SOCKS5, yerel DNS — sızıntı riski
curl -sS --socks5 "USER:[email protected]:8989" https://api.ipify.org
echo
# SOCKS5, uzak DNS
curl -sS --socks5-hostname "USER:[email protected]:8989" https://api.ipify.org
echo
İkinci ve üçüncü komutun çıkış IP’si aynı olabilir. DNS farkı IP echo’sunda görünmez; kendi alt alanınızın yetkili logunda görünür. Üçüncü komutta log kaynağı çıkış IP’si, ikincide istemci IP’si ise teşhis tamamdır.
Python
requests HTTPS’te HTTP proxy kullanırken CONNECT’e host adını yazar. SOCKS5 için requests[socks] (PySocks) gerekir. socks5:// birçok kurulumda yerel çözer; uzak DNS için şema socks5h:// olmalıdır.
import requests
proxies = {
"http": "socks5h://USER:[email protected]:8989",
"https": "socks5h://USER:[email protected]:8989",
}
response = requests.get("https://api.ipify.org", proxies=proxies, timeout=30)
print(response.text)
HTTP proxy yeterse şemayı http:// yapın; PySocks gerekmez. Kurulum ayrıntısı için Python proxy entegrasyonu adımlarına bakın. trust_env=True ise HTTP_PROXY ortam değişkeni kodunuzdaki sözlüğü ezer; test sırasında Session.trust_env = False kullanın, yoksa “kod socks5h, süreç HTTP” durumu yaşarsınız.
Node.js
Node’un yerleşik fetch’i sistem proxy’sini kendiliğinden kullanmaz. HTTP proxy için undici ProxyAgent CONNECT’e host adını verir. SOCKS5 ve uzak DNS için socks-proxy-agent paketinde socks5h:// şemasını kullanın; ajan host adını ATYP 0x03 ile iletmelidir. Yerel dns.lookup sonrası IP’ye bağlanan bir sarmalayıcı sızıntıyı geri getirir.
import { ProxyAgent, fetch } from 'undici'
const proxy = new ProxyAgent('http://USER:[email protected]:8989')
const response = await fetch('https://api.ipify.org', { dispatcher: proxy })
console.log(await response.text())
Node.js proxy entegrasyonu aynı gateway biçimini örneklerle gösterir. global-agent veya NODE_OPTIONS ile enjekte edilen bir ajan, dosyadaki ProxyAgent’ı gölgeleyebilir; test sürecini temiz bir ortamda çalıştırın.
Rate limit, sticky oturum ve havuz
Sızıntı kapandıktan sonra aynı çıkış IP’si hedefte hız sınırına takılır. 429 ve Retry-After (HTTP anlambilimi RFC 9110’dadır) tek bir IP’ye yığılan eşzamanlı istekten gelir. Sticky oturum çerezi ve yerel depolamayı sabit tutar; sayacı da o IP’de biriktirir. İstek başına dönen havuz sayacı yayar, oturum sürekliliğini keser.
İkisini karıştırmayın. DNS sızıntısı rotasyonla kapanmaz: her yeni çıkışta çözümleyici hâlâ sizin gerçek IP’nizi görür. Önce DNS ve WebRTC, sonra havuz politikası.
import time
import requests
def get_with_backoff(url, proxies, attempts=5):
delay = 1.0
response = None
for _ in range(attempts):
response = requests.get(url, proxies=proxies, timeout=30)
if response.status_code != 429:
return response
retry_after = response.headers.get("Retry-After", "")
time.sleep(float(retry_after) if retry_after.isdigit() else delay)
delay = min(delay * 2, 30)
return response
Geri çekilme, ban’ı “aşma” yöntemi değildir. Hedef 429 yerine hesap kilidi veya boş gövde döndürüyorsa havuzu büyütmek hatayı şişirir. Eşzamanlılığı düşürün, Retry-After’a uyun, iş gerçekten yerel çıkış istiyorsa coğrafyayı ona göre seçin.
Yüksek güven gereken adımlar için dönen residential IP havuzu uygundur. Aynı kimliğin saatlerce kalması gerekiyorsa statik konut tipi proxy altyapısı tek çıkışı sabitler. Savunması zayıf, gecikmesi kritik işlerde datacenter proxy çözümleri daha dar gecikme verir. Seçim, sızıntı testinden sonradır; önce kanal, sonra ürün.
Türkiye hedefli işlerde çıkışın da Türkiye olması, sitenin geo katmanı ile sizin DNS logunuzun aynı ülkeyi anlatmasını sağlar. Lokasyon eşlemesi Türkiye proxy lokasyonları üzerinden yürür. Başka bir ülke sitesine Türkiye çıkışıyla gitmek protokol hatası değildir; işin gereği değilse gereksiz bir tutarsızlıktır.
KVKK, GDPR ve robots.txt
IP adresi, bir kişiyi belirlenebilir kıldığında kişisel veridir. Türkiye’de 6698 sayılı KVKK metni mevzuat.gov.tr üzerindedir. AB’de GDPR’nin kimlik tanımı EUR-Lex’teki 2016/679 metninde durur. Bu rehber hukuk görüşü değildir: DNS logu ve WebRTC adayı, sizin gerçek IP’nizi üçüncü bir çözümleyiciye veya sayfa betiğine taşıyabilir. Topladığınız veride başkalarının IP’si varsa işleme amacı ve saklama süresi ayrıca ele alınmalıdır.
robots.txt bir erişim kontrol listesi değildir. RFC 9309 bunu gönüllü bir tarama tercihi olarak tanımlar. Sayfayı proxy ile açabiliyor olmanız, yasağın kalktığı anlamına gelmez. Hedefin hizmet şartı, KVKK/GDPR kapsamındaki kişisel veri ve WeProxy kabul edilebilir kullanım kuralları birlikte geçerlidir. Otomasyon, herkese açık ve kuralların izin verdiği yüzeyde kalmalıdır.
WeProxy çıkışında kontrol listesi
- Proxy’siz IP’yi My IP ile yazın.
- Aynı testi HTTP
CONNECTveyasocks5hile tekrarlayın; adres değişmeden devam etmeyin. - Kendi alt alanınızda yetkili DNS logunu okuyun. Kaynak IP çıkış değilse yerel çözümleme vardır.
- Tarayıcıda ICE dökümü alın.
srflxev IP’si ise WebRTC politikasını uygulayıp testi yeniden çalıştırın. - Echo uç noktasında
X-Forwarded-ForveForwardedarayın. - IPv6 açıksa IPv6 kontrolünü proxy profiliyle tekrarlayın.
429görürseniz önce eşzamanlılığı veRetry-Afterdeğerini düzeltin; DNS sızıntısını havuz büyüterek kapatmaya çalışmayın.- İş bittikten sonra kimlik bilgisini komut satırı geçmişinden ve CI logundan temizleyin. URL içindeki parola, sızıntı testinin kendisini olaya çevirir.
DNS sızıntısı kapalı, WebRTC adayı proxy ile hizalı ve origin’e giden başlıkta istemci IP’si yoksa çıkış IP’si artık tek kimlik düzlemidir. Ondan sonra sticky mi rotasyon mu, residential mi datacenter mı sorusu işe yarar. Ters sırada ürün değiştirmek, çözümleyicinin gördüğü kaydı değiştirmez.









