tcpdump und Wireshark bei der Arbeit über einen Proxy: Paketmitschnitt und Fehlerdiagnose
Inhalt des Artikels
- Einführung: wenn die client-logs nicht mehr ausreichen
- Grundlagen: was vor dem proxy, im tunnel und danach sichtbar ist
- Deep dive: warum der proxy nicht mehr zeigen kann und wie man indirekte hinweise liest
- Tcpdump in der praxis: filter, dateiausgabe, rotation
- Wireshark: anzeigefilter, follow tcp stream, tls ohne entschlüsselung lesen
- Diagnose anhand des mitschnitts: rst, fin, retransmission, zero window
- Eigenen traffic über sslkeylogfile entschlüsseln
- Typische bilder: verbindungs-timeout, abbruch mitten in der antwort, verluste im mobilfunknetz
- Typische fehler beim erstellen und lesen von mitschnitten
- Werkzeuge und ressourcen
- Fallstudien und ergebnisse
- Checkliste zum erstellen eines mitschnitts für den support
- Faq
- Fazit
Wenn eine Anwendung über einen Proxy läuft und etwas schiefgeht, ist das Erste, was ein Entwickler öffnet, das Client-Log. Dort steht so etwas wie connection reset by peer, read timeout oder einfach EOF. Das Problem: Diese Zeilen verraten fast nichts über die Ursache. Wer hat die Verbindung abgebrochen: der Proxy, der Zielserver oder der Netzbetreiber zwischen dir und dem Proxy? Ist die Anfrage überhaupt beim Proxy angekommen? Konnte der TLS-Handshake abgeschlossen werden? Die HTTP-Client-Bibliothek weiß das nicht – und du weißt es dadurch auch nicht.
In diesem Artikel gehen wir eine Ebene tiefer, zu den Paketen. Wir schauen uns an, wie du mit tcpdump auf dem Client-Rechner einen Mitschnitt erstellst, was du darin siehst, wenn der Verkehr über einen HTTP-Proxy oder SOCKS5 läuft, warum du in einem HTTPS-Tunnel nur CONNECT und verschlüsselte TLS-Records entdeckst, wie du den Mitschnitt in Wireshark liest und wie du anhand von RST, FIN, Retransmissions und Zero Window erkennst, auf welcher Seite die Verbindung abgebrochen ist. Außerdem geht es um die Entschlüsselung des eigenen Traffics über SSLKEYLOGFILE und darum, wie du einen Mitschnitt richtig für den Support eines Proxy-Dienstes wie Proxeon vorbereitest.
Wichtiger Hinweis: Das ist kein Artikel über mitmproxy. Dort geht es um das Abfangen und Ersetzen von HTTPS auf Anwendungsebene mit einem gefälschten Zertifikat. Hier arbeiten wir auf Paketebene, ersetzen nichts und knacken keinen fremden Traffic. Unsere Aufgabe ist rein diagnostisch: Herausfinden, wo die Kette Client – Proxy – Zielserver reißt.
Einführung: Wenn die Client-Logs nicht mehr ausreichen
Stellen dir eine typische Situation vor. Ein Python-Skript läuft über einen mobilen Proxy, verarbeitet ein paar tausend Anfragen pro Stunde, und etwa zwei Prozent davon enden mit dem Fehler Connection aborted, RemoteDisconnected. Der Entwickler fügt Retries hinzu, der Fehler verschwindet nicht. Er schreibt an den Proxy-Support, die bitten um ein Beispiel und die Uhrzeit. Der Support schaut in seine Logs und antwortet: Bei uns ist alles in Ordnung, die Verbindung zum Zielserver wurde aufgebaut. Wer hat recht?
Ohne Mitschnitt ist dieser Streit endlos. Mit Mitschnitt ist er in fünf Minuten geklärt: Man sieht, dass der Proxy auf CONNECT mit 200 geantwortet hat, der Client einen ClientHello gesendet hat und 180 Millisekunden später ein RST vom Proxy kommt. Das bedeutet: Entweder konnte der Proxy sich nicht mit dem Zielserver einigen, oder der Server hat die Verbindung selbst geschlossen. Danach kann man die Timings genauer anschauen. Das Wichtigste ist, dass die Diskussion von Vermutungen zu Fakten übergeht.
HTTP-Client-Logs arbeiten auf Anwendungsebene. Sie sehen das Ergebnis, aber nicht den Prozess. Ein Traffic-Mitschnitt zeigt den Prozess: jedes Paket mit exaktem Zeitstempel, Richtung, Flags und Größe. Deshalb gilt in einem professionellen Proxy-Betrieb die Fähigkeit, einen Mitschnitt zu erstellen und zu lesen, als Grundlagenwissen – nicht als Exotik.
Was du aus diesem Artikel mitnimmst
- Ein Verständnis dafür, welche Daten auf dem Client-Netzwerkinterface bei der Arbeit über einen Proxy tatsächlich fließen und was davon im Klartext sichtbar ist.
- Fertige tcpdump-Befehle zum Mitschneiden mit Filtern, Rotation und Größenbegrenzung.
- Eine Sammlung von Wireshark-Anzeigefiltern, die du direkt kopieren kannst.
- Eine Methode, um Abbrüche auf deiner Seite, auf der Proxy-Seite und auf der Zielserver-Seite zu unterscheiden.
- Einen sicheren Weg, deinen eigenen TLS-Traffic zum Debuggen zu entschlüsseln.
- Eine Checkliste zum Vorbereiten eines Mitschnitts für den Support.
Grundlagen: Was vor dem Proxy, im Tunnel und danach sichtbar ist
Fangen wir mit dem Schema an. Bei der Arbeit über einen Proxy gibt es drei Abschnitte auf dem Weg, und auf dem Client-Rechner kannst du physisch nur den ersten beobachten.
Drei Beobachtungszonen
- Zone A: Client – Proxy. Das ist die einzige TCP-Verbindung, die über dein Netzwerkinterface läuft. tcpdump auf deinem Rechner sieht sie. Hier siehst du: den TCP-Handshake mit der IP-Adresse des Proxys, das Proxy-Protokoll (HTTP CONNECT oder SOCKS5) und danach entweder offenes HTTP oder verschlüsselte TLS-Records.
- Zone B: innerhalb des Tunnels. Nachdem der Proxy mit 200 Connection established geantwortet hat, werden alle Bytes zwischen dir und dem Zielserver einfach durchgeleitet. Wenn der Zielserver über HTTPS läuft, sind diese Bytes TLS-Records. Du siehst ihre Struktur (Record-Typ, Länge, ClientHello mit SNI, ServerHello, Alerts), aber nicht den Inhalt.
- Zone C: Proxy – Zielserver. Das ist eine separate TCP-Verbindung, die der Proxy in seinem eigenen Namen von seiner externen Adresse aus aufbaut. Auf dem Client-Rechner gibt es sie überhaupt nicht. Man sieht sie nur auf dem Proxy-Server selbst – und das ist die Infrastruktur des Anbieters. Alles, was du über Zone C erfährst, erfährst du indirekt: über die Antwortcodes auf CONNECT, über Verzögerungen und darüber, wie der Proxy den Tunnel schließt.
Das ist die Kernaussage dieses Artikels. Ein Mitschnitt auf dem Client zeigt den Zielserver nicht direkt. Aber er zeigt das Verhalten des Proxys, und ein guter Proxy als Repeater übersetzt das Verhalten des Zielservers in eine Form, die man interpretieren kann. Unsere Aufgabe ist es, diese Übersetzung lesen zu lernen.
HTTP-Proxy und offenes HTTP
Der transparenteste Fall. Wenn die Zielseite über http ohne Verschlüsselung läuft, sendet der Client eine Anfrage mit absoluter URI an den Proxy:
GET http://example.com/api/items HTTP/1.1
Host: example.com
Proxy-Authorization: Basic dXNlcjpwYXNz
User-Agent: my-client/1.0Im Mitschnitt ist alles sichtbar: Methode, Pfad, Header, Body, die Antwort des Proxys mit dem Body vom Server. Achte auf den Header Proxy-Authorization. Das sind deine Zugangsdaten in base64, sie liegen im Mitschnitt im Klartext. Merken wir uns – das wird wichtig, wenn es um die Weitergabe von Mitschnitten an Dritte geht.
HTTP-Proxy und HTTPS über CONNECT
Jetzt wird es interessant. Für HTTPS bittet der Client den Proxy zuerst, einen TCP-Tunnel zum Host und Port aufzubauen:
CONNECT api.example.com:443 HTTP/1.1
Host: api.example.com:443
Proxy-Authorization: Basic dXNlcjpwYXNz
Proxy-Connection: Keep-AliveDer Proxy antwortet:
HTTP/1.1 200 Connection establishedAb diesem Moment hört der Proxy auf, HTTP zu parsen. Er kopiert einfach Bytes von einem Socket zum anderen. Der Client beginnt den TLS-Handshake direkt mit dem Zielserver, und der gesamte HTTP-Traffic (GET, POST, Header, Bodies) liegt innerhalb von TLS. Deshalb sieht man im Mitschnitt eines HTTPS-Tunnels nur CONNECT: Das ist das Letzte, was der Client dem Proxy im Klartext sagt. Danach kommen TLS-Records, die der Proxy nicht lesen kann – und du im Mitschnitt auch nicht.
Was im Tunnel dennoch sichtbar bleibt:
- ClientHello: TLS-Versionen, Cipher Suites, Extensions und in der Regel der SNI (Hostname im Klartext).
- ServerHello: gewählte Version und Cipher.
- In TLS 1.2 das Serverzertifikat im Klartext. In TLS 1.3 ist das Zertifikat bereits verschlüsselt.
- TLS Alert: Der Alert-Typ ist in TLS 1.2 sichtbar; in TLS 1.3 sind Alerts nach dem Handshake verschlüsselt, aber die Tatsache eines Alert-Records mit 2 Byte Länge lässt sich erkennen.
- Größen und Timings der Application-Data-Records. Daraus lässt sich abschätzen, wie viele Daten angekommen sind, bevor die Verbindung abbrach.
SOCKS5
SOCKS5 funktioniert anders, aber die Idee ist dieselbe. Der Client sendet eine Begrüßung mit Authentifizierungsmethoden (Bytes 05 02 00 02), der Proxy wählt eine Methode, dann folgt die Authentifizierung mit Benutzername und Passwort (Subprotokoll mit Bytes 01, Länge, Name, Länge, Passwort), dann der CONNECT-Befehl mit Adresstyp 03 (Domänenname) und Port. Der Proxy antwortet 05 00 bei Erfolg oder mit einem Fehlercode: 01 allgemeiner Fehler, 03 Netzwerk nicht erreichbar, 04 Host nicht erreichbar, 05 Verbindung abgelehnt, 06 TTL abgelaufen. Diese Fehlercodes sind die direkte Übersetzung dessen, was der Proxy in Zone C gesehen hat. Wireshark kann SOCKS dekodieren, wenn man den Port über Decode As angibt.
Was nie sichtbar ist
Vom Client-Rechner aus siehst du nie: die externe IP des Proxys, von der aus er den Zielserver anspricht (bei mobilen Proxys ist das die Adresse des Mobilfunkbetreibers), die TCP-Verbindung Proxy – Server, die DNS-Anfragen des Proxys. Wenn der Proxeon-Support sagt, er sehe einen Fehler auf Seiten des Zielservers, dann schaut er genau in Zone C, die dir nicht zugänglich ist. Deine Aufgabe ist es, einen Mitschnitt von Zone A mitzubringen, damit man die beiden Bilder zeitlich abgleichen kann.
Deep Dive: Warum der Proxy nicht mehr zeigen kann und wie man indirekte Hinweise liest
Hier lohnt es sich zu verstehen, warum das Bild so ist und was daraus für die Diagnose folgt.
Der CONNECT-Tunnel als Byte-Röhre
Nach der 200-Antwort muss ein HTTP-Proxy laut Spezifikation Bytes in beide Richtungen weiterleiten, ohne sie zu interpretieren, bis eine Seite schließt. Er weiß nicht, dass darin TLS steckt. Er weiß nicht, welche HTTP-Anfragen du sendest. Er sieht nur zwei Ereignisse: den Byte-Strom und das Schließen des Sockets. Wenn der Zielserver die Verbindung zum Proxy schließt (FIN oder RST sendet), muss der Proxy die Verbindung zu dir schließen. Wie genau er das tut, hängt von der Implementierung ab: Manche Proxys übersetzen FIN als FIN und RST als RST, andere machen alles zu FIN, wieder andere senden beim Lesefehler vom entfernten Socket ein RST an den Client.
Praktische Konsequenz: Ein RST von der IP-Adresse des Proxys bedeutet nicht, dass der Proxy schuld ist. Es bedeutet, dass der Tunnel von der Proxy-Seite geschlossen wurde, und die Ursache kann irgendwo dahinter liegen. Um die Ursache zu verstehen, schauen wir auf den Kontext: Was ist vor dem RST passiert, wie viel Zeit ist vergangen, ist die Antwort angekommen.
Der Unterschied zwischen SYN an den Proxy und SYN an den Zielserver
Das ist die häufigste Quelle von Verwirrung. In einem Mitschnitt über einen Proxy wirst du nie ein SYN an Port 443 des Zielservers sehen. Alle SYNs gehen an die IP und den Port des Proxys. Wenn ein SYN an den Proxy kein SYN-ACK erhält und mit Intervallen von 1, 2, 4, 8 Sekunden wiederholt wird, liegt das Problem zwischen dir und dem Proxy: Netzwerk, Firewall, falsche Adresse oder falscher Port, Proxy läuft nicht. Der Zielserver ist hier völlig unbeteiligt, du hast ihn in den Begriffen deines Mitschnitts nicht einmal zu erreichen versucht.
Wenn dagegen die TCP-Verbindung zum Proxy steht, CONNECT gesendet wurde und die Antwort nach 20–30 Sekunden mit dem Code 504 Gateway Timeout oder 502 Bad Gateway kommt, konnte der Proxy Zone C nicht aufbauen. Das Timing spricht für sich: Dein CONNECT-Paket ging sofort raus, lange kam keine Antwort, also hat der Proxy in seinem Verbindungsversuch auf ein Timeout gewartet.
TLS 1.3, ECH und was sich bis 2026 ändert
Die Landschaft schließt sich langsam. TLS 1.3 dominiert, und darin ist das Serverzertifikat verschlüsselt, sodass man ohne Schlüssel aus dem Mitschnitt nicht mehr prüfen kann, welches Zertifikat der Server zurückgegeben hat. Die ECH-Erweiterung (Encrypted Client Hello) wird von Browsern und großen CDNs schrittweise eingeführt, und dort wird auch der SNI verschlüsselt. Für die Diagnose über einen Proxy ist das weniger kritisch, weil der Hostname ohnehin in der CONNECT-Zeile sichtbar ist, aber der gewohnte Filter nach SNI wird seltener greifen.
Ein weiterer Trend ist HTTP/3 über QUIC. Ein klassischer HTTP-Proxy mit CONNECT tunnelt nur TCP. Wenn du im Mitschnitt plötzlich UDP-Traffic an Port 443 direkt zur Adresse des Zielservers siehst, am Proxy vorbei, ist das ein Zeichen für ein Leck: Die Anwendung versucht, QUIC direkt zu nutzen, statt über den Proxy. Ein richtig konfigurierter Client sollte QUIC bei der Arbeit über einen Proxy entweder deaktivieren oder UDP über separate Mechanismen proxien. Der schnelle Prüffilter: udp.port == 443. Wenn ein Mitschnitt über den Proxy solche Pakete zeigt, muss die Client-Konfiguration korrigiert werden.
Wo man den Capture-Punkt setzt
Normalerweise ist die Antwort eindeutig: auf dem Client-Rechner. Aber es gibt Nuancen. Wenn der Client in einem Docker-Container läuft, zeigt tcpdump auf dem Host am Interface docker0 oder am Bridge-Interface den Verkehr vor dem NAT, am externen Interface nach dem NAT mit anderer Quelladresse. Einfacher ist es, in den Netzwerk-Namespace des Containers zu gehen: nsenter -t PID -n tcpdump ... oder den Container mit tcpdump über --net=container:name zu starten. Bei virtuellen Maschinen in der Cloud achte auf Offloading: Pakete im Mitschnitt können größer als die MTU aussehen, weil die Netzwerkkarte Segmente zusammenfügt. Das ist normal und beeinflusst die Analyse der Flags nicht.
tcpdump in der Praxis: Filter, Dateiausgabe, Rotation
tcpdump gibt es fast auf jedem Linux-Rechner und auf macOS. Unter Windows übernimmt Wireshark mit dem Npcap-Treiber oder das Konsolenwerkzeug dumpcap eine ähnliche Rolle. Schauen wir uns die Befehle an, die 95 Prozent der Proxy-Diagnoseaufgaben abdecken.
Basis-Capture des Traffics zum Proxy
Angenommen, die Proxy-Adresse ist 203.0.113.10, Port 8080. Wir schreiben alles, was zwischen uns und dem Proxy läuft, in eine Datei:
sudo tcpdump -i any -nn -s 0 -w proxy.pcap 'host 203.0.113.10 and port 8080'Die Optionen im Einzelnen:
- -i any – auf allen Interfaces lauschen. Praktisch, wenn du nicht weißt, über welches der Verkehr rausgeht. Wenn du es weißt, gib besser ein konkretes Interface an: -i eth0 oder -i wlan0. Unter macOS wird -i any nicht unterstützt, gib en0 an.
- -nn – IPs nicht in Namen und Ports nicht in Dienstnamen auflösen. Das Auflösen verlangsamt den Capture und erzeugt zusätzliche DNS-Anfragen im Netz.
- -s 0 – das Paket vollständig mitschneiden. In modernen Versionen ist das der Standard, aber explizit schadet nicht.
- -w proxy.pcap – in eine Datei im pcap-Format schreiben statt auf den Bildschirm. Nur so lässt sich der Mitschnitt später in Wireshark öffnen.
- Filter in einfachen Anführungszeichen – das ist ein BPF-Capture-Filter. Er filtert Überflüssiges schon im Kernel weg, sodass die Datei nur das Nötige enthält.
Filter nach Host und Port
Mehrere Proxys oder ein Portpool:
sudo tcpdump -i eth0 -nn -w proxy.pcap 'host 203.0.113.10 and portrange 10000-10100'Proxy über Domänennamen (tcpdump löst ihn einmal beim Start auf, was bei rotierenden Adressen nicht immer passt):
sudo tcpdump -i eth0 -nn -w proxy.pcap 'host proxy.example.net and port 8080'Nur Steuerpakete ohne Daten mitschneiden, um bei großem Volumen Handshakes und Abbrüche zu sehen:
sudo tcpdump -i eth0 -nn -w flags.pcap 'host 203.0.113.10 and tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'Nur RST in beide Richtungen:
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'Capture mit Ausschluss der eigenen SSH-Session, damit der Mitschnitt nicht zugemüllt wird, wenn man ihn auf einem Remote-Server erstellt:
sudo tcpdump -i eth0 -nn -w proxy.pcap 'host 203.0.113.10 and not port 22'Wie man keine Gigabytes ansammelt: Rotation nach Größe und Zeit
Wenn der Fehler selten ist und nur einmal pro Stunde auftritt, muss der Mitschnitt lange laufen. Ohne Rotation ist die Platte schnell voll. Rotation nach Größe, 100 MB pro Datei, Ring aus 10 Dateien:
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'Hier legt -C die Größe in Millionen Bytes fest, -W begrenzt die Anzahl der Dateien: Die elfte Datei überschreibt die erste. Rotation nach Zeit, neue Datei alle 10 Minuten, die letzten 24 Dateien behalten (4 Stunden):
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'Der Schalter -G gibt das Intervall in Sekunden an, und das Zeitmuster im Dateinamen ist Pflicht, sonst überschreibt tcpdump eine einzige Datei. Nützlich ist -Z benutzer, um nach dem Öffnen des Interfaces Privilegien abzugeben, und -U, um Pakete sofort in die Datei zu schreiben, ohne Pufferung – wichtig, wenn du die Datei parallel liest oder den Schwanz bei einem Absturz nicht verlieren willst.
Nutzlast kürzen
Eine weitere Möglichkeit, das Volumen zu senken, ist, nur Header mitzuschneiden. Für die Diagnose von Abbrüchen braucht man den Inhalt der TLS-Records nicht, die ersten 128 Bytes jedes Pakets reichen:
sudo tcpdump -i eth0 -nn -s 128 -w headers.pcap 'host 203.0.113.10'Vorsicht: Bei -s 128 können die CONNECT-Zeile und Header abgeschnitten sein, und Wireshark markiert die Pakete als truncated. Für die vollständige Analyse des TLS-Handshakes ist das zu wenig, ein ClientHello ist oft 300–600 Bytes und mehr. Ein Kompromiss ist -s 600.
Mitschnitt direkt in der Konsole lesen
Wireshark ist nicht immer zur Hand, aber schnell schauen muss sein. Datei lesen mit Ausgabe der TCP-Flags und absoluten Sequenznummern:
tcpdump -nn -r proxy.pcap -S -tttt 'tcp[tcpflags] & (tcp-rst|tcp-fin) != 0'Der Schalter -tttt gibt vollständiges Datum und Uhrzeit aus, -S zeigt absolute Sequence Numbers, was den Abgleich mit Logs erleichtert. Paketinhalt als ASCII ausgeben, um die CONNECT-Zeile und die Proxy-Antwort zu sehen:
tcpdump -nn -r proxy.pcap -A 'port 8080' | grep -E 'CONNECT|HTTP/1'tshark als Konsolen-Wireshark
Wenn Wireshark auf dem Server installiert ist, bietet tshark Zugriff auf dieselben Dissectors von der Konsole aus. Liste aller CONNECTs mit Antwortcodes:
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.codeListe der Streams, die mit RST endeten, mit Angabe, wer ihn gesendet hat:
tshark -r proxy.pcap -Y 'tcp.flags.reset == 1' -T fields -e frame.time_relative -e tcp.stream -e ip.src -e ip.dstWireshark: Anzeigefilter, Follow TCP Stream, TLS ohne Entschlüsselung lesen
Du hast die pcap in Wireshark geöffnet und siehst Tausende Zeilen. Wo anfangen? Mit Anzeigefiltern. Anders als BPF-Capture-Filter arbeiten sie auf der bereits aufgezeichneten Datei und verstehen die Protokollstruktur.
Basis-Filter für die Arbeit über den Proxy
Alles rund um den Proxy:
ip.addr == 203.0.113.10 && tcp.port == 8080Alle CONNECT-Anfragen:
http.request.method == "CONNECT"CONNECT zu einem bestimmten Host:
http.request.method == "CONNECT" && http.host contains "api.example.com"Proxy-Antworten, die nicht 200 sind (Autorisierungsfehler 407, Nichtverfügbarkeit 502, Timeouts 504):
http.response.code >= 400 && tcp.port == 8080Nur Antworten 407, ein Zeichen für falsche Zugangsdaten oder ausgeschöpftes Limit:
http.response.code == 407TLS-Filter innerhalb des Tunnels
Wireshark erkennt, dass nach CONNECT mit Antwort 200 TLS beginnt, und setzt automatisch den TLS-Dissector ein. Wenn nicht (kommt bei abgeschnittenen Paketen vor), klicke mit der rechten Maustaste auf das Paket, wähle Decode As und gib TLS für diesen Port an.
Alle ClientHellos:
tls.handshake.type == 1ClientHello mit bestimmtem SNI:
tls.handshake.extensions_server_name contains "example.com"ServerHello (fehlt er nach dem ClientHello, hat der Handshake von Serverseite nicht begonnen):
tls.handshake.type == 2TLS-Alerts:
tls.alert_messageEinen Stream, in dem ein ClientHello, aber kein ServerHello vorkommt, findet man mit einem einzelnen Filter schwer; bequemer geht es über Statistics > Conversations, sortiert nach Paketanzahl, und man schaut sich die Streams mit 5–7 Paketen an.
Filter für TCP-Probleme
Alle Pakete mit RST:
tcp.flags.reset == 1RSTs, die der Proxy in unsere Richtung gesendet hat:
tcp.flags.reset == 1 && ip.src == 203.0.113.10RSTs, die wir gesendet haben:
tcp.flags.reset == 1 && ip.dst == 203.0.113.10Retransmissions:
tcp.analysis.retransmissionZero Window und seine Folgen:
tcp.analysis.zero_window || tcp.analysis.window_fullAlle Anomalien, die Wireshark selbst bemerkt hat (Retransmissions, Duplicate ACKs, verlorene Segmente, Zero Window):
tcp.analysis.flags && !tcp.analysis.window_updateSYN ohne Antwort, also wiederholte SYNs:
tcp.flags.syn == 1 && tcp.flags.ack == 0 && tcp.analysis.retransmissionGroße Pausen innerhalb eines Streams, mehr als 5 Sekunden zwischen Paketen:
tcp.time_delta > 5Für diesen Filter musst du Edit > Preferences > Protocols > TCP > Calculate conversation timestamps einschalten.
Follow TCP Stream
Du hast ein verdächtiges Paket gefunden, zum Beispiel ein RST. Klicke mit der rechten Maustaste > Follow > TCP Stream. Wireshark zeigt den gesamten Dialog dieser Verbindung als Text: unseren Traffic in einer Farbe, den des Proxys in einer anderen. Für HTTPS über CONNECT siehst du die CONNECT-Zeile, die Antwort 200 Connection established und danach unlesbare TLS-Bytes. Das ist normal. Schauen musst du auf die Volumina: Wie viele Bytes sind von uns rausgegangen (unser ClientHello und die Anfragen), wie viele sind angekommen (ServerHello und Antwort) und wo ist alles zu Ende gegangen.
Unten im Follow-Fenster gibt es Zähler: so und so viele Bytes Client, so und so viele Server. Wenn nach der 200-Antwort 0 Bytes vom Server gekommen sind, hat der Zielserver auf das ClientHello überhaupt nicht geantwortet. Wenn etwa 100–4000 Bytes kamen und dann der Abbruch, hat der Handshake begonnen, aber nicht abgeschlossen. Wenn zig Kilobytes kamen und dann der Abbruch, liegt das Problem mitten in der Datenübertragung.
Eine nützliche Angewohnheit: Filtere nach der Stream-Nummer. Nach Follow erscheint in der Filterzeile automatisch tcp.stream eq 42. Schließe das Follow-Fenster, und in der Hauptliste bleiben nur dieser Stream mit Flags und Timings übrig. Das ist die bequemste Ansicht für die Analyse eines Abbruchs.
TLS-Handshake ohne Entschlüsselung lesen
Klappe das ClientHello im Paketbaum auf. Worauf du achten solltest:
- Version und supported_versions – bietet der Client TLS 1.3 an. Wenn der Server 1.3 verlangt und der Client nur 1.2 anbietet, schließt der Server die Verbindung mit einem protocol_version-Alert oder einfach FIN.
- server_name – stimmt der SNI mit dem Host in CONNECT überein. Abweichungen entstehen bei falscher Client-Konfiguration und führen zu Zertifikatsfehlern.
- Cipher Suites – die Liste der Cipher. Eine zu kurze oder veraltete Liste ist eine Ursache für einen handshake_failure-Alert.
- ALPN – bietet der Client h2 an. Wenn der Server h2 gewählt hat, der Client intern aber HTTP/1.1 erwartet, kann die Anwendung mit unklaren Fehlern abstürzen.
Im ServerHello schaust du auf die gewählte Version und den Cipher. In TLS 1.2 folgt danach das Certificate im Klartext, du kannst Name und Gültigkeit prüfen. In TLS 1.3 ist nach dem ServerHello fast alles verschlüsselt, und das Nächste, was man liest, ist der Record-Typ. Application Data bedeutet, dass der Handshake erfolgreich war und Daten fließen. Alert mit 2 Byte Länge direkt nach dem ServerHello oder statt seiner bedeutet, dass etwas nicht stimmt: In TLS 1.3 siehst du den Alert-Code ohne Schlüssel nicht, aber die Tatsache allein ist schon informativ.
Unter Statistics > Conversations > TCP lässt sich das Gesamtbild gut einschätzen: Wie viele Streams, wie viele Bytes in jede Richtung, wie lange. Streams mit einer Dauer von 0,05 Sekunden und 6 Paketen sind wahrscheinlich Verbindungen, die direkt nach dem Handshake zurückgesetzt wurden.
Diagnose anhand des Mitschnitts: RST, FIN, Retransmission, Zero Window
Jetzt zum Wichtigsten. Wie erkennt man anhand eines Mitschnitts von Zone A, wo genau es gerissen ist? Gehen wir jedes Signal und seine Interpretation im Proxy-Kontext durch.
Richtungsmatrix
Die erste Frage ist immer dieselbe: Wer hat das schließende Paket gesendet? Im Mitschnitt ist das das Feld ip.src. Es gibt nur zwei Möglichkeiten – unsere Adresse oder die des Proxys.
- RST oder FIN von uns – unsere Anwendung, unser Betriebssystem oder etwas auf unserem Host hat die Verbindung geschlossen. Proxy und Zielserver waren nicht beteiligt. Typische Ursachen: Timeout im HTTP-Client, abruptes Prozessende, Erschöpfung der Dateideskriptoren, lokale Firewall oder Antivirus.
- RST oder FIN vom Proxy – der Tunnel wurde von der Proxy-Seite geschlossen. Die Ursache liegt entweder im Proxy selbst (Limits, Policy, Idle-Timeout), oder sie wurde vom Zielserver übersetzt, oder vom Netzwerk zwischen Proxy und Server. Unterscheiden lässt sich das anhand des Kontexts und der Timings.
- Weder RST noch FIN, nur Retransmissions – Pakete gehen auf dem Weg zwischen uns und dem Proxy verloren. Keine Seite hat die Verbindung geschlossen, sie ist einfach an Verlusten gestorben.
RST nach CONNECT ohne Antwort 200
Das Bild: TCP aufgebaut, wir haben CONNECT gesendet, der Proxy antwortet mit RST ohne HTTP-Antwort. Dieses Verhalten bedeutet meist, dass der Proxy auf Policy-Ebene abgelehnt hat oder die Anfrage nicht parsen konnte. Ursachen: unzulässiger Zielport, Limit gleichzeitiger Verbindungen, fehlerhaftes Anfrageformat. Hier liegt das Problem in Zone A oder im Proxy selbst. Der Zielserver ist unbeteiligt.
Antwort 502, 503 oder 504 auf CONNECT
Das Bild: CONNECT ging raus, nach N Sekunden kam eine HTTP-Antwort mit Code 5xx. Schauen wir auf N. Wenn die Antwort in der Größenordnung der RTT zum Proxy kam, hat der Proxy sofort abgelehnt – vielleicht löst der DNS-Name auf seiner Seite nicht auf oder die Adresse ist sofort unerreichbar (ICMP unreachable). Wenn N bei 10–30 Sekunden liegt, hat der Proxy auf ein Timeout beim Verbindungsaufbau zum Zielserver gewartet: Der Server antwortet nicht auf SYN. In beiden Fällen ist das Zone C, und dein Mitschnitt beweist, dass du alles richtig gemacht hast und der Proxy ehrlich über die Unmöglichkeit informiert hat.
FIN oder RST direkt nach dem ClientHello
Das Bild: CONNECT – 200 – unser ClientHello – nach etwa einer RTT zum Proxy plus etwas kommt FIN oder RST vom Proxy. Hier gibt es zwei Kandidaten: Der Zielserver hat die Verbindung in der TLS-Phase abgelehnt (SNI passt nicht, Version, fehlendes Client-Zertifikat) oder ein Schutzsystem des Servers hat die Verbindung anhand von ClientHello-Merkmalen zurückgesetzt. Das Schlüsselmerkmal ist die Zeit. Wenn zwischen unserem ClientHello und dem Abbruch deutlich mehr Zeit vergangen ist als die RTT zum Proxy, dann hat der Proxy das ClientHello weitergeleitet und eine Reaktion erhalten. Der Proxy hat nicht entschieden zu schließen, das ist die übersetzte Reaktion des Zielservers.
Vergleiche mit der RTT zum Proxy, die du am TCP-Handshake misst: die Zeit zwischen SYN und SYN-ACK. Wenn die RTT zum Proxy 40 ms beträgt und der Abbruch nach dem ClientHello nach 200 ms kam, dann sind die 160 ms Differenz ungefähr die RTT Proxy – Server hin und zurück. Das Bild passt vollständig zu einer Ablehnung durch den Server.
Abbruch nach ServerHello oder nach einem Teil der Daten
Der Handshake hat begonnen, der Server hat geantwortet, Daten flossen, und mittendrin FIN oder RST. Wenn es ein FIN ist und vom Proxy kommt, und der letzte Application-Data-Record davor eine logische Größe hat, kann es sein, dass der Server die Verbindung nach der Antwort einfach geschlossen hat (Connection: close innerhalb von TLS) und der Client das falsch interpretiert hat. Wenn ein RST mitten im Datenstrom ohne vorherige Verlangsamung kommt, ist es entweder ein erzwungenes Schließen auf dem Server oder der Proxy hat den Tunnel wegen eines Traffic- oder Session-Limits unterbrochen. Bei mobilen Proxys mit zeitbasierter IP-Rotation ist Letzteres sehr wahrscheinlich: Der Abbruch erfolgt genau im Moment des IP-Wechsels. Prüfe, ob die Abbruchzeit mit dem Rotationsintervall in deinen Proxy-Einstellungen übereinstimmt.
Retransmissions und ihre Richtung
Wireshark markiert ein Paket als retransmission, wenn es dieselben Sequence Numbers erneut sieht. Schauen wir, wer retransmittet:
- Wir retransmitten – unsere Pakete werden vom Proxy nicht bestätigt. Entweder gehen sie auf dem Weg zum Proxy verloren, oder die Bestätigungen gehen auf dem Rückweg verloren. In beiden Fällen liegt das Problem im Netzwerk von Zone A.
- Der Proxy retransmittet – seine Pakete werden von uns nicht bestätigt. Wir erhalten sie nicht, oder unsere ACKs kommen nicht an. Ebenfalls Zone A, aber in Richtung eingehend.
- SYN-Retransmissions – ein Sonderfall: Der Proxy ist auf TCP-Ebene nicht erreichbar, die Verbindung kommt gar nicht zustande.
Wichtig: Verluste in Zone C siehst du nie als Retransmissions. Der Proxy regelt das selbst mit dem Zielserver. Die einzige Spur von Verlusten in Zone C sind Pausen: Der Proxy überträgt Daten ungleichmäßig, mit Lücken, obwohl im Mitschnitt keine Retransmissions zu sehen sind. Der Filter tcp.time_delta > 1 für Pakete vom Proxy zeigt solche Pausen.
Zero Window
Ein TCP-Fenster der Größe null bedeutet, dass der Empfänger nicht schnell genug Daten aus dem Socket-Puffer liest. Wenn wir ein Nullfenster ankündigen, liest unsere Anwendung die Antwort nicht schnell genug: Thread beschäftigt, Blockierung, langsame Verarbeitung. Der Proxy wartet in diesem Fall, sendet dann eine Zero Window Probe, und wenn die Anwendung nicht anfängt zu lesen, kann er die Verbindung nach einigen Dutzend Sekunden schließen. Der Client sieht den Abbruch und beschuldigt den Proxy, obwohl die Ursache im Client liegt.
Wenn der Proxy ein Nullfenster ankündigt, schafft er es nicht, unsere Daten weiterzuleiten – der Zielserver nimmt langsam an. Das ist ein indirekter Hinweis auf Probleme in Zone C, kommt beim Herunterladen großer Dateien über einen Proxy zu einem langsamen Server vor.
Duplicate ACKs und SACK
Duplicate ACK vom Proxy ist ein Signal, dass er ein Paket außer der Reihe erhalten hat, etwas von uns fehlt. Viele Duplicate ACKs und anschließende Retransmissions sind das klassische Bild von Verlusten im Mobilfunk- oder WLAN-Netz auf unserer Seite. Duplicate ACKs von uns – Pakete vom Proxy fehlen. Die SACK-Option im Handshake ermöglicht schnellere TCP-Erholung, aber die Tatsache der Verluste bleibt sichtbar.
TTL-Heuristik
Ein fortgeschrittener Trick. Schau auf das IP-TTL-Feld in normalen Paketen vom Proxy und im RST-Paket. Wenn das TTL im RST um mehrere Einheiten abweicht, wurde das RST nicht vom Proxy selbst erzeugt, sondern von einem Zwischenknoten auf dem Weg: Firewall, Loadbalancer oder Filteranlage des Netzbetreibers. Das ist kein absoluter Beweis, aber ein starker Hinweis, dass man den Pfad zwischen dir und dem Proxy prüfen sollte, statt den Proxy oder den Zielserver zu beschuldigen.
Übersichtstabelle der Interpretationen
- SYN wiederholt sich, kein SYN-ACK: Proxy nicht erreichbar oder Netzwerk dorthin. Zone A.
- SYN – RST: Proxy-Port geschlossen oder gefiltert. Zone A.
- CONNECT – 407: Falsche Autorisierung oder Konto-Limit. Proxy.
- CONNECT – 502/504 schnell: Proxy konnte die Verbindung zum Server nicht aufbauen. Zone C, eher DNS oder Route.
- CONNECT – 504 nach 20–30 Sekunden: Server antwortet nicht auf SYN des Proxys. Zone C.
- 200 – ClientHello – RST/FIN nach mehr als RTT: Server hat TLS abgelehnt. Zone C.
- 200 – ClientHello – Stille – Abbruch nach Client-Timeout: Server nimmt TCP an, antwortet aber nicht auf TLS. Zone C oder blockierender Filter hinter dem Proxy.
- Daten fließen – RST vom Proxy zu einem festen Zeitpunkt: Limit oder Rotation des Proxys. Proxy.
- Retransmissions und Duplicate ACKs ohne RST: Verluste im Netzwerk zwischen uns und dem Proxy. Zone A.
- Zero Window von uns: Unsere Anwendung liest nicht. Client.
- RST von uns nach langer Stille: Unser Timeout. Client.
Eigenen Traffic über SSLKEYLOGFILE entschlüsseln
Manchmal reichen die Flags nicht aus und man muss sehen, was der Server innerhalb von TLS tatsächlich zurückgegeben hat: Antwortcode, Header, Fehler-Body. Dafür braucht man kein mitmproxy und kein gefälschtes Zertifikat. Es reicht, dass der eigene Client die Session-Keys in eine Datei schreibt und Wireshark sie zur Entschlüsselung nutzt. Das funktioniert nur für den eigenen Client und die eigenen Verbindungen: Die Keys hat nur die Seite, die am Handshake beteiligt war. Fremden Traffic oder den Traffic, den der Proxy in Zone C mit dem Server führt, kann man damit nicht entschlüsseln – und das ist auch richtig so.
So aktivierst du es in verschiedenen Clients
Browser auf Chromium- und Firefox-Basis lesen die Umgebungsvariable SSLKEYLOGFILE und schreiben die Keys im NSS-Key-Log-Format hinein:
export SSLKEYLOGFILE=/home/user/tls-keys.log
google-chrome --proxy-server=http://203.0.113.10:8080curl, mit OpenSSL gebaut, liest diese Variable ebenfalls:
export SSLKEYLOGFILE=/home/user/tls-keys.log
curl -v -x http://user:pass@203.0.113.10:8080 https://api.example.com/healthNode.js mit Kommandozeilen-Schalter:
node --tls-keylog=/home/user/tls-keys.log app.jsPython liest die Variable nicht automatisch, aber seit Version 3.8 gibt es im SSLContext das Attribut keylog_filename. Für requests über einen Adapter:
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 über das Feld KeyLogWriter in tls.Config:
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,
}Keys in Wireshark einbinden
Zwei Möglichkeiten. Erstens: Edit > Preferences > Protocols > TLS > (Pre)-Master-Secret log filename, den Pfad zur Key-Datei angeben. Wireshark entschlüsselt alle Streams, für die es eine Übereinstimmung über den Client Random findet. Zweitens, zuverlässiger für die Weitergabe an Kollegen: Keys direkt in die pcapng einbetten:
editcap --inject-secrets tls,/home/user/tls-keys.log proxy.pcap proxy-with-keys.pcapngDanach erscheinen in Wireshark innerhalb des CONNECT-Tunnels entschlüsselte HTTP/1.1- oder HTTP/2-Anfragen und -Antworten. Filter für entschlüsseltes HTTP/2:
http2.header.name == ":status"Für entschlüsseltes HTTP/1.1 innerhalb des Tunnels funktionieren die normalen http.response.code und http.request.uri.
Was das für die Diagnose über einen Proxy bringt
Die Entschlüsselung beseitigt die letzte Unsicherheit. Du siehst, dass der Server mit 429 und Header Retry-After geantwortet und dann die Verbindung geschlossen hat, oder dass er 200 zurückgegeben hat, aber der Body bei 40 Prozent abbrach, oder dass die Anfrage rausging und gar keine Antwort kam. Mit diesem Bild wird die Anfrage an den Proxy-Support konkret: Entweder liegt das Problem klar beim Server oder klar im Tunnel.
Sicherheitsregeln
- Die Key-Datei erlaubt die vollständige Entschlüsselung aufgezeichneter Sessions, inklusive Cookies und Tokens. Behandle sie wie ein Passwort und lösche sie nach der Analyse.
- Gib die Key-Datei nicht zusammen mit dem Mitschnitt an den Proxy-Support oder an sonst wen weiter. Der Support braucht für die Analyse von Abbrüchen keine Keys, ihm reichen Flags und Timings.
- Wenn du entschlüsselten Inhalt zeigen musst, mach das mit einem Testkonto beim Zielservice und Test-Zugangsdaten für den Proxy.
- Lass SSLKEYLOGFILE nicht im Produktivbetrieb aktiv. Eine Umgebungsvariable, die versehentlich in die Service-Konfiguration gerät, schreibt jahrelang Keys auf die Platte.
Typische Bilder: Verbindungs-Timeout, Abbruch mitten in der Antwort, Verluste im Mobilfunknetz
Fassen wir die besprochenen Merkmale zu erkennbaren Szenarien zusammen. Jedes ist so beschrieben, wie es in der Wireshark-Paketliste nach dem Filter tcp.stream eq N aussieht.
Bild 1: Timeout beim Verbindungsaufbau zum Proxy
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)Kein einziges Paket vom Proxy. Die exponentiellen Intervalle 1, 2, 4, 8 Sekunden sind der Standard-Retransmission-Backoff des Linux-Kernels. Diagnose: Proxy ist von deinem Standort aus nicht erreichbar. Prüfe Adresse, Port, Firewall, Routing und ob sich die Proxy-Adresse geändert hat. Wenn es ein mobiler Proxeon-Proxy mit dediziertem Port ist, stelle sicher, dass der Port aus deinem Kundenkonto mit dem in der Client-Konfiguration übereinstimmt.
Bild 2: Timeout beim Verbindungsaufbau des Proxys zum Zielserver
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]RTT zum Proxy 41 ms, der Proxy hat den Empfang von CONNECT bestätigt und dann 30 Sekunden geschwiegen und 504 zurückgegeben. Diagnose: Der Zielserver antwortet dem Proxy nicht auf den Verbindungsversuch. Mögliche Ursachen: Server liegt down, Port ist für den Adresspool des Proxys geschlossen, Netzwerkprobleme auf der Route Proxy – Server. Dein Client und dein Netzwerk sind nicht beteiligt.
Bild 3: Server lehnt TLS ab
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]Abbruch 164 ms nach dem ClientHello bei einer RTT zum Proxy von 45 ms. Die Differenz von etwa 120 ms ist die Zeit, in der der Proxy das ClientHello an den Server weitergeleitet und die Schließung erhalten hat. Diagnose: Der Server hat TCP angenommen, aber die Verbindung in der TLS-Phase geschlossen. Prüfe die Handshake-Parameter: Versionen, Cipher, SNI, ALPN. Wenn kein ServerHello und kein Alert kommt, hat der Server die Verbindung still geschlossen, was Schutzsysteme bei untypischem ClientHello oft tun.
Bild 4: Abbruch mitten in der Antwort
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)
... noch 340 Datenpakete
4.812 proxy -> client Application Data (1460 bytes)
4.813 proxy -> client [RST, ACK]Der Handshake lief, etwa 500 KB Daten kamen an, dann RST ohne Verlangsamung, ohne Retransmissions, ohne Zero Window. Schau auf die absolute Zeit. Wenn sie mit dem Moment der IP-Rotation am mobilen Proxy oder mit dem Ablauf eines Session-Dauer-Limits zusammenfällt, liegt die Ursache beim Proxy, und die Lösung ist, das Rotationsintervall an die Dauer deiner Anfragen anzupassen oder einen Modus ohne Rotation bei langen Downloads zu nutzen. Wenn es keine Übereinstimmung gibt, ist ein Abbruch auf Seiten des Servers oder der CDN wahrscheinlich. Hier hilft die Entschlüsselung über SSLKEYLOGFILE: Wenn im Inneren der Header Content-Length zu sehen ist und der Body nicht vollständig ankam, hat der Server die Übertragung abgebrochen.
Bild 5: Verluste im Mobilfunknetz auf Client-Seite
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)Duplicate ACKs vom Proxy, danach Retransmissions von uns mit wachsenden Intervallen. Weder RST noch FIN. Diagnose: Verluste auf dem Weg Client – Proxy. Wenn der Client selbst über Mobilfunk oder WLAN angebunden ist, ist das in Momenten des Zellwechsels zu erwarten. Die Lösung: Client-Timeouts erhöhen, TCP-Keepalive einschalten, keine langen idle-Verbindungen halten, weil NAT von Mobilfunkbetreibern Einträge für idle-Verbindungen zurücksetzt, meist nach 30–300 Sekunden, und das nächste Paket ins Leere geht. Filter zur Einschätzung des Verlustumfangs:
tcp.analysis.retransmission && ip.dst == 203.0.113.10Berechne den Anteil dieser Pakete an der Gesamtzahl über Statistics > Capture File Properties. Ein bis zwei Prozent sind für ein Mobilfunknetz tolerierbar, mehr als fünf – suche das Problem in den Funkbedingungen oder in der Hardware.
Bild 6: Unser eigener Timeout
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]Die Anfrage ging raus, der Proxy hat bestätigt, es kam keine Antwort, und genau nach 10 Sekunden haben wir FIN gesendet. Das ist unser read timeout. Der Fehler im Client-Log sieht wie ein Abbruch aus, aber im Mitschnitt ist klar: Wir haben die Verbindung selbst geschlossen, weil der Server länger nachgedacht hat, als wir zu warten bereit waren. Die Lösung ist, entweder den Timeout zu erhöhen oder zu klären, warum der Server langsam ist – aber der Proxy hat hier einfach ehrlich mit uns gewartet.
Typische Fehler beim Erstellen und Lesen von Mitschnitten
Zählen wir auf, worüber selbst erfahrene Entwickler regelmäßig stolpern.
- Mitschneiden ohne Capture-Filter auf einer ausgelasteten Maschine. In einer Minute kommen Gigabytes zusammen, und die benötigten 200 Pakete sind darin schwer zu finden. Filtere immer nach dem Proxy-Host.
- Nach der Adresse des Zielservers filtern. Über den Proxy gibt es solche Pakete auf deiner Maschine nicht. Der Filter liefert nichts, und man denkt, es fließe kein Traffic. Er fließt, aber zum Proxy.
- Capture-Filter und Anzeigefilter verwechseln. Die BPF-Syntax in tcpdump (host, port, tcp[tcpflags]) und die Wireshark-Syntax (ip.addr, tcp.port, tcp.flags.reset) sind unterschiedlich. Ein Wireshark-Filter in tcpdump erzeugt einen Syntaxfehler und umgekehrt.
- Auf ein RST vom Proxy schauen und sofort den Proxy beschuldigen. Ein RST von der Proxy-Adresse bedeutet das Schließen des Tunnels, nicht ein Schuldeingeständnis. Schau auf die Timings und darauf, was vor dem RST passiert ist.
- Die RTT ignorieren. Ohne die gemessene Verzögerung zum Proxy kann man eine sofortige Ablehnung des Proxys nicht von einer übersetzten Ablehnung des Servers unterscheiden.
- Mit -s 64 mitschneiden und dann versuchen, CONNECT zu lesen. Header werden abgeschnitten. Für die Proxy-Diagnose braucht man einen vollständigen Capture oder mindestens -s 600.
- Die Zeit nicht synchronisieren. Wenn die Uhr auf der Capture-Maschine eine Minute nachgeht, lässt sich der Mitschnitt nicht mit den Support-Logs abgleichen. Schalte NTP ein und gib UTC an.
- Einen Mitschnitt mit Proxy-Zugangsdaten versenden. Der Header Proxy-Authorization in einer offenen HTTP-Anfrage an den Proxy enthält Login und Passwort. Entweder mit Testdaten mitschneiden oder nach dem Versand das Passwort ändern.
- Die Key-Datei zusammen mit dem Mitschnitt senden. Das legt den gesamten Inhalt der Sessions offen. Der Support braucht keine Keys für die Analyse von Abbrüchen.
- Einen langen Mitschnitt ohne Rotation laufen lassen. Die Platte füllt sich im ungünstigsten Moment, und tcpdump stürzt zusammen mit den benötigten Paketen ab.
- QUIC-Lecks nicht prüfen. UDP auf 443 direkt ist ein Zeichen, dass ein Teil des Traffics am Proxy vorbeiläuft, und die Diagnose über den TCP-Tunnel zeigt dann nichts.
- Segmentation Offload vergessen. Pakete mit 60 KB im Mitschnitt auf einer virtuellen Maschine bedeuten nicht eine falsche MTU. Der Kernel übergibt tcpdump noch nicht zerlegte Segmente.
Werkzeuge und Ressourcen
Das minimale Set für die beschriebene Methodik.
Capture
- tcpdump – Standard auf Linux und macOS. Fast überall installiert, erfordert root oder die Capability CAP_NET_RAW.
- dumpcap – Konsolen-Capture-Tool aus dem Wireshark-Paket, unterstützt dieselben Rotationsschalter (-b filesize, -b files) und das pcapng-Format.
- Wireshark mit Npcap – für Windows. Man kann direkt aus der GUI mit Capture-Filter in derselben BPF-Syntax mitschneiden.
- tshark – Konsolenanalyse mit Wireshark-Dissectors, praktisch auf Servern ohne Grafik und für die Automatisierung.
Analyse
- Wireshark – das Hauptwerkzeug. Follow TCP Stream, Expert Info, Statistics > Conversations, IO Graph zur Visualisierung von Pausen und Retransmission-Spitzen.
- editcap – pcap schneiden und filtern, TLS-Keys in pcapng einbetten.
- mergecap – Rotationsdateien für die Analyse zusammenfügen.
- capinfos – schnelle Zusammenfassung einer Datei: Dauer, Paketanzahl, Größe.
Clients mit Debug-Unterstützung
- curl mit -v und --trace-time spiegelt das Bild des Mitschnitts auf Anwendungsebene und unterstützt SSLKEYLOGFILE.
- openssl s_client -proxy host:port ermöglicht, CONNECT und TLS-Handshake über den Proxy manuell auszuführen und die Antwort des Servers ohne HTTP-Client zu sehen.
Nützliche Einzeiler
Rotationsdateien zusammenfügen:
mergecap -w all.pcapng proxy-*.pcapNur einen Stream aus dem Mitschnitt für den Support herausschneiden:
tshark -r all.pcapng -Y 'tcp.stream eq 42' -w stream42.pcapngSchnelle Statistik über Streams mit RST:
tshark -r all.pcapng -q -z conv,tcp | head -40Manueller CONNECT-Test über openssl:
openssl s_client -proxy 203.0.113.10:8080 -connect api.example.com:443 -servername api.example.com -briefFallstudien und Ergebnisse
Fall 1: Zwei Prozent Abbrüche, schuld war der Client
Ein Preissammel-Service lief über einen Pool mobiler Proxys mit etwa 40.000 Anfragen pro Tag. Etwa 2,3 Prozent der Anfragen scheiterten mit RemoteDisconnected. Das Team war sicher, die Proxys seien schuld. Man erstellte einen Mitschnitt mit 100-MB-Rotation über einen Tag, filterte tcp.flags.reset == 1 und schaute auf ip.src. In 91 Prozent der Fälle sendete der Client selbst das RST. Die Analyse der Streams zeigte: Vor dem RST herrschte genau 5 Sekunden Stille nach dem Senden der Anfrage, dann RST vom Client. Im Code stand ein read timeout von 5 Sekunden, aber der Zielserver antwortete in Spitzenzeiten erst nach 6–8 Sekunden. Die Erhöhung des Timeouts auf 15 Sekunden senkte die Fehler auf 0,3 Prozent. Die restlichen 0,3 Prozent waren echte FINs vom Proxy 160–200 ms nach dem ClientHello: Der Server lehnte zeitweise Verbindungen von einem Teil des Adresspools ab. Diese Daten wurden an den Support übergeben, der das Bild anhand seiner Zone-C-Logs bestätigte.
Fall 2: Abbrüche großer Downloads genau alle 10 Minuten
Ein Client lud 300–800 MB große Archive über einen mobilen Proxy herunter und klagte über Abbrüche in der Mitte. Der Mitschnitt zeigte RSTs vom Proxy in Abständen von genau 600 Sekunden, sekundengenau, unabhängig vom Downloadstart. Die Ursache war die auf 10 Minuten eingestellte zeitbasierte IP-Rotation: Beim Adresswechsel schließt der Proxy aktive Tunnel. Die Lösung war, den Port auf Rotation auf Anfrage umzustellen und den Adresswechsel zwischen Downloads auszulösen. Die Abbrüche verschwanden vollständig; die Diagnose dauerte zwei Stunden statt wochenlanger Korrespondenz.
Fall 3: Der Server liegt, aber es sieht aus, als sei der Proxy schuld
Am Morgen begannen alle Anfragen an eine API, Verbindungsfehler zurückzugeben. Client-Logs: Connection aborted. Erste Reaktion: Der Proxy ist down. Ein Mitschnitt über eine Minute zeigte: Die TCP-Verbindung zum Proxy kommt in 38 ms zustande, CONNECT geht raus, und nach 30 Sekunden kommt 504 und FIN. Gleichzeitig lief eine Anfrage an einen anderen Host über denselben Proxy in 300 ms durch. Diagnose: Der Zielserver nimmt keine Verbindungen vom Proxy an. 40 Minuten später bestätigte die Statusseite des Zielservices einen Vorfall auf dessen Seite. Der Mitschnitt sparte einen Morgen und verhinderte ein falsches Ticket beim Proxy-Support.
Fall 4: WLAN-Verluste sahen wie ein Proxy-Problem aus
Ein Entwickler testete eine Integration von einem Laptop über den mobilen Proxeon-Proxy und bekam sporadische Timeouts. Der Mitschnitt zeigte Retransmissions vom Client mit einer Rate von 6 Prozent und Duplicate ACKs vom Proxy, aber kein einziges RST vom Proxy. Der Anschluss des Laptops per Kabel senkte die Retransmissions auf null, die Timeouts verschwanden. Das Problem lag im überlasteten Access Point des Büros.
Checkliste zum Erstellen eines Mitschnitts für den Support
Wenn du einen Mitschnitt an den Support eines Proxy-Dienstes senden willst, hier die Reihenfolge, die beiden Seiten Zeit spart.
Vorbereitung
- Synchronisiere die Uhr der Maschine per NTP. Prüfe mit timedatectl oder date -u.
- Wenn möglich, richte für die Diagnose separate Test-Zugangsdaten beim Proxy ein oder plane einen Passwortwechsel nach dem Versand des Mitschnitts.
- Notiere Version des Clients, HTTP-Bibliothek, Betriebssystem und Art der Internetanbindung (Kabel, WLAN, Mobilfunk).
- Notiere Adresse und Port des Proxys, Zielhost, erwartetes und tatsächliches Verhalten.
Capture
- Starte tcpdump mit Filter auf Host und Port des Proxys, mit Rotation, voller Paketgröße:
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'- Reproduziere das Problem. Wenn es selten auftritt, lass den Capture entsprechend laufen; 48 Dateien à 5 Minuten decken 4 Stunden ab.
- Mache gleichzeitig eine Kontrollanfrage mit curl -v und --trace-time und speichere die Ausgabe. Sie liefert die genaue zeitliche Zuordnung zu den Paketen.
- Notiere die genaue Zeit (UTC) jedes Auftretens des Fehlers aus den Client-Logs.
- Stoppe tcpdump mit Ctrl+C. Stelle sicher, dass die Dateien nicht leer sind: capinfos proxy-*.pcap.
Aufbereitung
- Füge die Dateien zusammen: mergecap -w all.pcapng proxy-*.pcap.
- Finde die problematischen Streams mit dem Filter tcp.flags.reset == 1 oder über die Zeit aus den Logs.
- Schneide nur die benötigten Streams heraus: tshark -r all.pcapng -Y 'tcp.stream in {12 47 93}' -w report.pcapng. Der Support braucht keine Stunden normalen Traffics.
- Prüfe, dass im herausgeschnittenen Mitschnitt nichts Überflüssiges ist: fremde Verbindungen, Traffic anderer Dienste.
- Die TLS-Key-Datei nicht beilegen.
Text der Anfrage
- Zeitpunkt des Auftretens in UTC, sekundengenau.
- Adresse und Port des Proxys, Zielhost.
- Kurze Interpretation: Was du im Mitschnitt siehst (zum Beispiel 200 auf CONNECT, dann FIN vom Proxy 170 ms nach dem ClientHello, RTT zum Proxy 45 ms).
- Frame- oder Stream-Nummern in der beigefügten Datei.
- Ausgabe von curl -v mit Zeitmarken.
- Was du bereits geprüft und ausgeschlossen hast: anderer Host über denselben Proxy, derselbe Host über eine andere Anbindung.
Eine solche Anfrage bearbeitet der Support in einem Durchgang. Es genügt, deine Zeitmarken mit den Zone-C-Logs abzugleichen und die Version zu bestätigen oder zu widerlegen.
FAQ
Warum ist im Mitschnitt keine IP-Adresse des Zielservers, ich rufe ihn doch auf?
Weil du ihn nicht direkt aufrufst, sondern über den Proxy. Dein Client baut eine TCP-Verbindung zur Proxy-Adresse auf und bittet ihn, sich mit dem Zielhost zu verbinden. Die Verbindung Proxy – Server existiert nur auf Seiten des Proxys. Im Mitschnitt ist der Name des Zielhosts in der CONNECT-Zeile und im SNI innerhalb des ClientHello sichtbar, aber Pakete an seine IP von deiner Maschine gibt es nicht und kann es nicht geben.
Kann man am Mitschnitt erkennen, welche externe IP der Proxy für die Anfrage an den Server verwendet hat?
Nein. Diese Information gehört zu Zone C. Die einzige Möglichkeit ist, über den Proxy einen Dienst abzufragen, der die Client-Adresse zurückgibt, oder im Kundenkonto des Anbieters nachzuschauen, welche Adresse zu diesem Zeitpunkt aktiv war.
Der Proxy hat RST gesendet. Liegt das Problem also beim Proxy?
Nicht unbedingt. Ein RST von der Proxy-Adresse bedeutet, dass der Tunnel von der Proxy-Seite geschlossen wurde, und die Ursache kann beim Zielserver oder im Netzwerk hinter dem Proxy liegen. Schau auf das Timing: Wenn das RST deutlich mehr als die RTT zum Proxy nach deinem letzten Paket kommt, hat der Proxy wahrscheinlich die Reaktion des Servers übersetzt. Wenn das RST zu einem festen Zeitpunkt oder nach einem exakten Intervall kommt, ist eine Policy des Proxys wahrscheinlich, etwa Rotation oder Limit.
Wie misst man die RTT zum Proxy am Mitschnitt?
Differenz der Zeit zwischen SYN von dir und SYN-ACK vom Proxy zu Beginn einer beliebigen Verbindung. In Wireshark kann man Statistics > TCP Stream Graphs > Round Trip Time für den Stream einschalten oder das Feld tcp.analysis.ack_rtt als Spalte nutzen.
Wireshark zeigt kein TLS im Tunnel, nur TCP-Daten. Was tun?
Klicke mit der rechten Maustaste auf das Paket nach der Antwort 200 Connection established, wähle Decode As und in der Spalte Current TLS für den TCP-Port des Proxys. Stelle außerdem sicher, dass die Pakete nicht abgeschnitten sind (-s 0 beim Capture) und dass der HTTP-Dissector auf den Proxy-Port eingestellt ist, falls er nicht Standard ist: Edit > Preferences > Protocols > HTTP > TCP ports.
Worin unterscheidet sich dieser Ansatz von mitmproxy?
mitmproxy arbeitet auf Anwendungsebene: Es terminiert TLS mit einem gefälschten Zertifikat, liest und kann HTTP-Anfragen verändern. Dafür muss der Client seinem Root-Zertifikat vertrauen. tcpdump und Wireshark arbeiten auf Paketebene und ersetzen nichts: Du siehst echte Pakete, echte Flags und Timings, einschließlich TCP-Fehler, die mitmproxy verbergen würde, weil es sie selbst behandeln würde. Für die Diagnose von Abbrüchen ist die Paketebene ehrlicher. Für das Anschauen von Anfrageinhalten ist mitmproxy bequemer, aber bei Bedarf kann man den Inhalt des eigenen Traffics auch in Wireshark über SSLKEYLOGFILE ohne Zertifikatsersetzung sehen.
Kann man in Wireshark den Traffic entschlüsseln, den der Proxy mit dem Server führt?
Nein. Du hast weder die Pakete dieser Verbindung noch die Keys dazu. SSLKEYLOGFILE liefert nur Keys von Sessions deines Clients, und innerhalb des CONNECT-Tunnels ist das genau deine Session mit dem Server, deshalb lässt sie sich entschlüsseln. Aber ein separates TLS zwischen Proxy und Server gibt es beim CONNECT nicht: Der Proxy leitet einfach deine Bytes weiter.
Wie erkennt man, dass der Client am Proxy vorbei leakt?
Erstelle einen Mitschnitt nicht mit Filter auf den Proxy, sondern mit Filter auf dein gesamtes Interface, und schaue auf ausgehende Verbindungen an Ports 80 und 443 zu Adressen, die nicht der Proxy sind, sowie auf UDP 443 (QUIC) und DNS-Anfragen an externe Resolver mit Namen der Zielhosts. Wireshark-Filter: (tcp.port == 443 || udp.port == 443) && !(ip.addr == 203.0.113.10). Jede Übereinstimmung ist eine Konfigurationslücke.
Wie groß sollte ein Mitschnitt für den Support sein?
Je kleiner, desto besser. Ein herausgeschnittener problematischer Stream belegt 5 bis 500 KB. Eine Datei über 50 MB analysiert der Support länger, und die Hälfte davon ist normaler Traffic. Schneide die benötigten Streams mit tshark oder File > Export Specified Packets in Wireshark heraus.
Was tun, wenn tcpdump auf einer virtuellen Maschine Pakete größer als die MTU zeigt?
Das ist Generic Segmentation Offload: Der Kernel übergibt tcpdump große Segmente, bevor die Netzwerkkarte sie zerteilt. Auf die Analyse von Flags, Timings und Abbrüchen hat das keinen Einfluss. Wenn es stört, deaktiviere das Offload für den Capture mit ethtool -K eth0 gso off tso off gro off, aber bedenke, dass das die Netzwerkleistung senkt.
Fazit
Ein Traffic-Mitschnitt bei der Arbeit über einen Proxy ist kein Spähen nach Inhalten und keine Magie. Es ist eine ehrliche Aufzeichnung dessen, was tatsächlich auf der Leitung passiert ist: millisekundengenau und bis zum letzten Flag. Das Client-Log sagt, dass die Verbindung abgebrochen ist. Der Mitschnitt sagt, wer es getan hat, wann genau und was davor passiert ist.
Fassen wir die Methodik zusammen. Auf dem Client-Rechner siehst du nur die Verbindung zum Proxy: TCP-Handshake, CONNECT- oder SOCKS-Dialog und verschlüsselte TLS-Records im Tunnel. Der Zielserver ist nicht direkt sichtbar, aber sein Verhalten wird vom Proxy über Antwortcodes auf CONNECT, Timings und die Art des Tunnel-Schließens übersetzt. RST oder FIN von deiner Adresse – dein Problem oder dein Timeout. Retransmissions und Duplicate ACKs ohne Schließen – Verluste auf dem Weg zum Proxy. Schließen vom Proxy nach einer Zeit, die deutlich über der RTT zu ihm liegt – übersetzte Reaktion des Servers. Schließen zu festen Zeitpunkten – Policy des Proxys. Zero Window von dir – deine Anwendung liest nicht.
Praktische Schritte für heute: Lege die tcpdump-Befehle mit Rotation und die Wireshark-Filter aus diesem Artikel in deine Lesezeichen; prüfe, ob die Uhren auf den Maschinen, auf denen deine Clients laufen, synchronisiert sind; stelle sicher, dass dein Client kein QUIC-Leck am Proxy vorbei hat; lege Test-Zugangsdaten für die Diagnose an, um keine produktiven in Mitschnitten preiszugeben. Und wenn das Log das nächste Mal connection reset by peer sagt, rate nicht. Erstelle einen Mitschnitt, öffne den Stream, schau auf Richtung und Zeit. Nach fünf Minuten weißt du, wem du schreiben musst: dir selbst, dem Proxy-Support oder dem Betreiber des Zielservers.