Les logs du client sont parfaits tant qu'ils racontent quelque chose. Mais un jour, tu te heurtes à un mur : l'appli écrit un laconique connection reset, le proxy ne dit rien dans ses logs, et le serveur cible jure que tout va bien chez lui. Qui ment ? Personne. Simplement, tu regardes le problème depuis le dernier étage, alors que la vérité vit au niveau des paquets. Et il faut descendre jusque-là.

Cet article est un guide d'ingénierie détaillé sur l'usage de tcpdump et Wireshark quand le trafic passe par un proxy. On va voir ce qu'un observateur voit avant le proxy et après lui, pourquoi à l'intérieur d'un tunnel HTTPS on ne voit que la requête CONNECT et rien d'autre, et comment distinguer, à partir d'une seule capture, une coupure de ton côté d'une coupure côté serveur cible. Il ne s'agit pas d'interception ni de substitution HTTPS au niveau applicatif : on parle ici du niveau paquet et d'un diagnostic honnête des coupures.

Introduction : quand les logs du client ne suffisent plus

Imagine une infra classique. Ton appli appelle une API externe via un proxy HTTP Proxeon. D'habitude, tout roule. Mais cinq pour cent des requêtes échouent, et tu ne comprends pas pourquoi. Les logs de l'appli montrent juste le fait : la connexion a été coupée. Les logs du proxy montrent que le tunnel a bien été établi. Le serveur cible est hors de ton contrôle. Tu es coincé entre trois boîtes noires.

C'est exactement là que commence le diagnostic au niveau paquet. Une capture de trafic, c'est la transcription fidèle d'une conversation entre machines, enregistrée mot pour mot, sans interprétation et sans droit de mentir. Un paquet est soit arrivé, soit pas. Le flag RST est soit présent, soit absent. TCP ne sait pas faire semblant. Et si tu apprends à lire cette transcription, tu arrêteras de deviner.

Dans ce guide, tu vas découvrir : comment capturer avec tcpdump sans remplir ton disque de gigaoctets ; quels filtres d'affichage Wireshark te font gagner des heures ; comment lire un handshake TLS même sans déchiffrer ; comment identifier le coupable d'une coupure grâce aux flags ; et comment déchiffrer légalement ton propre trafic via la variable SSLKEYLOGFILE. À la fin, tu trouveras une checklist prête à l'emploi pour contacter le support et une FAQ détaillée.

Les bases : trois segments pour une seule connexion

La première chose à bien ancrer dans ta tête : quand un client passe par un proxy, ce n'est pas une seule connexion, mais au moins deux connexions TCP distinctes. L'une va du client au proxy. L'autre va du proxy au serveur cible. C'est le socle sans lequel tout le reste n'a pas de sens.

Qu'est-ce qu'une capture et comment c'est fait

Une capture de paquets, c'est une séquence de paquets réseau capturés sur une interface réseau précise d'une machine précise. Le mot clé, c'est précise. Tu ne vois jamais que le trafic qui traverse physiquement le point de capture. En capturant sur le client, tu vois la conversation client-proxy. En capturant sur le proxy, tu vois les deux côtés. Sur le serveur cible, tu ne vois que la conversation proxy-serveur.

Chaque paquet porte des en-têtes de niveau : Ethernet, IP, TCP ou UDP, et une charge utile. Pour diagnostiquer des coupures, c'est le niveau TCP qui nous intéresse en premier : numéros de ports, numéros de séquence (sequence), accusés de réception (ACK) et flags — SYN, ACK, FIN, RST, PSH.

Le modèle du proxy : deux connexions au lieu d'une

Décomposons le trajet du trafic avec un proxy HTTP en mode tunnel :

  • Segment A (client - proxy). Le client ouvre une connexion TCP vers l'IP et le port du proxy. Sur ce canal, il envoie la commande pour établir un tunnel.
  • Segment B (proxy - serveur cible). Le proxy ouvre, en son propre nom, une connexion TCP distincte vers le serveur cible. C'est déjà une autre IP source, un autre port source, un autre état.
  • Tunnel logique. Une fois établis, le proxy se met à recopier aveuglément les octets du segment A vers le segment B et inversement. Il ne regarde pas ce qu'il y a dedans.

Pourquoi c'est crucial pour le diagnostic ? Parce qu'une coupure peut survenir sur l'un ou l'autre des deux segments, et du point de vue du client, le symptôme sera identique : la connexion est tombée. Mais la cause, et donc la solution, sont différentes.

Proxy HTTP, SOCKS et tunnellisation

Pour une requête HTTP non chiffrée, le proxy voit la méthode, l'URL et les en-têtes. Mais dès qu'on parle de HTTPS, la donne change. Le client ne peut pas confier au proxy une requête non chiffrée — sinon le chiffrement ne sert à rien. C'est là qu'intervient le mécanisme de tunnellisation : le client dit au proxy connecte-moi à tel hôte sur tel port, puis n'intervient plus. Cette commande, c'est le CONNECT.

Au cœur du sujet : pourquoi on ne voit que CONNECT dans un tunnel

C'est sans doute la source de perplexité la plus fréquente chez les ingénieurs qui ouvrent pour la première fois une capture HTTPS à travers un proxy. Tu t'attends à voir des requêtes et des réponses, et tu vois une seule ligne puis une bouillie illisible. Voyons pourquoi, et pourquoi c'est normal.

Anatomie du CONNECT

Quand un client veut établir une connexion sécurisée via un proxy, il envoie d'abord cette requête au proxy en clair :

CONNECT api.example.com:443 HTTP/1.1\r\nHost: api.example.com:443\r\n\r\n

Le proxy ouvre une connexion TCP vers api.example.com sur le port 443, et si tout se passe bien, il répond au client :

HTTP/1.1 200 Connection established\r\n\r\n

À partir de ce moment, le proxy devient un simple tuyau. Tout ce que le client enverra ensuite, le proxy le transmettra au serveur octet par octet, et inversement. Et qu'envoie le client ensuite ? Le ClientHello TLS, le début du handshake. Un échange chiffré. Le proxy n'a pas les clés et ne peut physiquement pas regarder dedans.

Ce que cela signifie pour l'observateur d'une capture

Si tu captures sur le client ou sur le proxy, tu verras :

  • L'établissement de la connexion TCP vers le proxy (SYN, SYN-ACK, ACK).
  • Le texte en clair de la requête CONNECT avec le nom de l'hôte cible et le port.
  • La réponse du proxy sur le statut d'établissement du tunnel.
  • Et ensuite — uniquement des enregistrements TLS, un flux chiffré dont on ne lit à l'œil nu que les métadonnées du handshake.

Voilà l'insight principal : le nom de l'hôte cible est toujours visible dans la capture — dans la ligne CONNECT. Même sans un seul octet déchiffré, tu sais exactement où le client tentait d'aller. C'est inestimable en diagnostic : tu élimines d'emblée la question est-ce que la requête allait bien là-bas.

Le SNI TLS : une deuxième source pour le nom d'hôte

Même sans CONNECT (par exemple en connexion directe sans proxy), le nom d'hôte est souvent visible dans le champ SNI au sein du ClientHello. Le Server Name Indication est transmis en clair au début du handshake. Wireshark l'affiche parfaitement. Dans les réseaux modernes, Encrypted Client Hello gagne du terrain pour masquer le SNI, mais à travers un tunnel CONNECT, cela ne gêne pas le diagnostic — le nom d'hôte a déjà été annoncé dans le CONNECT lui-même.

tcpdump en pratique : capturer sans générer des gigaoctets

Passons à la pratique. tcpdump est un utilitaire en ligne de commande pour capturer des paquets, disponible sur presque tout système de type Unix. Il est puissant, léger, et irremplaçable sur les serveurs sans interface graphique. Voyons les scénarios clés.

Capture de base sur la bonne interface

D'abord, listons les interfaces :

tcpdump -D

Capture sur une interface précise avec affichage à l'écran :

tcpdump -i eth0 -n

Le flag -n désactive la résolution de noms pour que tcpdump ne ralentisse pas sur les requêtes DNS et affiche des IP brutes. C'est important : la résolution en temps réel fausse l'image et ralentit la capture.

Filtrer par hôte et par port

Capturer tout le trafic d'une interface sur un serveur chargé, c'est le chemin direct vers des gigaoctets de déchets. Filtre dès le début. Capture du trafic vers un proxy précis par IP et port :

tcpdump -i eth0 -n host 203.0.113.10 and port 8080

Capture uniquement vers le serveur cible (utile côté proxy) :

tcpdump -i eth0 -n host api.example.com and port 443

Combinaison : trafic vers le proxy OU vers le serveur cible :

tcpdump -i eth0 -n "(host 203.0.113.10 and port 8080) or (host 198.51.100.5 and port 443)"

Attention aux guillemets : quand l'expression contient des parenthèses et des opérateurs logiques, entoure le filtre de guillemets pour que le shell n'interprète pas les caractères spéciaux.

Écrire dans un fichier et choisir le bon format

Pour analyser ensuite dans Wireshark, il faut un fichier au format pcap. Le flag -w écrit les paquets bruts dans un fichier :

tcpdump -i eth0 -n host 203.0.113.10 and port 8080 -w dump.pcap

Point essentiel : -s 0, ou le comportement moderne par défaut, capture le paquet entier (snaplen). Les anciennes versions tronquaient les paquets. Si tu veux les données complètes, assure-toi que le snaplen est suffisant :

tcpdump -i eth0 -n -s 0 host 203.0.113.10 and port 8080 -w dump.pcap

Si tu n'as besoin que des en-têtes pour diagnostiquer les coupures (flags, seq, ack) et pas du contenu, limite le snaplen pour que le fichier soit plus compact :

tcpdump -i eth0 -n -s 96 host 203.0.113.10 and port 8080 -w headers.pcap

Rotation des fichiers : comment ne pas saturer le disque

Pour un diagnostic long d'un problème intermittent, la capture peut tourner des heures. Pour éviter un fichier monstrueux, utilise la rotation par taille et par nombre de fichiers. Le flag -C définit la taille du fichier en mégaoctets, -W le nombre de fichiers dans le buffer circulaire :

tcpdump -i eth0 -n host 203.0.113.10 and port 8080 -w dump-%Y%m%d-%H%M%S.pcap -C 100 -W 10

Cette commande créera jusqu'à dix fichiers de cent mégaoctets. Quand le dixième sera plein, tcpdump recommencera à écraser le premier. Tu conserves ainsi toujours à peu près le dernier gigaoctet de trafic et tu ne satureras jamais le disque. Le motif temporel dans le nom du fichier rend l'archive lisible.

Alternative — la rotation par le temps. Le flag -G définit un intervalle en secondes après lequel un nouveau fichier est créé :

tcpdump -i eth0 -n host 203.0.113.10 and port 8080 -G 3600 -w dump-%Y%m%d-%H%M%S.pcap

Un nouveau fichier chaque heure. Pratique pour retrouver ensuite rapidement l'intervalle correspondant au moment de l'incident.

Capturer autour de l'événement : attraper une coupure rare

La situation la plus sournoise : le problème se reproduit une fois par heure, de façon imprévisible. Tu lances un buffer circulaire et tu attends. Dès que l'appli a enregistré l'erreur, tu notes l'heure précise et tu arrêtes la capture. Ensuite, dans l'analyse, tu vas à la seconde voulue. Astuce pratique : fais écrire à ton appli un horodatage précis à la milliseconde dans ses logs en cas d'erreur — c'est ton ancre dans la capture.

Filtrer par flags TCP directement dans tcpdump

Parfois, il est utile de ne capturer que les paquets portant certains flags. Par exemple, uniquement les paquets avec le flag RST, pour savoir tout de suite si des resets circulent :

tcpdump -i eth0 -n "tcp[tcpflags] & tcp-rst != 0"

Uniquement les paquets SYN — pratique pour suivre les tentatives d'établissement de connexion :

tcpdump -i eth0 -n "tcp[tcpflags] & tcp-syn != 0"

Combinaison RST ou FIN pour surveiller les fermetures de connexion vers le proxy :

tcpdump -i eth0 -n "host 203.0.113.10 and (tcp[tcpflags] & (tcp-rst|tcp-fin) != 0)"

Wireshark : lire une capture comme un livre ouvert

tcpdump capture, Wireshark lit. C'est un analyseur graphique avec un système très riche de filtres d'affichage et de décodeurs de protocoles. Tu ouvres ton fichier pcap sauvegardé et tu commences l'enquête. Voyons les outils vraiment utiles pour notre tâche.

Filtres d'affichage vs filtres de capture

Important de ne pas confondre. Le filtre de capture (celui de tcpdump) écarte les paquets avant l'écriture — ce qui n'est pas capturé n'existe pas. Le filtre d'affichage dans Wireshark, c'est une loupe : il ne fait que masquer le superflu dans un fichier déjà chargé, sans rien supprimer. Leur syntaxe est différente. Ci-dessous, ce sont bien des filtres d'affichage.

Filtres d'affichage de base

Afficher uniquement le trafic vers une IP précise :

ip.addr == 203.0.113.10

Uniquement le port TCP du proxy :

tcp.port == 8080

Combinaison hôte et port :

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

Afficher uniquement les paquets avec le flag RST — on voit instantanément tous les resets de connexion :

tcp.flags.reset == 1

Uniquement les paquets avec FIN :

tcp.flags.fin == 1

Uniquement les SYN sans ACK — les tentatives d'ouverture de connexion :

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

Chercher CONNECT et les en-têtes HTTP

Pour trouver la requête CONNECT elle-même dans la capture :

http.request.method == "CONNECT"

La réponse du proxy annonçant l'établissement du tunnel apparaît comme une réponse HTTP. Filtrer toutes les requêtes HTTP :

http.request

Toutes les réponses HTTP avec leurs codes :

http.response

Follow TCP Stream : reconstituer la conversation

C'est sans doute la fonction la plus précieuse de Wireshark pour notre tâche. Clic droit sur n'importe quel paquet de la connexion, puis Follow, puis TCP Stream. Wireshark rassemblera tout l'échange bidirectionnel dans une seule fenêtre, où les données du client et du serveur sont affichées dans des couleurs différentes. Pour du trafic non chiffré, tu verras du texte clair : la requête CONNECT, la réponse du proxy, puis des octets TLS illisibles.

C'est justement dans Follow Stream que tu vois le basculement au CONNECT. Les premières lignes se lisent comme du texte humain, puis commence la zone chiffrée. Cela confirme : le tunnel est établi, à partir de là c'est du chiffrement, et sans clés on ne peut pas aller plus loin — ce qui est parfaitement normal.

Lire un handshake TLS sans déchiffrement

Même sans clés, un handshake TLS raconte beaucoup. Filtre les enregistrements de handshake :

tls.handshake

Trouver le ClientHello, où le client se présente au serveur :

tls.handshake.type == 1

Trouver le ServerHello, la réponse du serveur :

tls.handshake.type == 2

Que nous apporte cette paire ? Si tu vois un ClientHello mais jamais de ServerHello — le serveur n'a pas répondu au handshake. Cause : soit le serveur cible est injoignable à travers le proxy, soit la coupure est survenue avant la réponse. Si tu vois les deux, puis une coupure — le problème est plus profond, dans l'échange chiffré ou au niveau applicatif.

À l'intérieur du ClientHello, sans aucun déchiffrement, on lit le champ SNI — le nom de l'hôte contacté :

tls.handshake.extensions_server_name == "api.example.com"

Tu vois aussi les versions TLS proposées et les suites de chiffrement. Si le serveur répond par un Alert au lieu d'un ServerHello, c'est que le handshake est refusé — par exemple à cause d'une incompatibilité de versions ou de suites. Filtre pour les alertes :

tls.alert_message

Diagnostic à partir de la capture : qui a coupé la connexion

Nous voici au cœur de l'article. La connexion est tombée — la question est de savoir qui l'a coupée et pourquoi. TCP laisse des indices, et on peut trancher grâce à eux. Voyons les signaux clés.

Fermeture normale : FIN

La fermeture propre d'une connexion se fait via un échange de paquets FIN. Une partie dit j'ai fini de transmettre, l'autre accuse réception et envoie aussi un FIN. C'est un au revoir poli. Si dans ta capture tu vois un échange propre FIN-ACK-FIN-ACK, la connexion s'est fermée correctement. La seule question est de savoir si ton client attendait cette fermeture. Si le serveur a envoyé le FIN après avoir livré la réponse complète, tout va bien. Si le FIN arrive au milieu des données attendues, le serveur a fermé trop tôt.

Fermeture brutale : RST

Le flag RST, c'est une coupure brutale. Pas un au revoir, mais un claquement de porte. RST veut dire : cette connexion n'est plus valide, oublie-la immédiatement. Les causes varient :

  • Port fermé — personne n'écoute de l'autre côté. Le RST arrive presque instantanément après le SYN.
  • L'application côté serveur a fermé le socket de manière anormale.
  • Un équipement intermédiaire (pare-feu, load balancer, le proxy lui-même) a réinitialisé la connexion sur timeout ou par politique.
  • Une des parties a reçu un paquet pour une connexion dont elle avait déjà oublié l'existence.

La clé du mystère, c'est qui a envoyé le RST. Regarde l'IP source du paquet avec RST. Si le RST vient de l'IP du proxy — c'est le proxy, ou quelque chose entre le proxy et toi, qui a coupé. Si c'est l'IP du serveur cible — alors le segment proxy-serveur a atteint le serveur, et c'est lui, ou un équipement à côté de lui, qui a coupé.

Mais souviens-toi des deux segments. En capturant sur le client, tu ne vois le RST que depuis l'IP du proxy, parce que tu ne communiques pas directement avec le serveur — le proxy est entre vous. Pour comprendre ce qui se passe sur le segment B, il faut une capture côté proxy. On en parle dans la section sur la checklist.

Retransmissions : retransmission

Wireshark marque automatiquement les retransmissions. Filtre :

tcp.analysis.retransmission

Une retransmission signifie que l'émetteur n'a pas reçu d'ACK pour le segment envoyé dans les délais et le renvoie. Quelques retransmissions isolées, c'est normal sur Internet. Mais une avalanche de retransmissions, c'est le symptôme de pertes de paquets sur le chemin. C'est particulièrement typique des réseaux mobiles et instables.

Filtres utiles associés. Les ACK en double, qui signalent un segment manquant :

tcp.analysis.duplicate_ack

Tous les événements problématiques que Wireshark a pu reconnaître :

tcp.analysis.flags

Si tu vois une série de retransmissions suivie d'un RST, le tableau se reconstitue : des paquets se perdaient, une des parties a cessé d'attendre et a coupé la connexion. C'est une histoire classique de mauvaise liaison.

Zero Window : le récepteur est saturé

TCP dispose d'un mécanisme de contrôle de flux via la fenêtre de réception. Si le récepteur n'arrive pas à traiter les données, il annonce zero window — le buffer est plein, freine. Filtre :

tcp.analysis.zero_window

Zero window, ce n'est pas une perte réseau, mais le signal que l'application réceptrice lit lentement depuis le socket. Par exemple, ton client reçoit une grosse réponse mais la traite en un seul thread et n'arrive pas à suivre. L'émetteur attend, la fenêtre ne s'ouvre pas, et à la fin un timeout peut se déclencher. Si après un zero window arrive un window update, tout est rentré dans l'ordre. Si après un zero window il n'y a que du silence puis un RST — le récepteur a planté ou est tombé.

Signal cousin — window full, quand l'émetteur bute sur la fenêtre annoncée et ne peut plus rien envoyer :

tcp.analysis.window_full

Matrice des verdicts

Rassemblons la logique dans un cadre pratique. Regarde les derniers paquets de la connexion vivante avant la coupure :

  • SYN présent, pas de SYN-ACK, puis RST ou silence. La connexion ne s'est pas établie. Le point cible est injoignable ou le port est fermé. À travers un proxy, le RST viendra du proxy si le serveur derrière lui est injoignable.
  • Établissement réussi, CONNECT envoyé, pas de réponse. Le proxy a accepté la commande mais n'a pas pu joindre le serveur cible, ou celui-ci reste muet. Attends le timeout.
  • ClientHello présent, pas de ServerHello. Le serveur cible n'a pas répondu au handshake. Le problème est sur le segment proxy-serveur.
  • Des données circulaient, puis RST du serveur. Le serveur a fermé la connexion brutalement — surcharge, erreur applicative, timeout de son côté.
  • Des données circulaient, puis FIN du serveur au milieu de la réponse. Le serveur a fermé proprement, mais plus tôt que le client ne l'attendait — sans doute une limite sur la taille de la réponse ou un timeout de requête.
  • Avalanche de retransmissions, puis RST. Pertes sur le canal. Cherche le problème dans le réseau — connexion mobile, route saturée.
  • Zero window, puis silence. Ton client ne lisait pas les données assez vite. Le problème est de ton côté, dans le traitement.

Déchiffrer son propre trafic via SSLKEYLOGFILE

Parfois les seules métadonnées ne suffisent pas — il faut voir le contenu de l'échange chiffré. C'est légal et correct uniquement quand le trafic est le tien : ton client, tes clés, ton application. On n'intercepte rien chez les autres et on ne remplace aucun certificat. On demande juste à notre propre client de bien vouloir écrire les clés de session dans un fichier, pour ensuite les donner à Wireshark.

Comment ça marche

Beaucoup de bibliothèques TLS côté client supportent la variable d'environnement SSLKEYLOGFILE. Si elle est définie, la bibliothèque ajoute dans le fichier indiqué les secrets de session dans un format standard. Wireshark sait lire ce fichier et déchiffrer les sessions correspondantes dans la capture. Aucune magie, aucun piratage — le client livre volontairement ses propres clés, parce que toi, propriétaire du client, tu en as décidé ainsi.

Exemple en ligne de commande et pour les navigateurs sur moteur compatible

Définir la variable avant de lancer l'application sous un système de type Unix :

export SSLKEYLOGFILE=/home/user/tls-keys.log

Lancer un client, par exemple curl, qui supporte cette variable quand il est compilé avec une bibliothèque adéquate :

SSLKEYLOGFILE=/home/user/tls-keys.log curl -x http://203.0.113.10:8080 https://api.example.com/status

Ici, le flag -x définit le proxy Proxeon, et SSLKEYLOGFILE force l'écriture des clés de session. En parallèle, tu captures avec tcpdump. Après ça, tu as à la fois le pcap et le fichier de clés.

Connecter les clés dans Wireshark

Dans Wireshark, ouvre les paramètres, trouve la section du protocole TLS, indique le chemin vers le fichier de clés dans le champ prévu pour le fichier de log des pre-master secrets. Ensuite, relis la capture. Les enregistrements TLS jusqu'alors illisibles deviennent déchiffrés : tu vois les vraies requêtes et réponses HTTP à l'intérieur du tunnel. Maintenant, Follow TLS Stream affiche l'échange applicatif dans son intégralité.

Limites importantes

  • Seul le trafic dont les clés sont dans le fichier est déchiffré. Les sessions des autres restent chiffrées — et c'est très bien ainsi.
  • Les clés sont sensibles. Le fichier tls-keys.log ouvre de fait le contenu de tes sessions. Garde-le comme un secret, supprime-le après le débogage.
  • La méthode est destinée au débogage de tes propres applications, pas à l'observation du trafic des autres. C'est une frontière éthique et juridique de principe.

Les tableaux typiques de coupure et comment les lire

La théorie sans patterns reconnaissables s'évapore vite. Voyons quelques scénarios caractéristiques que tu rencontreras encore et encore. Apprends à les reconnaître au premier coup d'œil.

Timeout de connexion : serveur injoignable derrière le proxy

Tableau dans la capture côté client : la connexion TCP vers le proxy s'établit normalement, le client envoie CONNECT, puis silence. Pas de réponse 200 du proxy. Au bout d'un moment, soit un RST arrive du proxy, soit l'application ferme elle-même la connexion sur son propre timeout.

Ce que ça veut dire : le proxy a accepté ta commande, a tenté d'ouvrir le segment B vers le serveur cible, mais celui-ci n'a pas répondu. Le serveur cible est down, le port est fermé, ou la route jusqu'à lui est coupée. Ton côté et le proxy fonctionnent normalement. Action : vérifier l'accessibilité de l'hôte cible, et si besoin capturer côté proxy pour voir le segment B.

Coupure au milieu de la réponse

Tableau : le tunnel est établi, TLS a fonctionné, les données commencent à circuler, une partie de la réponse est reçue, puis soudain un FIN ou un RST du côté serveur. Le client a reçu une réponse incomplète et râle sur un contenu tronqué.

Si c'est un FIN, le serveur a fermé proprement, mais prématurément — peut-être une limite de temps de génération de la réponse ou une contrainte de taille de son côté. Si c'est un RST, le serveur ou un équipement proche a coupé brutalement. Action : si le problème se répète sur les grosses réponses, cherche des timeouts et des limites. Déchiffrer son propre trafic via SSLKEYLOGFILE aide à voir si l'en-tête HTTP a été reçu et quelle quantité de corps est arrivée.

Pertes en réseau mobile

Tableau : de nombreux paquets marqués comme retransmission, des duplicate ack qui apparaissent, des écarts de temps notables entre paquets. La connexion est soit douloureusement lente, soit finit par se casser sur timeout.

C'est un classique du canal radio instable. Les paquets se perdent, TCP les renvoie, le débit chute. Les réseaux mobiles ont aussi tendance à couper les connexions longtemps inactives via les timeouts NAT des équipements intermédiaires de l'opérateur : au milieu du silence, un RST surgit soudain quand une des parties tente de reprendre l'échange sur une connexion que l'opérateur a déjà oubliée. Action : configurer des keep-alive et des timeouts raisonnables, des reprises au niveau applicatif, et ne pas garder de connexions longuement inactives.

Proxy totalement injoignable

Tableau : le client envoie un SYN vers l'IP et le port du proxy, mais ne reçoit pas de SYN-ACK. Soit du silence et des retransmissions de SYN, soit un RST immédiat. Si c'est le silence — quelque chose entre toi et le proxy filtre les paquets, ou le proxy n'écoute pas. Si c'est un RST immédiat — personne ne répond sur ce port. Action : vérifier l'adresse et le port du proxy, l'accessibilité réseau, la justesse de la configuration.

Client lent : zero window

Tableau : l'échange avance, mais périodiquement le client annonce zero window, l'émetteur se met en pause, puis un window update relance le flux. Si cela se répète souvent, ton application lit le socket plus lentement que le serveur n'émet. Action : optimiser le traitement de la réponse, lire le flux dans un thread dédié, augmenter les buffers.

Les erreurs classiques lors de la capture et de la lecture d'un dump

L'expérience, c'est une collection de bosses. Rassemblons les erreurs les plus fréquentes pour que tu ne les répètes pas.

  • Capturer au mauvais endroit. Tu cherches une coupure sur le segment proxy-serveur, mais tu as capturé côté client, où ce segment n'apparaît pas du tout. Réfléchis toujours au segment qu'il te faut et capture au bon point.
  • Tout capturer. Sans filtre sur un serveur chargé, tu récupéreras des gigaoctets et tu t'y noieras. Filtre par hôte et par port dès le départ.
  • Snaplen tronqué là où il faut des données. Si tu veux voir le contenu et que tu as mis un snaplen court, la charge utile sera tronquée et Follow Stream affichera des fragments.
  • Résolution de noms activée. Tu as oublié le flag -n, et tcpdump rame sur le DNS en faussant les timings. Toujours -n en capture.
  • Ignorer la direction du RST. On voit un RST et on conclut sans regarder qui l'a envoyé. L'IP source du paquet RST, c'est la moitié de la réponse.
  • Confondre un FIN normal avec une panne. FIN, c'est une fermeture normale. Il ne faut pas paniquer devant le FIN lui-même, mais devant un FIN arrivé avant la fin attendue des données.
  • Oublier les fuseaux horaires et l'heure exacte. Logs applicatifs et capture doivent être synchronisés en temps, sinon tu ne retrouveras pas le bon moment. Garde NTP en ordre.
  • Conserver le fichier de clés SSLKEYLOGFILE. Après le débogage, il doit être supprimé. C'est un secret qui révèle le contenu de tes sessions.
  • Tirer des conclusions d'une seule connexion. Les problèmes intermittents exigent des statistiques. Une requête tombée peut être un hasard, un motif de dix, un diagnostic.

Outils et ressources de l'ingénieur

Rassemblons l'arsenal à garder sous la main quand on travaille avec du trafic proxifié.

Capture

  • tcpdump — l'outil principal de capture sur serveurs et en console. Léger, toujours disponible, filtre flexible.
  • dumpcap — l'utilitaire console livré avec Wireshark, spécialement conçu pour la capture efficace avec rotation.
  • tshark — le Wireshark en console. Permet d'appliquer des filtres d'affichage sans interface graphique, pratique pour les scripts et les serveurs distants.

Analyse

  • Wireshark — analyseur graphique, décodeurs de centaines de protocoles, système de filtres puissant, Follow Stream, statistiques par connexion.
  • Informations expertes Wireshark — panneau intégré qui surligne les anomalies : retransmissions, resets, zero window. Commence ton enquête par lui.
  • Statistiques de conversations — tableau de toutes les connexions TCP de la capture avec octets et durée. On voit vite quelle connexion est anormalement courte.

Astuces utiles en ligne de commande

Voir rapidement le contenu d'un pcap en console via tshark avec un filtre d'affichage :

tshark -r dump.pcap -Y "tcp.flags.reset == 1"

N'afficher que les requêtes CONNECT d'un fichier :

tshark -r dump.pcap -Y "http.request.method == \"CONNECT\""

Voir toutes les retransmissions :

tshark -r dump.pcap -Y "tcp.analysis.retransmission"

Ces commandes sont inestimables quand il n'y a pas d'interface graphique et qu'il faut comprendre ici et maintenant, en ssh.

Cas concrets et résultats de l'application

Rien ne convainc mieux que des histoires vécues. Voici des cas composites, reflétant la pratique réelle du diagnostic de trafic proxifié.

Cas 1 : cinq pour cent des requêtes échouent la nuit

L'équipe d'intégration se plaignait : environ cinq pour cent des requêtes vers une API externe via le proxy échouaient avec une réponse tronquée, principalement la nuit. Les logs de l'appli montraient un contenu incomplet. Les logs du proxy — des tunnels établis, sans erreur.

On a capturé côté client avec rotation circulaire sur plusieurs heures et une marque d'erreur précise issue du log. Au moment de l'incident, on a vu : tunnel établi, TLS fonctionnel, une partie du corps de la réponse reçue, puis FIN du proxy. Le déchiffrage du trafic propre via SSLKEYLOGFILE a montré : un en-tête HTTP correct avec la taille du corps, mais le corps s'interrompait au milieu. Conclusion : le serveur cible fermait la connexion sur son propre timeout de génération des gros rapports nocturnes. Solution côté intégration — demander les données par pages plus petites. Le problème a complètement disparu.

Cas 2 : mystérieux RST instantané

Un autre ingénieur recevait un reset immédiat juste après l'envoi du CONNECT pour un hôte bien précis, alors que tout fonctionnait pour d'autres hôtes. Le premier soupçon tombait sur le proxy.

La capture côté client montrait : le CONNECT partait, et presque instantanément un RST revenait depuis l'IP du proxy. Mais l'instantanéité était intrigante — d'habitude une indisponibilité de serveur donne un timeout, pas un reset immédiat. On a capturé côté proxy et on a vu le segment B : le proxy ouvrait une connexion vers l'hôte cible sur le port attendu, et le serveur cible répondait RST sur le SYN — le port était fermé. Le proxy relayait honnêtement ce refus au client. Il s'avérait que le service cible avait récemment changé de port. Conclusion : un RST instantané, c'est le plus souvent un port fermé, pas un problème de proxy. Le bon port a rétabli le fonctionnement.

Cas 3 : dégradation sur le segment mobile

Une application mobile passant par le proxy perdait régulièrement la connexion chez certains utilisateurs. Une capture depuis l'appareil, dans la zone de couverture problématique, montrait le tableau classique : des séries de retransmissions, des duplicate ack, des intervalles qui s'allongeaient, et pour finir un RST après une longue inactivité — conséquence d'un timeout NAT chez l'opérateur.

Conclusion : le réseau, pas le proxy ni le serveur. Solution — au niveau applicatif, on a introduit des reprises adaptatives, des keep-alive raisonnables et une gestion gracieuse des ruptures avec rétablissement de connexion. Le nombre d'erreurs visibles par l'utilisateur a chuté de plusieurs fois, alors que le canal radio, lui, n'avait pas changé. La capture de paquets a permis de ne pas perdre de temps en fausses hypothèses sur le proxy et de se concentrer sur la vraie cause.

Insight commun aux trois cas

Dans les trois histoires, la capture a économisé des semaines d'échanges et d'accusations mutuelles entre équipes. Les paquets ne mentent pas. Dès qu'une capture avec la direction du RST, la présence ou l'absence de ServerHello et le tableau des retransmissions arrive sur la table, le débat sur le coupable se règle en quelques minutes. C'est là la vraie valeur de la méthode : elle fait passer le diagnostic du plan des opinions au plan des faits.

Checklist de capture pour contacter le support

Quand tu t'adresses au support — que ce soit celui de ton fournisseur de proxy Proxeon ou le propriétaire de l'API cible — une capture bien faite accélère la résolution dans des proportions énormes. Voici la checklist à dérouler avant de les contacter.

Avant la capture

  • Note l'heure précise du début du diagnostic et synchronise les horloges par NTP sur toutes les machines concernées.
  • Détermine les points de capture : au minimum sur le client, si possible aussi côté serveur où tu as accès.
  • Rassemble les données d'entrée : IP et port du proxy, nom et port de l'hôte cible, comportement attendu et comportement réel.

Pendant la capture

  • Lance tcpdump avec un filtre sur l'hôte proxy et le port cible, snaplen complet et rotation :
    tcpdump -i eth0 -n -s 0 "host 203.0.113.10 and port 8080" -w support-%Y%m%d-%H%M%S.pcap -C 100 -W 10
  • Reproduis le problème et note l'heure exacte de l'incident avec les millisecondes depuis le log applicatif.
  • N'oublie pas de sauvegarder en parallèle les logs applicatifs sur le même intervalle.

Ce qu'il faut joindre à la demande

  • Le fichier pcap lui-même, découpé sur l'intervalle de temps pertinent, pour ne pas envoyer des gigaoctets.
  • Les horodatages précis de l'incident et le fuseau horaire.
  • IP et port du proxy, nom et port de l'hôte cible, description du scénario.
  • Un extrait des logs applicatifs avec l'erreur.
  • Ton analyse préliminaire : qui a envoyé le RST ou le FIN, y a-t-il eu un ServerHello, a-t-on observé des retransmissions. Cela montre que tu as fait ton travail.

Comment découper un pcap sur l'intervalle voulu

Un fichier énorme peut être réduit par le temps via tshark ou editcap. Exemple de découpe par numéro de paquets ou par filtre :

tshark -r big.pcap -Y "frame.time >= \"2026-01-01 03:00:00\" && frame.time <= \"2026-01-01 03:05:00\"" -w small.pcap

Une capture propre et ciblée comme celle-ci sera traitée rapidement par le support, car il n'aura pas à chercher une aiguille dans une botte de foin.

FAQ : questions fréquentes sur les captures via proxy

Pourquoi dans une capture de trafic HTTPS via proxy je ne vois que CONNECT puis quelque chose d'illisible ?

Parce qu'après l'établissement du tunnel, le proxy ne fait que relayer les octets TLS chiffrés, sans en avoir les clés. En clair, ne circule que la commande CONNECT avec le nom d'hôte et la réponse du proxy annonçant l'établissement. Tout le reste est protégé par le chiffrement — et c'est exactement pour cela qu'HTTPS existe. Pour voir le contenu de ton propre trafic, utilise SSLKEYLOGFILE.

Comment savoir si la connexion a été coupée par le serveur cible et non par le proxy ?

Regarde l'IP source du paquet avec RST ou FIN. Mais rappelle-toi les deux segments : sur une capture côté client, tu ne vois que l'IP du proxy, parce que tu ne communiques pas directement avec le serveur. Pour attribuer avec certitude la coupure au serveur cible, il faut une capture côté proxy, où l'on voit le segment proxy-serveur. Si le RST du segment B vient de l'IP du serveur — c'est lui qui a coupé.

Quelle est la différence de sens diagnostique entre retransmission et RST ?

La retransmission, c'est le renvoi d'un segment non acquitté, signe de pertes de paquets sur le canal, mais la connexion est encore vivante et se bat. RST, c'est une terminaison, un ordre d'oublier la connexion. Une avalanche de retransmissions qui se transforme en RST se lit comme : le canal perdait des paquets, la partie a cessé d'attendre et a coupé. Quelques retransmissions isolées, c'est normal sur Internet.

Que signifie zero window et le proxy en est-il responsable ?

Zero window est annoncé par le récepteur dont le buffer de réception est plein, parce que l'application lit trop lentement

À propos de l'auteur

Andrey Kokh

Andrey Kokh

Leading Expert and Business Consultant

Expérience professionnelle : Leading expert with 12 years of experience. Consults Forbes-listed companies, author of 3 books. Teaches at HSE and SKOLKOVO. His methodologies are used by hundreds of companies across Russia. RBC and Forbes expert on strategic development and digital transformation.
Formation : Higher School of Economics. Faculty of Economics, Master's Program
Expertise :
Strategic Consulting Digital Transformation Change Management Business Strategy Innovation Management Organizational Development Lean Management Agile Transformation

Partagez cet article :