Le tunnel tombe, le kill switch s'active, et un téléchargement achevé aux trois quarts se fige ou échoue immédiatement. Ces deux issues viennent de choix d'application différents, pas de niveaux de protection différents. Un paquet abandonné laisse la connexion en attente, tandis qu'un paquet refusé la ferme et prévient l'application. Choisir le comportement que vous voulez est une question de conception, et le tester est un exercice séparé.

Abandonné, refusé et réinitialisé sont différents

Une règle de pare-feu qui abandonne le trafic jette le paquet sans rien renvoyer, si bien que l'émetteur continue de retransmettre selon ses propres minuteries. Une règle qui refuse avec un reset TCP ferme la connexion immédiatement et l'application voit une erreur. La plupart des kill switches abandonnent, parce qu'un refus révélerait la politique et parce qu'abandonner ressemble au comportement d'un réseau mort.

Bloquer n'est pas non plus la même chose que fermer le socket. L'application tient toujours un descripteur à l'état établi, et seuls les paquets manquent. C'est pourquoi une page peut rester sur un indicateur de chargement pendant des minutes alors que le système d'exploitation affirme que la connexion existe. Lisez la mise en œuvre documentée plutôt que de la déduire du message de l'application, car les deux comportements ressemblent à un réseau hors service.

Ce que l'application fait pendant la coupure

TCP retransmet avec des délais croissants, et le budget de nouvelles tentatives par défaut de Linux expire vers un quart d'heure, pas en quelques secondes. Jusque-là, le socket n'est ni vraiment ouvert ni fermé. Les applications dotées de leurs propres keepalives ou délais de requête abandonnent souvent plus tôt, ce qui explique pourquoi deux programmes sur la même machine se comportent différemment pendant une panne.

Quand le tunnel revient, le socket local est inchangé mais le chemin ne l'est peut-être pas. Une nouvelle adresse source publique produit un quadruplet différent au serveur, si bien qu'un pare-feu à état de l'autre côté ne correspond plus à la session. La connexion est morte alors que le client n'a jamais vu d'erreur.

Décidez si la récupération est requise

Choisissez entre deux contrats. Soit la session doit survivre à une courte coupure, ce qui exige un adressage stable et un serveur qui conserve son état, soit l'application doit se reconnecter proprement, ce qui exige une logique de nouvelle tentative sûre à répéter. Tout ce qui est entre les deux produit le pire résultat : un client qui renvoie ce que le serveur a déjà validé, ou un qui annonce un succès pour une session que personne ne voit.

L'adressage stable est la partie que les gens oublient, car une reconnexion qui atterrit sur une autre adresse publique invalide l'état côté serveur même quand le socket du client semble sain. Notez lequel des deux contrats s'applique à chaque application, car ils correspondent rarement tous.

Testez le blocage et la récupération séparément

Traitez la protection contre les fuites et la survie de la session comme deux propriétés, car réussir l'une ne dit rien de l'autre. Une session qui survit ne prouve pas que le trafic direct a été bloqué, et une session qui meurt ne prouve pas que toutes les routes directes l'ont été.

ss -tnp state established '( dport = :443 )'
sudo conntrack -L -p tcp --dport 443
sudo tcpdump -ni any 'tcp port 443 and tcp[tcpflags] & tcp-syn != 0'

Utilisez une opération de test inoffensive pour observer la récupération, afin qu'un envoi en double ne devienne pas l'incident. Notez le mode de défaillance réellement observé : ce que l'application a affiché, si le socket a survécu et quand il s'est rétabli tout seul.

Écrivez le comportement attendu à côté de la règle d'application et datez-le. La prochaine personne qui modifiera cette règle doit savoir lequel des deux contrats le déploiement a promis.

Articles similaires