Bir uygulama proxy üzerinden çalışırken bir şeyler ters gittiğinde, bir mühendisin ilk açtığı şey istemci logları olur. Orada connection reset by peer, read timeout ya da sadece EOF yazar. Sorun şu ki, bu satırlar nedenini neredeyse hiç anlatmaz. Bağlantıyı kim sıfırladı: proxy mi, hedef sunucu mu, yoksa sizinle proxy arasındaki operatör mü? İstek proxy'ye kadar ulaştı mı? TLS el sıkışması tamamlanabildi mi? HTTP istemci kütüphanesi bunu bilmez, dolayısıyla siz de bilemezsiniz.

Bu yazıda bir seviye alta, paketlere ineceğiz. İstemci makinede tcpdump ile nasıl döküm alınır, HTTP proxy ve SOCKS5 üzerinden çalışırken bu dökümde tam olarak ne görünür, HTTPS tünelinde neden sadece CONNECT ve şifreli TLS kayıtlarını görürsünüz, döküm Wireshark'ta nasıl okunur ve RST, FIN, yeniden iletim ile sıfır pencere işaretlerinden bağlantının hangi tarafta koptuğu nasıl anlaşılır, hepsini ele alacağız. Ayrıca kendi trafiğinizi SSLKEYLOGFILE ile şifre çözme ve bir proxy servisine, örneğin Proxeon'a, doğru şekilde döküm hazırlama konusunu ayrıca konuşacağız.

Önemli bir not: bu bir mitmproxy yazısı değil. Orada söz konusu olan, uygulama seviyesinde sahte bir sertifikayla HTTPS'i yakalamak ve değiştirmek. Biz burada paket seviyesinde çalışıyoruz, hiçbir şeyi değiştirmiyor ve başkasının trafiğini açmıyoruz. Amacımız tamamen teşhis: istemci - proxy - hedef sunucu zincirinin nerede koptuğunu anlamak.

Giriş: istemci loglarının artık yetmediği an

Tipik bir durumu hayal edin. Python ile yazılmış bir betik mobil proxy üzerinden çalışıyor, saatte birkaç bin istek işliyor ve bunların yaklaşık yüzde ikisi Connection aborted, RemoteDisconnected hatasıyla bitiyor. Geliştirici yeniden deneme ekliyor, hata geçmiyor. Proxy desteğine yazıyor, onlar örnek istek ve saat istiyor. Destek kendi loglarına bakıp şöyle diyor: bizde her şey yolunda, hedef sunucuya bağlantı kuruluyordu. Kim haklı?

Döküm olmadan bu tartışma sonsuzdur. Dökümle beş dakikada biter: görürsünüz ki proxy CONNECT'e 200 yanıtı verdi, istemci ClientHello gönderdi ve 180 milisaniye sonra proxy'den RST geldi. Bu, ya proxy'nin hedef sunucuyla anlaşamadığı ya da sunucunun bağlantıyı kendisinin kapattığı anlamına gelir. Gerisi zamanlama bakmaya ve netleştirmeye kalır. Önemli olan, konuşmanın tahminlerden olgulara taşınmış olmasıdır.

HTTP istemci logları uygulama seviyesinde çalışır. Sonucu görür, süreci görmez. Trafik dökümü süreci gösterir: her paket, kesin zaman damgası, yön, bayraklar ve boyutla. Bu yüzden ciddi bir proxy altyapısı işletiminde döküm alıp okuma becerisi egzotik değil, temel bir yetenek sayılır.

Bu yazıdan ne elde edeceksiniz

  • Proxy üzerinden çalışırken istemcinin ağ arayüzünden fiziksel olarak hangi verilerin geçtiğini ve bunlardan hangilerinin açık şekilde görülebileceğini anlamak.
  • Filtreler, rotasyon ve boyut sınırlamasıyla döküm kaydetmek için hazır tcpdump komutları.
  • Olduğu gibi kopyalanabilecek Wireshark görüntüleme filtreleri.
  • Kopmanın kendi tarafınızda, proxy tarafında ve hedef sunucu tarafında olduğunu ayırt etme yöntemi.
  • Hata ayıklama için kendi TLS trafiğinizi güvenli şekilde şifre çözme yolu.
  • Destek ekibine başvuru için döküm hazırlama kontrol listesi.

Temeller: proxy öncesinde, tünel içinde ve sonrasında ne görünür

Şemayla başlayalım. Proxy üzerinden çalışırken yolun üç bölümü var ve istemci makinede fiziksel olarak yalnızca birincisini gözlemleyebilirsiniz.

Üç gözlem bölgesi

  1. Bölge A: istemci - proxy. Ağ arayüzünüzden geçen tek TCP bağlantısı budur. Makinenizdeki tcpdump bunu görür. Burada şunlar görünür: proxy'nin IP adresiyle TCP el sıkışması, proxy hizmet protokolü (HTTP CONNECT veya SOCKS5), ardından ya açık HTTP ya da şifreli TLS kayıtları.
  2. Bölge B: tünel içi. Proxy 200 Connection established yanıtını verdikten sonra sizinle hedef sunucu arasındaki tüm baytlar olduğu gibi aktarılır. Hedef sunucu HTTPS ile çalışıyorsa bu baytlar TLS kayıtlarıdır. Yapılarını görürsünüz (kayıt tipi, uzunluk, SNI'li ClientHello, ServerHello, uyarılar) ama içeriğini görmezsiniz.
  3. Bölge C: proxy - hedef sunucu. Bu, proxy'nin kendi adına kendi dış adresinden kurduğu ayrı bir TCP bağlantısıdır. İstemci makinede hiç yoktur. Yalnızca proxy sunucusunda görülebilir ki o da sağlayıcının altyapısıdır. Bölge C hakkında öğrendiğiniz her şeyi dolaylı öğrenirsiniz: CONNECT'e verilen kodlardan, gecikmelerden ve proxy'nin tüneli kapatma şeklinden.

Bu, yazının ana fikri. İstemcideki döküm hedef sunucuyu doğrudan göstermez. Ama proxy'nin davranışını gösterir, ve iyi bir aktarıcı olan proxy, hedef sunucunun davranışını yorumlanabilir bir biçime tercüme eder. Bizim işimiz bu çeviriyi okumayı öğrenmek.

HTTP proxy ve açık HTTP

En şeffaf durum. Hedef site şifrelemesiz http ile çalışıyorsa, istemci proxy'ye mutlak URI'li bir istek gönderir:

GET http://example.com/api/items HTTP/1.1
Host: example.com
Proxy-Authorization: Basic dXNlcjpwYXNz
User-Agent: my-client/1.0

Dökümde her şey görünür: metot, yol, başlıklar, gövde, proxy'nin sunucudan gelen gövdeli yanıtı. Proxy-Authorization başlığına dikkat. Bu sizin base64'lenmiş kimlik bilgileriniz, dökümde açık şekilde duruyor. Bu gerçeği unutmayalım, dökümü üçüncü kişilere verirken lazım olacak.

HTTP proxy ve CONNECT üzerinden HTTPS

Asıl ilginç kısım burada başlıyor. HTTPS için istemci önce proxy'den host ve porta TCP tüneli kurmasını ister:

CONNECT api.example.com:443 HTTP/1.1
Host: api.example.com:443
Proxy-Authorization: Basic dXNlcjpwYXNz
Proxy-Connection: Keep-Alive

Proxy yanıt verir:

HTTP/1.1 200 Connection established

Bu andan itibaren proxy HTTP'yi ayrıştırmayı bırakır. Sadece bir soketten diğerine bayt kopyalar. İstemci doğrudan hedef sunucuyla TLS el sıkışmasına başlar ve tüm HTTP trafiği (GET, POST, başlıklar, gövdeler) TLS'in içinde kalır. İşte bu yüzden HTTPS tünelinin dökümünde yalnızca CONNECT görünür: bu, istemcinin proxy'ye açık şekilde söylediği son şeydir. Sonrasında TLS kayıtları gelir ki proxy de okuyamaz, siz de dökümde okuyamazsınız.

Tünelde görünür kalanlar:

  • ClientHello: TLS sürümleri, şifre paketleri, uzantılar ve genellikle SNI (host adı açık şekilde).
  • ServerHello: seçilen sürüm ve şifre.
  • TLS 1.2'de sunucu sertifikası açık şekilde. TLS 1.3'te sertifika artık şifreli.
  • TLS Alert: uyarı tipi TLS 1.2'de görünür, TLS 1.3'te el sıkışma sonrası uyarılar şifreli ama 2 bayt uzunluğundaki Alert tipi kayıt olduğu yine tespit edilir.
  • Application Data kayıtlarının boyutu ve zamanlaması. Bunlardan bağlantı kopmadan önce ne kadar veri geldiği tahmin edilebilir.

SOCKS5

SOCKS5 farklı çalışır ama fikir aynıdır. İstemci kimlik doğrulama metotlarıyla bir karşılama mesajı gönderir (05 02 00 02 baytları), proxy metodu seçer, ardından kullanıcı adı ve parola ile kimlik doğrulama gelir (01, uzunluk, ad, uzunluk, paroladan oluşan alt protokol), sonra adres tipi 03 (alan adı) ve portla CONNECT komutu gelir. Proxy başarıda 05 00 ile ya da hata koduyla yanıt verir: 01 genel hata, 03 ağ erişilemez, 04 host erişilemez, 05 bağlantı reddedildi, 06 TTL doldu. Bu hata kodları, proxy'nin Bölge C'de gördüğünün doğrudan tercümesidir. Wireshark, portu Decode As ile belirtirseniz SOCKS'u çözebilir.

Asla görünmeyenler

İstemci makineden şunları göremezsiniz: proxy'nin hedef sunucuya gittiği dış IP (mobil proxy'lerde bu operatörün adresidir), proxy - sunucu TCP bağlantısı, proxy'nin DNS sorguları. Proxeon desteği hedef sunucu tarafında hata gördüğünü söylüyorsa, tam olarak size kapalı olan Bölge C'ye bakıyor. Sizin işiniz, iki tabloyu zamanla eşleştirebilmek için Bölge A dökümünü getirmek.

Derinlemesine: proxy neden daha fazlasını gösteremez ve dolaylı işaretler nasıl okunur

Burada tablonun neden böyle olduğunu ve bunun teşhis için ne anlama geldiğini anlamak gerekir.

Bayt borusu olarak CONNECT tüneli

200 yanıtından sonra HTTP proxy, spesifikasyona göre taraflardan biri kapanana kadar baytları yorumlamadan iki yöne iletmek zorundadır. İçeride TLS olduğunu bilmez. Hangi HTTP isteklerini gönderdiğinizi bilmez. Yalnızca iki olay görür: bayt akışı ve soket kapanışı. Hedef sunucu proxy ile bağlantıyı kapattığında (FIN veya RST gönderdiğinde) proxy sizinle olan bağlantıyı kapatmak zorundadır. Bunu tam olarak nasıl yapacağı uygulamaya bağlıdır: bazı proxy'ler FIN'i FIN, RST'i RST olarak aktarır, bazıları her şeyi FIN'e çevirir, bazıları uzak soketten okuma hatasında istemciye RST gönderir.

Pratik sonuç: Proxy'nin IP adresinden gelen RST, proxy'nin suçlu olduğu anlamına gelmez. Bu, tünelin proxy tarafından kapatıldığı anlamına gelir ve neden arkasında herhangi bir yerde olabilir. Nedeni anlamak için bağlama bakarız: RST'den önce ne oldu, ne kadar zaman geçti, yanıt geldi mi.

Proxy'ye SYN ile hedef sunucuya SYN arasındaki fark

Bu, en sık karışıklık kaynağıdır. Proxy üzerinden dökümde hedef sunucunun 443 portuna SYN'i asla görmezsiniz. Tüm SYN'ler proxy'nin IP'sine ve portuna gider. Proxy'ye SYN yanıt almaz ve 1, 2, 4, 8 saniye aralıklarla tekrarlanırsa sorun sizinle proxy arasındadır: ağ, güvenlik duvarı, yanlış adres veya port, proxy çalışmıyor. Hedef sunucunun burada hiçbir ilgisi yoktur, sizin dökümünüz açısından ona ulaşmayı bile denemediniz.

Ama proxy ile TCP kurulursa, CONNECT gönderilirse ve yanıt 20-30 saniye sonra 504 Gateway Timeout veya 502 Bad Gateway koduyla gelirse, bu proxy'nin Bölge C'yi kuramadığı anlamına gelir. Buradaki zamanlama kendi adına konuşur: CONNECT paketiniz anında gitti, uzun süre yanıt yoktu, demek ki proxy kendi girişiminde zaman aşımı bekledi.

TLS 1.3, ECH ve 2026'ya doğru değişenler

Manzara yavaş yavaş kapanıyor. TLS 1.3 baskın hale geldi ve içinde sunucu sertifikası şifreli, dolayısıyla sunucunun hangi sertifikayı döndürdüğünü anahtarlar olmadan dökümden kontrol etmek artık mümkün değil. ECH (Encrypted Client Hello) uzantısı tarayıcılar ve büyük CDN'ler tarafından kademeli olarak devreye alınıyor ve orada SNI de şifreli hale geliyor. Proxy üzerinden teşhis için bu daha az kritik çünkü host adı yine de CONNECT satırında görünür, ama alışılmış SNI filtresi daha seyrek çalışacak.

Bir başka eğilim de QUIC üzerinden HTTP/3. Klasik HTTP proxy'si CONNECT ile yalnızca TCP'yi tüneller. Dökümde aniden hedef sunucunun adresine doğrudan 443 portuna UDP trafiği görürseniz, bu bir sızıntı işaretidir: uygulama proxy üzerinden değil, doğrudan QUIC kullanmaya çalışıyor. Doğru yapılandırılmış bir istemci ya proxy üzerinden çalışırken QUIC'i kapatmalı ya da UDP'yi ayrı mekanizmalarla proxy'lemeli. Hızlı kontrol filtresi: udp.port == 443. Proxy üzerinden döküm böyle paketler gösteriyorsa istemci yapılandırması düzeltilmelidir.

Yakalama noktası nereye konur

Genellikle tek cevap vardır: istemci makinede. Ama nüanslar var. İstemci bir Docker konteynerinde çalışıyorsa, host üzerindeki tcpdump docker0 arayüzünde veya köprü arayüzünde NAT öncesi trafiği, dış arayüzde ise NAT sonrası, farklı kaynak adresle gösterir. En basiti konteynerin ağ ad alanına girmek: nsenter -t PID -n tcpdump ... veya konteyneri --net=container:ad ile tcpdump çalıştırarak başlatmak. Buluttaki sanal makinelerde offloading'e dikkat: dökümdeki paketler MTU'dan büyük görünebilir çünkü ağ kartı segmentleri birleştiriyor. Bu normaldir ve bayrak analizini etkilemez.

tcpdump pratikte: filtreler, dosyaya yazma, rotasyon

tcpdump neredeyse her Linux makinede ve macOS'ta var. Windows'ta aynı rolü Npcap sürücülü Wireshark ya da konsol tabanlı dumpcap üstlenir. Proxy teşhis görevlerinin yüzde 95'ini kapsayan komutları inceleyelim.

Proxy'ye temel trafik yakalama

Diyelim proxy adresi 203.0.113.10, port 8080. Bizimle proxy arasında gidip gelen her şeyi dosyaya yazalım:

sudo tcpdump -i any -nn -s 0 -w proxy.pcap 'host 203.0.113.10 and port 8080'

Anahtarların açıklaması:

  • -i any - tüm arayüzleri dinle. Trafiğin hangisinden çıktığını bilmediğinizde kullanışlıdır. Biliyorsanız belirtmek daha iyidir: -i eth0 veya -i wlan0. macOS'ta -i any desteklenmez, en0 belirtin.
  • -nn - IP'leri isimlere ve portları servis adlarına çözümleme. Çözümleme yakalamayı yavaşlatır ve ağa ekstra DNS sorguları ekler.
  • -s 0 - paketi tamamen yakala. Modern sürümlerde bu varsayılan değerdir ama açıkça belirtmek zarar vermez.
  • -w proxy.pcap - ekrana değil, pcap formatında dosyaya yaz. Döküm ancak bu şekilde sonradan Wireshark'ta açılabilir.
  • Tek tırnak içindeki filtre - bu BPF yakalama filtresidir. Gereksiz her şeyi daha çekirdekte keser, dolayısıyla dosya yalnızca gerekli olanı içerir.

Host ve port filtreleri

Birkaç proxy veya port havuzu:

sudo tcpdump -i eth0 -nn -w proxy.pcap 'host 203.0.113.10 and portrange 10000-10100'

Alan adıyla proxy (tcpdump başlangıçta bir kez çözer, ki bu döner adresler için her zaman uygun değildir):

sudo tcpdump -i eth0 -nn -w proxy.pcap 'host proxy.example.net and port 8080'

Çok miktarda trafikte el sıkışmalara ve kopmalara bakmak için yalnızca veri içermeyen servis paketlerini yakalama:

sudo tcpdump -i eth0 -nn -w flags.pcap 'host 203.0.113.10 and tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'

Her iki yönde yalnızca RST:

sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'

Uzak sunucuda döküm alırken kendi SSH oturumunuzu hariç tutarak dökümü kirletmeme:

sudo tcpdump -i eth0 -nn -w proxy.pcap 'host 203.0.113.10 and not port 22'

Gigabaytları doldurmamak: boyut ve zaman rotasyonu

Hata seyrekse ve saatte bir tekrarlanıyorsa, döküm uzun süre dönmelidir. Rotasyon olmadan disk dolar. Boyut rotasyonu, dosya başına 100 MB, 10 dosyadan oluşan halka:

sudo tcpdump -i eth0 -nn -w proxy-%Y%m%d-%H%M%S.pcap -C 100 -W 10 'host 203.0.113.10 and port 8080'

Burada -C boyutu milyon bayt olarak belirler, -W dosya sayısını sınırlar: on birinci dosya birinciyi üzerine yazar. Zaman rotasyonu, her 10 dakikada yeni dosya, son 24 dosyayı sakla (4 saat):

sudo tcpdump -i eth0 -nn -w proxy-%Y%m%d-%H%M%S.pcap -G 600 -W 24 'host 203.0.113.10 and port 8080'

-G anahtarı saniye cinsinden aralığı belirtir ve dosya adındaki zaman şablonu zorunludur, aksi halde tcpdump tek dosyanın üzerine yazar. Faydalı anahtar -Z kullanıcı arayüzü açtıktan sonra yetkileri düşürür ve -U paketleri arabellek olmadan hemen dosyaya yazar, bu da dosyayı paralel okurken veya ani çökmede kuyruğu kaybetmek istemiyorsanız önemlidir.

Yükün kısaltılması

Hacmi azaltmanın bir başka yolu da yalnızca başlıkları yakalamaktır. Kopma teşhisi için TLS kayıtlarının içeriği gerekli değildir, her paketin ilk 128 baytı yeterlidir:

sudo tcpdump -i eth0 -nn -s 128 -w headers.pcap 'host 203.0.113.10'

Dikkat: -s 128 ile CONNECT satırı ve başlıklar kesilebilir ve Wireshark paketleri truncated olarak işaretler. Tam TLS el sıkışma analizi için bu yetersizdir, ClientHello genellikle 300-600 bayt veya daha fazlasını kaplar. Uzlaşma -s 600'dür.

Dökümü doğrudan konsolda okuma

Wireshark her zaman elinizin altında olmaz ama çabucak göz atmak gerekir. TCP bayraklarını ve mutlak sıra numaralarını göstererek dosyayı okuma:

tcpdump -nn -r proxy.pcap -S -tttt 'tcp[tcpflags] & (tcp-rst|tcp-fin) != 0'

-tttt anahtarı tam tarih ve saati yazdırır, -S mutlak sıra numaralarını gösterir, bu da loglarla eşleştirmeye yardımcı olur. CONNECT satırını ve proxy yanıtını görmek için paket içeriğini ASCII olarak yazdırma:

tcpdump -nn -r proxy.pcap -A 'port 8080' | grep -E 'CONNECT|HTTP/1'

Konsol Wireshark'ı olarak tshark

Sunucuda Wireshark kuruluysa, tshark aynı çözücülere konsoldan erişim sağlar. Tüm CONNECT'lerin ve yanıt kodlarının listesi:

tshark -r proxy.pcap -Y 'http.request.method == "CONNECT" or http.response.code' -T fields -e frame.time -e tcp.stream -e http.request.uri -e http.response.code

RST ile biten akışların listesi, kim gönderdiği belirtilerek:

tshark -r proxy.pcap -Y 'tcp.flags.reset == 1' -T fields -e frame.time_relative -e tcp.stream -e ip.src -e ip.dst

Wireshark: görüntüleme filtreleri, Follow TCP Stream, şifre çözmeden TLS okuma

pcap'i Wireshark'ta açtınız ve binlerce satır gördünüz. Nereden başlamalı? Görüntüleme filtrelerinden. Yakalama BPF filtrelerinden farklı olarak bunlar yazılmış dosya üzerinde çalışır ve protokol yapısını anlar.

Proxy üzerinden çalışmak için temel filtreler

Proxy ile ilgili her şey:

ip.addr == 203.0.113.10 && tcp.port == 8080

Tüm CONNECT istekleri:

http.request.method == "CONNECT"

Belirli bir hosta CONNECT:

http.request.method == "CONNECT" && http.host contains "api.example.com"

200 dışındaki proxy yanıtları (yetkilendirme hatası 407, erişilemezlik 502, zaman aşımı 504):

http.response.code >= 400 && tcp.port == 8080

Yalnızca 407 yanıtları, hatalı kimlik bilgileri veya tükenmiş limit işareti:

http.response.code == 407

Tünel içindeki TLS filtreleri

Wireshark, 200 yanıtlı CONNECT'ten sonra TLS'in başladığını tanır ve TLS çözücüsünü otomatik atar. Tanımazsa (kesilmiş paketlerde olur), pakete sağ tıklayıp Decode As seçin ve bu port için TLS belirtin.

Tüm ClientHello'lar:

tls.handshake.type == 1

Belirli SNI'li ClientHello:

tls.handshake.extensions_server_name contains "example.com"

ServerHello (ClientHello'dan sonra yoksa sunucu tarafından el sıkışma başlamamış demektir):

tls.handshake.type == 2

TLS uyarıları:

tls.alert_message

ClientHello olup ServerHello olmayan akışı tek filtreyle bulmak daha zordur; en pratik yol Statistics > Conversations, paket sayısına göre sırala ve 5-7 paketli akışlara bak.

TCP sorunlarına göre filtreler

RST içeren tüm paketler:

tcp.flags.reset == 1

Proxy'nin bize gönderdiği RST'ler:

tcp.flags.reset == 1 && ip.src == 203.0.113.10

Bizim gönderdiğimiz RST'ler:

tcp.flags.reset == 1 && ip.dst == 203.0.113.10

Yeniden iletimler:

tcp.analysis.retransmission

Sıfır pencere ve sonuçları:

tcp.analysis.zero_window || tcp.analysis.window_full

Wireshark'ın kendi fark ettiği tüm anormallikler (yeniden iletimler, yinelenen ACK'lar, kayıp segmentler, sıfır pencere):

tcp.analysis.flags && !tcp.analysis.window_update

Yanıtsız SYN, yani tekrarlanan SYN'ler:

tcp.flags.syn == 1 && tcp.flags.ack == 0 && tcp.analysis.retransmission

Akış içinde 5 saniyeden büyük duraklamalar:

tcp.time_delta > 5

Bu filtre için Edit > Preferences > Protocols > TCP > Calculate conversation timestamps seçeneğini açmanız gerekir.

Follow TCP Stream

Şüpheli bir paket buldunuz, örneğin RST. Sağ tıklayın > Follow > TCP Stream. Wireshark bu bağlantının tüm diyalogunu metin olarak gösterir: bizim trafiğimiz bir renkte, proxy'nin trafiği başka bir renkte. CONNECT üzerinden HTTPS için CONNECT satırını, 200 Connection established yanıtını, sonrasında okunamaz TLS baytlarını görürsünüz. Bu normaldir. Bakılacak şey hacimlerdir: bizden ne kadar bayt gitti (ClientHello'muz ve isteklerimiz), ne kadar geldi (ServerHello ve yanıt) ve her şey nerede bitti.

Follow penceresinin altında sayaçlar var: şu kadar bayt istemci, şu kadar bayt sunucu. 200 yanıtından sonra sunucudan 0 bayt geldiyse, hedef sunucu ClientHello'ya hiç yanıt vermemiştir. Yaklaşık 100-4000 bayt gelip kesildiyse, el sıkışma başlamış ama tamamlanmamıştır. On binlerce bayt gelip sonra kopma olduysa, sorun veri aktarımının ortasındadır.

Faydalı bir alışkanlık: akış numarasına göre filtreleyin. Follow sonrasında filtre satırına otomatik olarak tcp.stream eq 42 gelir. Follow penceresini kapatın, ana listede yalnızca bu akış bayraklar ve zamanlamalarla kalır. Kopma analizi için en kullanışlı görünüm budur.

TLS el sıkışmasını şifre çözmeden okuma

ClientHello'yu paket ağacında açın. Bakılacaklar:

  • Version ve supported_versions - istemci TLS 1.3 öneriyor mu. Sunucu 1.3 istiyor ama istemci yalnızca 1.2 öneriyorsa sunucu protocol_version uyarısıyla ya da sadece FIN ile kapatır.
  • server_name - SNI, CONNECT'teki host ile eşleşiyor mu. Farklılık, yanlış istemci yapılandırmasında olur ve sertifika hatalarına yol açar.
  • Cipher Suites - şifre listesi. Çok kısa veya eskimiş liste, handshake_failure uyarısının nedenidir.
  • ALPN - istemci h2 öneriyor mu. Sunucu h2 seçtiyse ama istemci içeride HTTP/1.1 bekliyorsa uygulama anlaşılmaz hatalarla çökebilir.

ServerHello'da seçilen sürüme ve şifreye bakın. TLS 1.2'de sonrasında Certificate açık şekilde gelir, adı ve geçerlilik süresi kontrol edilebilir. TLS 1.3'te ServerHello'dan sonra neredeyse her şey şifreli ve okunabilen bir sonraki şey kayıt tipidir. Application Data, el sıkışmanın başarıyla tamamlandığı ve verinin başladığı anlamına gelir. ServerHello'dan hemen sonra ya da onun yerine 2 baytlık Alert gelmesi bir şeylerin ters gittiği anlamına gelir: TLS 1.3'te anahtarlar olmadan uyarı kodunu göremezsiniz, ama gerçeğin kendisi zaten bilgilendiricidir.

Statistics > Conversations > TCP'de genel tabloyu değerlendirmek rahattır: kaç akış, her yöne kaç bayt, süre. 0,05 saniye süreli ve 6 paketli akışlar büyük olasılıkla el sıkışmadan hemen sonra sıfırlanmış bağlantılardır.

Döküm üzerinden teşhis: RST, FIN, retransmission, zero window

Şimdi asıl konuya. Bölge A dökümünden tam olarak nerede koptuğunu nasıl anlarız? Her işareti ve proxy bağlamındaki yorumunu inceleyelim.

Yön matrisi

İlk soru her zaman aynıdır: kapatma paketini kim gönderdi? Dökümde bu ip.src alanıdır. Yalnızca iki seçenek var - bizim adresimiz veya proxy'nin adresi.

  • RST veya FIN bizden - bağlantıyı uygulamamız, işletim sistemimiz ya da hostumuzdaki bir şey kapattı. Proxy ve hedef sunucu burada yer almadı. Tipik nedenler: HTTP istemcisinde zaman aşımı, sürecin ani sonlanması, dosya tanımlayıcılarının tükenmesi, yerel güvenlik duvarı veya antivirüs.
  • RST veya FIN proxy'den - tünel proxy tarafından kapatıldı. Neden ya proxy'nin kendisinde (limitler, politika, boşta kalma zaman aşımı) ya hedef sunucudan aktarılmış ya da proxy ile sunucu arasındaki ağda. Bağlam ve zamanlamayla ayırt ederiz.
  • Ne RST ne FIN, sadece yeniden iletim - paketler bizimle proxy arasında kayboluyor. Hiçbir taraf bağlantıyı kapatmadı, sadece kayıplardan öldü.

200 yanıtı olmadan CONNECT sonrası RST

Tablo: TCP kurulu, CONNECT gönderdik, proxy HTTP yanıtı olmadan RST verdi. Bu davranış genellikle proxy'nin politika seviyesinde reddettiği veya isteği ayrıştıramadığı anlamına gelir. Nedenler: geçersiz hedef port, eşzamanlı bağlantı limiti, hatalı istek formatı. Burada sorun Bölge A'da veya proxy'nin kendisinde. Hedef sunucunun ilgisi yok.

CONNECT'e 502, 503 veya 504 yanıtı

Tablo: CONNECT gitti, N saniye sonra 5xx kodlu HTTP yanıtı geldi. N'e bakın. Yanıt proxy'ye giden RTT düzeyinde geldiyse, proxy anında reddetti - belki DNS adı kendi tarafında çözülemiyor veya adres anında erişilemez (ICMP unreachable). N 10-30 saniye civarındaysa, proxy hedef sunucuya bağlanırken zaman aşımı bekledi: sunucu SYN'e yanıt vermiyor. Her iki durumda da bu Bölge C ve dökümünüz doğru yaptığınızı, proxy'nin imkânsızlığı dürüstçe bildirdiğini kanıtlıyor.

ClientHello'dan hemen sonra FIN veya RST

Tablo: CONNECT - 200 - ClientHello'muz - proxy'ye giden bir RTT artı biraz sonra proxy'den FIN veya RST gelir. Burada iki aday var: hedef sunucu TLS aşamasında bağlantıyı reddetti (SNI hoşuna gitmedi, sürüm, istemci sertifikası eksikliği) ya da sunucunun koruma sistemi ClientHello özelliklerinden bağlantıyı sıfırladı. Anahtar işaret zaman. ClientHello'muz ile kopma arası proxy'ye giden RTT'den belirgin şekilde fazlaysa, demek proxy ClientHello'yu iletmiş ve yanıt almış. Bunu proxy kapatmaya karar vermedi, aktarılmış hedef sunucu tepkisidir.

Proxy'ye giden RTT ile karşılaştırın, bunu TCP el sıkışmasından ölçün: SYN ile SYN-ACK arası süre. Proxy'ye RTT 40 ms ve ClientHello sonrası kopma 200 ms sonra geldiyse, 160 ms'lik fark yaklaşık proxy - sunucu gidiş-dönüş RTT'sidir. Tablo tamamen sunucu reddiyle tutarlıdır.

ServerHello sonrası veya verinin bir kısmından sonra kopma

El sıkışma başladı, sunucu yanıt verdi, veri aktı ve ortada FIN veya RST. Eğer bu FIN ise ve proxy'den geldiyse ve öncesindeki son Application Data kaydı mantıklı bir boyuttaysa, sunucu yanıttan sonra bağlantıyı kapatmış olabilir (TLS içinde Connection: close) ve istemci bunu yanlış yorumlamıştır. Eğer veri akışının ortasında, hızda bir düşüş olmadan RST gelirse bu ya sunucuda zorla kapatmadır ya da proxy tüketim veya oturum ömrü limiti nedeniyle tüneli kesmiştir. Zamanla IP döndüren mobil proxy'lerde ikincisi çok olasıdır: kopma tam IP değişimi anında gerçekleşir. Kopma zamanının proxy ayarlarınızdaki rotasyon aralığıyla örtüşüp örtüşmediğini kontrol edin.

Yeniden iletimler ve yönleri

Wireshark bir paketi aynı sıra numaralarını tekrar gördüğünde retransmission olarak işaretler. Kimin yeniden ilettiğine bakalım:

  • Yeniden ileten biziz - paketlerimiz proxy tarafından onaylanmıyor. Ya proxy'ye giden yolda kayboluyor ya da onaylar dönüş yolunda kayboluyor. Her iki durumda da sorun Bölge A ağında.
  • Yeniden ileten proxy - onun paketleri bizim tarafımızdan onaylanmıyor. Ya biz onları almıyoruz ya da ACK'lerimiz ulaşmıyor. Bu da Bölge A ama gelen yöne doğru.
  • SYN yeniden iletimleri - ayrı bir durum: proxy TCP seviyesinde erişilemez, bağlantı hiç kurulmuyor.

Önemli: Bölge C'deki kayıpları yeniden iletim olarak asla görmezsiniz. Proxy hedef sunucuyla kendi ilgilenir. Bölge C'deki kayıpların tek izi duraklamalardır: proxy bize veriyi düzensiz, boşluklarla aktarır, dökümde yeniden iletim olmasa bile. Proxy'den gelen paketler için tcp.time_delta > 1 filtresi bu duraklamaları gösterir.

Zero Window

Sıfır boyutlu TCP penceresi, alıcının soket arabelleğinden veriyi okuyamadığı anlamına gelir. Sıfır pencereyi biz ilan ediyorsak, uygulamamız yanıtı yeterince hızlı okumuyor demektir: iş parçacığı meşgul, kilitlenmiş, yavaş işliyor. Proxy bu durumda bekler, sonra Zero Window Probe gönderir ve uygulama okumaya başlamazsa birkaç on saniye sonra bağlantıyı kapatabilir. İstemci kopmayı görür ve proxy'yi suçlar, oysa neden istemcidedir.

Proxy sıfır pencere ilan ediyorsa, bizim verimizi ileri iletmeye yetişemiyor - hedef sunucu yavaş alıyor demektir. Bu, Bölge C'deki sorunların dolaylı işaretidir, yavaş bir sunucuya proxy üzerinden büyük dosya yüklerken görülür.

Yinelenen ACK'lar ve SACK

Proxy'den gelen duplicate ACK, sıra dışı bir paket aldığı, bizden bir şeyin kaybolduğu sinyalidir. Çok sayıda duplicate ACK ve ardından gelen yeniden iletimler, bizim tarafımızda mobil veya Wi-Fi ağındaki kayıpların klasik tablosudur. Bizden gelen duplicate ACK'lar - proxy'den paketler kaybolmuş. El sıkışmada SACK seçeneğinin olması TCP'nin daha verimli toparlanmasını sağlar, ama kayıp gerçeği yine de ortadadır.

TTL sezgisi

İleri düzey bir yöntem. Proxy'den gelen normal paketlerdeki IP TTL alanına ve RST paketindekine bakın. RST'deki TTL birkaç birim farklıysa, RST'yi proxy'nin kendisi değil, yolda bir ara düğüm üretti: bir güvenlik duvarı, yük dengeleyici veya operatörün filtreleme sistemi. Bu kesin bir kanıt değil, ama proxy ile sizin aranızdaki yolu kontrol etmeye, proxy'yi veya hedef sunucuyu suçlamamaya dair güçlü bir ipucudur.

Özet yorum tablosu

  • SYN tekrarlanıyor, SYN-ACK yok: proxy erişilemez veya ona giden ağ. Bölge A.
  • SYN - RST: proxy portu kapalı veya filtreleniyor. Bölge A.
  • CONNECT - 407: hatalı yetkilendirme veya hesap limiti. Proxy.
  • CONNECT - hızlı 502/504: proxy sunucuya bağlanmayı başlatamadı. Bölge C, büyük ihtimalle DNS veya rota.
  • CONNECT - 20-30 saniye sonra 504: sunucu proxy'nin SYN'ine yanıt vermiyor. Bölge C.
  • 200 - ClientHello - RTT'den uzun süre sonra RST/FIN: sunucu TLS'i reddetti. Bölge C.
  • 200 - ClientHello - sessizlik - istemci zaman aşımıyla kopma: sunucu TCP'yi kabul ediyor ama TLS'e yanıt vermiyor. Bölge C veya proxy arkasında bloklayıcı filtre.
  • Veri akıyor - sabit bir anda proxy'den RST: limit veya proxy rotasyonu. Proxy.
  • RST olmadan yeniden iletimler ve duplicate ACK'lar: bizimle proxy arasındaki ağda kayıplar. Bölge A.
  • Bizden Zero Window: uygulamamız okumuyor. İstemci.
  • Uzun sessizlikten sonra bizden RST: bizim zaman aşımımız. İstemci.

Kendi trafiğinizi SSLKEYLOGFILE ile şifre çözme

Bazen bayraklar yetmez ve sunucunun TLS içinde tam olarak ne döndürdüğünü görmek gerekir: yanıt kodu, başlıklar, hata gövdesi. Bunun için mitmproxy ve sahte sertifika gerekmez. Kendi istemcinizin oturum anahtarlarını bir dosyaya yazması ve Wireshark'ın bunları şifre çözmek için kullanması yeterlidir. Bu yalnızca kendi istemciniz ve kendi bağlantılarınız için çalışır: anahtarlar yalnızca el sıkışmaya katılan tarafta vardır. Başkasının trafiğini veya proxy'nin Bölge C'de sunucuyla yürüttüğü trafiği bu yöntemle çözmek imkânsızdır ve bu doğrudur.

Farklı istemcilerde nasıl açılır

Chromium ve Firefox tabanlı tarayıcılar SSLKEYLOGFILE ortam değişkenini okur ve oraya NSS Key Log formatında anahtarlar yazar:

export SSLKEYLOGFILE=/home/user/tls-keys.log
google-chrome --proxy-server=http://203.0.113.10:8080

OpenSSL ile derlenmiş curl de bu değişkeni okur:

export SSLKEYLOGFILE=/home/user/tls-keys.log
curl -v -x http://user:pass@203.0.113.10:8080 https://api.example.com/health

Node.js komut satırı anahtarıyla:

node --tls-keylog=/home/user/tls-keys.log app.js

Python değişkeni otomatik okumaz, ama 3.8 sürümünden itibaren SSLContext'te keylog_filename özniteliği var. Bir adaptör üzerinden requests için:

import os, ssl, requests
from requests.adapters import HTTPAdapter

class KeyLogAdapter(HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
ctx = ssl.create_default_context()
ctx.keylog_filename = os.environ.get("SSLKEYLOGFILE")
kwargs["ssl_context"] = ctx
return super().init_poolmanager(*args, **kwargs)

s = requests.Session()
s.mount("https://", KeyLogAdapter())
s.proxies = {"https": "http://user:pass@203.0.113.10:8080"}
r = s.get("https://api.example.com/health", timeout=30)
print(r.status_code)

Go, tls.Config içindeki KeyLogWriter alanıyla:

f, _ := os.OpenFile(os.Getenv("SSLKEYLOGFILE"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
tlsCfg := &tls.Config{KeyLogWriter: f}
tr := &http.Transport{
Proxy: http.ProxyURL(proxyURL),
TLSClientConfig: tlsCfg,
}

Wireshark'ta anahtarları bağlama

İki yol. Birincisi: Edit > Preferences > Protocols > TLS > (Pre)-Master-Secret log filename, anahtar dosyasının yolunu belirtin. Wireshark Client Random eşleşmesini bulduğu tüm akışları şifre çözer. Dosyayı iş arkadaşlarına iletmek için ikinci yol daha güvenlidir: anahtarları doğrudan pcapng içine gömün:

editcap --inject-secrets tls,/home/user/tls-keys.log proxy.pcap proxy-with-keys.pcapng

Sonrasında Wireshark'ta CONNECT tüneli içinde şifre çözülmüş HTTP/1.1 veya HTTP/2 istekleri ve yanıtları görünür. Şifre çözülmüş HTTP/2 için filtre:

http2.header.name == ":status"

Tünel içindeki şifre çözülmüş HTTP/1.1 için normal http.response.code ve http.request.uri filtreleri çalışır.

Proxy üzerinden teşhis için ne sağlar

Şifre çözme son belirsizliği ortadan kaldırır. Sunucunun Retry-After başlığıyla 429 yanıtı verdiğini ve sonra bağlantıyı kapattığını, ya da 200 döndürdüğünü ama gövdenin yüzde 40'ta kesildiğini, ya da isteğin gittiğini ama yanıtın hiç olmadığını görürsünüz. Böyle bir tabloyla proxy desteğine başvuru somut hale gelir: ya sorun açıkça sunucudadır ya da açıkça tüneldedir.

Güvenlik kuralları

  • Anahtar dosyası, kaydedilen oturumları çerezler ve jetonlar dahil tamamen şifre çözmenizi sağlar. Onu bir parola gibi saklayın ve analizden sonra silin.
  • Anahtar dosyasını dökümle birlikte proxy desteğine veya başka birine göndermeyin. Destek kopma analizi için anahtarlara ihtiyaç duymaz, bayraklar ve zamanlamalar yeterlidir.
  • Yine de şifre çözülmüş içeriği göstermeniz gerekirse, bunu hedef hizmette test hesabı ve proxy'nin test kimlik bilgileriyle yapın.
  • Üretimde SSLKEYLOGFILE'i açık bırakmayın. Hizmet yapılandırmasına kazara giren bir ortam değişkeni yıllarca diske anahtar yazar.

Tipik tablolar: bağlantı zaman aşımı, yanıt ortasında kopma, mobil ağda kayıplar

İncelediğimiz işaretleri tanınabilir senaryolarda toplayalım. Her biri, tcp.stream eq N filtresinden sonra Wireshark paket listesinde göründüğü gibi tanımlanmıştır.

Tablo 1: proxy'ye bağlantı zaman aşımı

0.000 client -> proxy [SYN]
1.002 client -> proxy [SYN] (TCP Retransmission)
3.006 client -> proxy [SYN] (TCP Retransmission)
7.010 client -> proxy [SYN] (TCP Retransmission)
15.02 client -> proxy [SYN] (TCP Retransmission)

Proxy'den tek paket yok. Üstel aralıklar 1, 2, 4, 8 saniye - Linux çekirdeğinin standart retransmission backoff'u. Teşhis: proxy sizin noktanızdan erişilemez. Adresi, portu, güvenlik duvarını, yönlendirmeyi kontrol edin ve proxy adresinin değişip değişmediğine bakın. Özel portlu bir mobil Proxeon proxy'siyse, portun kişisel panelinizdekiyle eşleştiğinden emin olun.

Tablo 2: proxy'nin hedef sunucuya bağlantı zaman aşımı

0.000 client -> proxy [SYN]
0.041 proxy -> client [SYN, ACK]
0.041 client -> proxy [ACK]
0.042 client -> proxy CONNECT api.example.com:443 HTTP/1.1
0.083 proxy -> client [ACK]
30.10 proxy -> client HTTP/1.1 504 Gateway Timeout
30.10 proxy -> client [FIN, ACK]

Proxy'ye RTT 41 ms, proxy CONNECT'i aldığını onayladı, sonra 30 saniye sustu ve 504 döndü. Teşhis: hedef sunucu proxy'nin bağlantı girişimine yanıt vermiyor. Olası nedenler - sunucu yatıyor, port proxy adres havuzuna kapalı, proxy - sunucu rotasında ağ sorunları. İstemciniz ve ağınızın ilgisi yok.

Tablo 3: sunucu TLS'i reddediyor

0.000 client -> proxy CONNECT api.example.com:443 HTTP/1.1
0.045 proxy -> client HTTP/1.1 200 Connection established
0.046 client -> proxy TLSv1.3 Client Hello (SNI=api.example.com)
0.210 proxy -> client [FIN, ACK]
0.210 client -> proxy [FIN, ACK]

Proxy'ye RTT 45 ms iken ClientHello'dan 164 ms sonra kopma. Fark yaklaşık 120 ms - proxy'nin ClientHello'yu sunucuya ilettiği ve kapanışı aldığı süre. Teşhis: sunucu TCP'yi kabul etti ama TLS aşamasında bağlantıyı kapattı. El sıkışma parametrelerini kontrol edin: sürümler, şifreler, SNI, ALPN. ServerHello yoksa ve uyarı da yoksa sunucu bağlantıyı sessizce kapatmıştır, bunu genellikle alışılmadık ClientHello'da koruma sistemleri yapar.

Tablo 4: yanıt ortasında kopma

0.000 client -> proxy CONNECT cdn.example.com:443 HTTP/1.1
0.044 proxy -> client HTTP/1.1 200 Connection established
0.045 client -> proxy Client Hello
0.190 proxy -> client Server Hello, Change Cipher Spec, Application Data
0.195 client -> proxy Application Data (request)
0.350 proxy -> client Application Data (1460 bytes)
... ещё 340 пакетов данных
4.812 proxy -> client Application Data (1460 bytes)
4.813 proxy -> client [RST, ACK]

El sıkışma geçti, yaklaşık 500 KB veri geldi ve yavaşlama olmadan, yeniden iletim olmadan, sıfır pencere olmadan RST geldi. Mutlak zamana bakın. Mobil proxy'de IP rotasyonu anıyla veya oturum süresi limitinin dolmasıyla örtüşüyorsa neden proxy'dedir ve çözüm rotasyon aralığını isteklerinizin süresiyle hizalamak veya uzun indirmeler sırasında rotasyonsuz mod kullanmaktır. Örtüşme yoksa kopma büyük olasılıkla sunucu veya CDN tarafındadır. Burada SSLKEYLOGFILE ile şifre çözme yardımcı olur: içeride Content-Length başlığı görünüyor ve gövde tam gelmemişse sunucu aktarımı kesmiştir.

Tablo 5: istemci tarafında mobil ağda kayıplar

0.000 client -> proxy Application Data (1460 bytes)
0.001 client -> proxy Application Data (1460 bytes)
0.002 client -> proxy Application Data (1460 bytes)
0.180 proxy -> client [ACK] (Dup ACK 1)
0.181 proxy -> client [ACK] (Dup ACK 2)
0.182 proxy -> client [ACK] (Dup ACK 3)
0.183 client -> proxy Application Data (TCP Fast Retransmission)
0.420 client -> proxy Application Data (TCP Retransmission)
0.900 client -> proxy Application Data (TCP Retransmission)

Proxy'den duplicate ACK'lar, ardından bizden artan aralıklarla yeniden iletimler. Ne RST ne FIN. Teşhis: istemci - proxy yolunda kayıplar. İstemci kendisi hücresel ağ veya Wi-Fi üzerinden bağlıysa, baz istasyonları arasında geçiş anlarında bu beklenir. Çözüm istemci zaman aşımlarını artırmak, TCP keepalive açmak, uzun boşta duran bağlantılar tutmamaktır, çünkü operatör NAT'ları idle bağlantı kayıtlarını genellikle 30-300 saniye içinde düşürür ve bir sonraki paket boşluğa gider. Kayıpların boyutunu değerlendirme filtresi:

tcp.analysis.retransmission && ip.dst == 203.0.113.10

Bu paketlerin toplam içindeki yüzdesini Statistics > Capture File Properties üzerinden hesaplayın. Yüzde bir-iki mobil ağ için katlanılabilir, yüzde beşten fazlaysa sorunu radyo koşullarında veya ekipmanda arayın.

Tablo 6: kendi zaman aşımımız

0.000 client -> proxy CONNECT api.example.com:443 HTTP/1.1
0.044 proxy -> client HTTP/1.1 200 Connection established
0.045 client -> proxy Client Hello
0.200 proxy -> client Server Hello ... Application Data
0.205 client -> proxy Application Data (request)
0.250 proxy -> client [ACK]
10.21 client -> proxy [FIN, ACK]
10.25 proxy -> client [FIN, ACK]

İstek gitti, proxy onayladı, yanıt gelmedi ve tam 10 saniye sonra FIN'i biz gönderdik. Bu bizim read timeout'umuz. İstemci logundaki hata kopma gibi görünecek, ama dökümden belli: bağlantıyı biz kendimiz kapattık çünkü sunucu beklemeye hazır olduğumuzdan daha yavaş düşündü. Çözüm ya zaman aşımını artırmak ya da sunucunun neden yavaş olduğunu çözmektir, ama proxy burada sadece bizimle birlikte dürüstçe bekledi.

Döküm alırken ve okurken tipik hatalar

Deneyimli mühendislerin bile düzenli takıldığı noktaları sıralayalım.

  • Yüklü makinede yakalama filtresi olmadan döküm almak. Bir dakikada gigabayt birikir, gerekli 200 paketi içinde aramak rahatsızdır. Her zaman proxy hostuna göre filtreleyin.
  • Hedef sunucunun adresine göre filtrelemek. Proxy üzerinden böyle paketler makinenizde yoktur. Filtre boş döner ve kişi trafiğin akmadığına karar verir. Akıyor ama proxy'ye.
  • Yakalama filtresi ile görüntüleme filtresini karıştırmak. tcpdump'taki BPF sözdizimi (host, port, tcp[tcpflags]) ile Wireshark sözdizimi (ip.addr, tcp.port, tcp.flags.reset) farklıdır. Wireshark filtresi tcpdump'ta sözdizimi hatası verir ve tersi de geçerlidir.
  • Proxy'den gelen RST'ye bakıp hemen proxy'yi suçlamak. Proxy adresinden gelen RST tünelin kapatılmasıdır, suç kabulü değil. Zamanlamalara ve RST'den öncesine bakın.
  • RTT'yi görmezden gelmek. Proxy'ye ölçülmüş gecikme olmadan, anlık proxy reddini aktarılmış sunucu reddinden ayırt etmek mümkün değildir.
  • -s 64 ile döküm alıp sonra CONNECT'i okumaya çalışmak. Başlıklar kesilir. Proxy teşhisi için tam yakalama veya en azından -s 600 gerekir.
  • Saati senkronize etmemek. Döküm alan makinede saat bir dakika geriyse dökümü destek loglarıyla eşleştirmek mümkün olmaz. NTP'yi açın ve başvuruda UTC belirtin.
  • Proxy kimlik bilgileriyle döküm göndermek. Proxy'ye açık HTTP isteğindeki Proxy-Authorization başlığı kullanıcı adı ve parola içerir. Ya test verileriyle döküm alın ya da gönderdikten sonra parolayı değiştirin.
  • Anahtar dosyasını dökümle birlikte göndermek. Bu oturumların tüm içeriğini açar. Destek kopma analizi için anahtarlara ihtiyaç duymaz.
  • Rotasyonsuz tek uzun döküm tutmak. Disk en uygunsuz anda dolar ve tcpdump gerekli paketlerle birlikte düşer.
  • QUIC sızıntısını kontrol etmemek. Doğrudan 443'e UDP, trafiğin bir kısmının proxy'yi atladığının işaretidir ve TCP tüneli üzerinden teşhis bir şey göstermez.
  • Segmentation offload'u unutmak. Sanal makinede dökümdeki 60 KB boyutlu paketler yanlış MTU anlamına gelmez. Bu çekirdeğin tcpdump'a henüz bölünmemiş segmentleri vermesidir.

Araçlar ve kaynaklar

Anlatılan yöntem için asgari set.

Yakalama

  • tcpdump - Linux ve macOS'ta standart. Neredeyse her yerde kurulu, root veya CAP_NET_RAW yeteneği gerektirir.
  • dumpcap - Wireshark paketinden konsol yakalayıcı, aynı rotasyon anahtarlarını (-b filesize, -b files) ve pcapng formatını destekler.
  • Npcap'li Wireshark - Windows için. Doğrudan GUI'den aynı BPF sözdizimiyle yakalama filtresiyle yakalanabilir.
  • tshark - Wireshark çözücüleriyle konsol analizi, grafik olmayan sunucularda ve otomasyon için kullanışlıdır.

Analiz

  • Wireshark - ana araç. Follow TCP Stream, Expert Info, Statistics > Conversations, duraklamaları ve yeniden iletim dalgalanmalarını görselleştirmek için IO Graph.
  • editcap - pcap dilimleme ve filtreleme, pcapng içine TLS anahtarları gömme.
  • mergecap - analiz için rotasyon dosyalarını birleştirme.
  • capinfos - dosya hakkında hızlı özet: süre, paket sayısı, boyut.

Hata ayıklama destekli istemciler

  • curl -v ve --trace-time anahtarlarıyla, dökümün tablosunu uygulama seviyesinde yineler ve SSLKEYLOGFILE'ı destekler.
  • openssl s_client -proxy host:port proxy üzerinden CONNECT ve TLS el sıkışmasını manuel yapmanıza ve sunucunun yanıtını HTTP istemcisi olmadan görmenize izin verir.

Faydalı tek satırlıklar

Rotasyon dosyalarını birleştir:

mergecap -w all.pcapng proxy-*.pcap

Dökümden yalnızca tek bir akışı desteğe göndermek için ayıkla:

tshark -r all.pcapng -Y 'tcp.stream eq 42' -w stream42.pcapng

RST'li akışlar hakkında hızlı istatistik:

tshark -r all.pcapng -q -z conv,tcp | head -40

openssl ile manuel CONNECT kontrolü:

openssl s_client -proxy 203.0.113.10:8080 -connect api.example.com:443 -servername api.example.com -brief

Vakalar ve sonuçlar

Vaka 1: yüzde iki kopma, suçlu istemci çıktı

Bir fiyat toplama servisi mobil proxy havuzu üzerinden çalışıyordu, günde yaklaşık 40 bin istek. İsteklerin yaklaşık yüzde 2,3'ü RemoteDisconnected ile düşüyordu. Ekip proxy'lerin suçlu olduğundan emindi. Bir günlük, 100 MB'lık rotasyonlu döküm alındı, tcp.flags.reset == 1 ile filtrelendi ve ip.src'e bakıldı. Vakaların yüzde 91'inde RST'yi istemcinin kendisi gönderiyordu. Akış incelemesi gösterdi: RST'den önce istediğin gönderilmesinden tam 5 saniye sonra sessizlik, ardından istemciden RST. Kodda read timeout 5 saniyeydi, hedef sunucu yoğun saatlerde 6-8 saniyede yanıtlıyordu. Zaman aşımını 15 saniyeye çıkarmak hataları yüzde 0,3'e düşürdü. Kalan yüzde 0,3 adres havuzunun bir kısmından ClientHello'dan 160-200 ms sonra gelen gerçek FIN'lerdi. Bu veriler desteğe iletildi, onlar da kendi Bölge C loglarıyla tabloyu doğruladı.

Vaka 2: büyük indirmelerde tam 10 dakikada bir kopmalar

İstemci mobil proxy üzerinden 300-800 MB'lık arşivler indiriyor ve ortada kopmalardan şikâyet ediyordu. Döküm, indirmenin başlamasından bağımsız olarak birbirinden tam saniyesi saniyesine 600 saniye arayla proxy'den RST'ler gösterdi. Neden, her 10 dakikada bir planlı IP rotasyonuydu: adres değişiminde proxy aktif tünelleri kapatıyor. Çözüm portu istek üzerine rotasyona çevirmek ve adres değişimini indirmeler arasında başlatmak oldu. Kopmalar tamamen kayboldu, haftalarca yazışma yerine iki saatlik teşhis yetti.

Vaka 3: sunucu yatıyor, ama proxy suçlu gibi görünüyor

Sabah bir API'ye yapılan tüm istekler bağlantı hatası vermeye başladı. İstemci logları: Connection aborted. İlk tepki - proxy düştü. Bir dakikalık döküm gösterdi: proxy ile TCP 38 ms'de kuruluyor, CONNECT gidiyor ve 30 saniye sonra 504 ile FIN geliyordu. Aynı proxy üzerinden başka bir hosta yapılan istek 300 ms'de geçiyordu. Teşhis: hedef sunucu proxy'den bağlantı kabul etmiyor. 40 dakika sonra hedef servisin durum sayfası kendi taraflarındaki olayı doğruladı. Döküm sabahı kurtardı ve proxy desteğine yanlış bir talep açılmasını önledi.

Vaka 4: Wi-Fi kayıpları proxy sorunu gibi görünüyordu

Bir geliştirici dizüstü bilgisayardan mobil Proxeon proxy'si üzerinden entegrasyonu test ediyor ve aralıklı zaman aşımları alıyordu. Döküm, istemciden yüzde 6 oranında yeniden iletim ve proxy'den duplicate ACK gösterdi, ancak proxy'den hiç RST yoktu. Dizüstünü kabloya bağlamak yeniden iletimleri sıfıra indirdi, zaman aşımları kayboldu. Sorun ofisin aşırı yüklü erişim noktasındaydı.

Destek ekibine başvuru için döküm alma kontrol listesi

Dökümü bir proxy servisi desteğine göndermeyi planlıyorsanız, her iki tarafın zamanını kurtaracak adımlar sırası.

Hazırlık

  1. Makinede saatleri NTP üzerinden senkronize edin. timedatectl veya date -u ile kontrol edin.
  2. Mümkünse teşhis süresince proxy için ayrı test kimlik bilgileri alın veya dökümü gönderdikten sonra parolayı değiştirmeyi planlayın.
  3. İstemci sürümünü, HTTP kütüphanesini, işletim sistemini, internete bağlantı yöntemini (kablo, Wi-Fi, hücresel ağ) kaydedin.
  4. Proxy adresini ve portunu, hedef hostu, beklenen ve gerçekleşen davranışı yazın.

Yakalama

  1. tcpdump'ı proxy hostu ve portu filtresiyle, rotasyonlu, tam paket boyutuyla başlatın:
sudo tcpdump -i eth0 -nn -s 0 -U -w proxy-%Y%m%d-%H%M%S.pcap -G 300 -W 48 'host 203.0.113.10 and port 8080'
  1. Sorunu yeniden üretin. Seyrek oluşuyorsa yakalamayı gerekli süre boyunca bırakın; 5 dakikalık 48 dosya 4 saati kapsar.
  2. Yakalamayla eşzamanlı olarak curl ile -v ve --trace-time kullanarak bir kontrol isteği yapın, çıktıyı kaydedin. Bu, zamanı paketlere kesin bağlar.
  3. İstemci loglarındaki her hata anının kesin saatini (UTC) kaydedin.
  4. tcpdump'ı Ctrl+C ile durdurun. Dosyaların boş olmadığından emin olun: capinfos proxy-*.pcap.

İşleme

  1. Dosyaları birleştirin: mergecap -w all.pcapng proxy-*.pcap.
  2. Sorunlu akışları tcp.flags.reset == 1 filtresi veya loglardaki zamanla bulun.
  3. Yalnızca gerekli akışları ayıklayın: tshark -r all.pcapng -Y 'tcp.stream in {12 47 93}' -w report.pcapng. Desteğe saatlerce normal trafik gerekmez.
  4. Ayıklanan dökümde gereksiz bir şey olmadığını kontrol edin: başka bağlantılar, diğer servislerin trafiği.
  5. TLS anahtar dosyasını eklemeyin.

Başvuru metni

  • Olayın UTC cinsinden saniyesine kadar zamanı.
  • Proxy adresi ve portu, hedef host.
  • Kısa yorum: dökümde ne gördüğünüz (örneğin CONNECT'e 200, ardından ClientHello'dan 170 ms sonra proxy'den FIN, proxy'ye RTT 45 ms).
  • Eklenen dosyadaki kare veya akış numaraları.
  • Zaman damgalı curl -v çıktısı.
  • Şimdiye kadar kontrol edip hariç tuttuklarınız: aynı proxy üzerinden başka host, başka bağlantı üzerinden aynı host.

Böyle bir başvuruyu destek tek seferde işler. Ona zaman damgalarınızı Bölge C loglarıyla karşılaştırıp versiyonu doğrulamak veya çürütmek yeter.

SSS

Dökümde hedef sunucunun IP adresi neden yok, ben ona istek yapıyorum ya?

Çünkü ona doğrudan değil, proxy üzerinden istek yapıyorsunuz. İstemciniz proxy adresiyle TCP bağlantısı kurar ve ondan hedef hosta bağlanmasını ister. Proxy - sunucu bağlantısı yalnızca proxy tarafında vardır. Dökümde hedef hostun adı CONNECT satırında ve ClientHello içindeki SNI'de görünür, ama makinenizden onun IP'sine giden paketler yoktur ve olamaz.

Dökümden proxy'nin sunucuya giderken hangi dış IP'yi kullandığı anlaşılabilir mi?

Hayır. Bu bilgi Bölge C'ye aittir. Tek yol, proxy üzerinden istemci adresini döndüren bir servise istek yapmak ya da sağlayıcının panelinden o anda hangi adresin aktif olduğuna bakmaktır.

Proxy RST gönderdi. Yani sorun proxy'de mi?

Şart değil. Proxy adresinden gelen RST, tünelin proxy tarafından kapatıldığı anlamına gelir, neden hedef sunucuda veya proxy arkasındaki ağda olabilir. Zamanlamaya bakın: son paketinizden sonra proxy'ye RTT'yi belirgin şekilde aşan bir süre sonra RST geldiyse, büyük olasılıkla proxy sunucunun tepkisini aktarmıştır. RST sabit bir anda veya kesin bir aralıktan sonra geldiyse, muhtemelen proxy'nin kendi politikasıdır, örneğin rotasyon veya limit.

Dökümden proxy'ye RTT nasıl ölçülür?

Herhangi bir bağlantının başında sizden gelen SYN ile proxy'den gelen SYN-ACK arasındaki zaman farkı. Wireshark'ta bir akış için Statistics > TCP Stream Graphs > Round Trip Time açabilir veya sütun olarak tcp.analysis.ack_rtt alanını kullanabilirsiniz.

Wireshark tünel içindeki TLS'i göstermiyor, sadece TCP verisi var. Ne yapmalı?

200 Connection established yanıtından sonraki bir pakete sağ tıklayın, Decode As seçin, Current sütununda TCP proxy portu için TLS seçin. Ayrıca paketlerin kesilmediğinden (yakalamada -s 0) ve proxy portu standart değilse HTTP çözücüsünün porta ayarlandığından emin olun: Edit > Preferences > Protocols > HTTP > TCP ports.

Bu yaklaşımın mitmproxy'den farkı ne?

mitmproxy uygulama seviyesinde çalışır: sahte sertifikayla TLS'i sonlandırır, HTTP isteklerini okur ve değiştirebilir. Bunun için istemci onun kök sertifikasına güvenmelidir. tcpdump ve Wireshark paket seviyesinde çalışır ve hiçbir şeyi değiştirmez: gerçek paketleri, gerçek bayrakları ve zamanlamaları görürsünüz, mitmproxy'nin gizleyeceği TCP hataları dahil, çünkü onları kendi işlerdi. Kopma teşhisi için paket seviyesi daha dürüsttür. İstek içeriğini görmek için mitmproxy daha kolaydır, ama istenirse kendi trafiğinizin içeriği sertifika değiştirmeden SSLKEYLOGFILE ile Wireshark'ta da görülebilir.

Wireshark'ta proxy'nin sunucuyla yürüttüğü trafiği şifre çözebilir miyim?

Hayır. Ne o bağlantının paketleri ne de anahtarları sizde. SSLKEYLOGFILE yalnızca kendi istemcinizin oturumlarının anahtarlarını verir ve CONNECT tüneli içinde bu tam da sizin sunucuyla olan oturumunuzdur, dolayısıyla şifresi çözülebilir. Ama CONNECT durumunda proxy ile sunucu arasında ayrı bir TLS yoktur: proxy sadece sizin baytlarınızı iletir.

İstemcinin proxy'yi atlayarak trafik sızdırdığını nasıl anlarım?

Proxy'ye göre filtre olmadan, tüm arayüzünüze göre filtreyle bir döküm alın ve proxy dışındaki adreslere giden 80 ve 443 portu bağlantılarına, ayrıca UDP 443 (QUIC) ve hedef host adlarıyla dış çözümleyicilere giden DNS sorgularına bakın. Wireshark filtresi: (tcp.port == 443 || udp.port == 443) && !(ip.addr == 203.0.113.10). Herhangi bir eşleşme yapılandırma sızıntısıdır.

Destek için döküm ne kadar büyük olmalı?

Ne kadar küçük olursa o kadar iyi. Ayıklanan tek sorunlu akış 5 KB ile 500 KB arasında yer kaplar. 50 MB'tan büyük bir dosyayı destek daha uzun inceler ve bu hacmin yarısı normal trafik olur. Gerekli akışları tshark ile veya Wireshark'ta File > Export Specified Packets ile ayıklayın.

Sanal makinede tcpdump MTU'dan büyük paketler gösteriyorsa ne yapmalı?

Bu generic segmentation offload: çekirdek, ağ kartı dilimlemeden önce tcpdump'a büyük segmentleri veriyor. Bayrak, zamanlama ve kopma analizini etkilemez. Rahatsız ediyorsa yakalama süresince ethtool -K eth0 gso off tso off gro off komutuyla offload'u kapatın, ama bunun ağ performansını düşüreceğini unutmayın.

Sonuç

Proxy üzerinden trafik dökümü, içeriği gözetlemek veya sihir değildir. Bu, telde gerçekten olanların dürüst kaydıdır: milisaniyesine ve her bayrağa kadar. İstemci logları bağlantının koptuğunu söyler. Döküm kimin yaptığını, tam olarak ne zaman ve öncesinde ne olduğunu söyler.

Yöntemi özetleyelim. İstemci makinede yalnızca proxy'ye olan bağlantıyı görürsünüz: TCP el sıkışması, CONNECT veya SOCKS diyaloğu ve tünel içindeki şifreli TLS kayıtları. Hedef sunucu doğrudan görünmez, ama davranışı proxy tarafından CONNECT'e verilen yanıt kodları, zamanlamalar ve tüneli kapatma biçimiyle aktarılır. Adresinizden gelen RST veya FIN - sizin sorununuz veya zaman aşımınız. Kapanma olmadan yeniden iletimler ve duplicate ACK'lar - proxy'ye giden yolda kayıplar. Proxy'den, ona giden RTT'nin katları sonra gelen kapanma - aktarılmış sunucu tepkisi. Sabit anlardaki kapanmalar - proxy politikası. Sizden Zero Window - uygulamanız okumuyor.

Bugün atılacak pratik adımlar: bu yazıdaki rotasyonlu tcpdump komutlarını ve Wireshark filtrelerini yer imlerine ekleyin; istemcilerinizin çalıştığı makinelerde saatlerin senkronize olup olmadığını kontrol edin; istemcinizde proxy'yi atlayan QUIC sızıntısı olmadığından emin olun; dökümlerde çalışma bilgilerinizi açığa çıkarmamak için teşhis amaçlı test kimlik bilgileri edinin. Ve bir dahaki sefere loglar connection reset by peer dediğinde tahmin etmeyin. Döküm alın, akışı açın, yöne ve zamana bakın. Beş dakika içinde kime yazacağınızı biliyor olacaksınız: kendinize, proxy desteğine veya hedef sunucunun sahibine.