Contexte, pendant longtemps, nous avons eu des problèmes avec notre pare-feu qui maintiennent parfois les requêtes HTTP suspendues partiellement chargées jusqu'à ce que TCP expire.
Après avoir tracé le trafic sur le pare-feu, j'ai remarqué qu'il ne se produit que dans certaines conditions de synchronisation, par exemple lorsque le serveur Web a envoyé la réponse entière avant que le client ait envoyé son deuxième ACK sur la charge utile. [SYN, SYN / ACK, ACK] a été échangé, REQUEST a été envoyé et ACK'ed et le premier paquet RESPONSE a été reçu et ACK'ed, puis le serveur Web envoie le reste du corps de la réponse en une seule fois (8 paquets y compris le dernier FIN, PSH) et avant que le client ait ACKé l'un de ceux-ci, le pare-feu REJETTE avec un RST vers le serveur Web et maintient le client suspendu infini.
Voici l'intégralité de la trace wireShark avec des paquets des deux côtés du pare-feu. 192.168.126.161 est l'adresse IP NAT'et privée du client. 172.16.1.2 est l'IP du serveur Web (ne montrant pas l'IP publique réelle) et 10.1.1.1 est l'IP externe du pare-feu (ne montrant pas l'IP publique réelle)
2105 0.086275 192.168.126.161 172.16.1.2 TCP 37854 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=89375083 TSER=0
2106 0.000066 10.1.1.1 172.16.1.2 TCP 37854 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=89375083 TSER=0
2107 0.002643 172.16.1.2 10.1.1.1 TCP http > 37854 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=1460
2108 0.007705 172.16.1.2 192.168.126.161 TCP http > 37854 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=1460
2109 0.006301 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
2110 0.000025 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
2111 0.000007 192.168.126.161 172.16.1.2 HTTP GET /test/style.css HTTP/1.1
2112 0.000015 10.1.1.1 172.16.1.2 HTTP GET /test/style.css HTTP/1.1
2113 0.001536 172.16.1.2 10.1.1.1 TCP http > 37854 [ACK] Seq=1 Ack=111 Win=32658 Len=0
2114 0.000014 172.16.1.2 192.168.126.161 TCP http > 37854 [ACK] Seq=1 Ack=111 Win=32658 Len=0
2115 0.002274 172.16.1.2 10.1.1.1 HTTP HTTP/1.1 200 OK (text/css)
2116 0.000025 172.16.1.2 192.168.126.161 HTTP HTTP/1.1 200 OK (text/css)
2117 0.005689 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=1461 Win=8760 Len=0
2118 0.000024 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=1461 Win=8760 Len=0
2119 0.001536 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2120 0.000026 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2121 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2122 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2123 0.000313 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2124 0.000030 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2125 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2126 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2127 0.000009 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2128 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2129 0.001108 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2130 0.000035 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2131 0.000008 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2132 0.000022 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2133 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
REJECT-->
2134 0.000089 10.1.1.1 172.16.1.2 TCP 37854 > http [RST] Seq=111 Win=0 Len=0
CLIENT FIRST ACK-->
2135 0.002421 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=2921 Win=11680 Len=0
2136 0.000033 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=2921 Win=11680 Len=0
2137 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=4381 Win=14600 Len=0
2138 0.000014 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=4381 Win=14600 Len=0
2139 0.000008 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=5841 Win=17520 Len=0
2140 0.000014 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=5841 Win=17520 Len=0
2141 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=7301 Win=20440 Len=0
2142 0.000013 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=7301 Win=20440 Len=0
2143 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=8761 Win=23360 Len=0
2144 0.000015 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=8761 Win=23360 Len=0
2145 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=10221 Win=26280 Len=0
2146 0.000013 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=10221 Win=26280 Len=0
2147 0.001059 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=11681 Win=29200 Len=0
2148 0.000018 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=11681 Win=29200 Len=0
J'ai creusé et consigné la traversée de paquets selon ce tableau et il semble que le dernier paquet entrant 2133 ait dépassé raw-PREROUTING, conntrack, mangle-PREROUTING mais est ensuite perdu. Je n'ai pas de règles REJECT dans mes iptables, j'enregistre toutes les règles DROP et aucune d'entre elles ne montre où le paquet 2133 est perdu.
J'aimerais utiliser la cible TRACE sur le filtre entrant, mais malheureusement ubuntu 8.04 n'est pas livré avec le support de la cible TRACE.
Je crois donc que certaines règles de routage / conntrack / mangling implicites internes s'appliquent qui, pour une raison quelconque, réinitialise la connexion. Peut-être que le trafic déclenche une protection DOS, mais je ne sais pas où configurer / analyser cela. Le plus frustrant est qu'un paquet est rejeté et que rien n'est enregistré ...
La demande de ce fichier fonctionne également à 100% à partir des hôtes Windows, mais elle échoue sur certains hôtes Linux et 99,9% de toutes les demandes passent mais parfois le timing des paquets déclenche ce comportement dans notre pare-feu.
EDIT Ok, maintenant j'ai ajouté des tonnes de connexion à iptables et il semble que ce qui suit se produit (je ne sais toujours pas pourquoi!)
Pour les paquets traversant avec succès le pare-feu, les étapes suivantes sont suivies, les références de table / étape d' ici
Table 3-3 step
2 raw-pre
conntrack
3 mangle-pre
4 [nat-pre]
5 routing-decision -> destination forward
6 mangle-fwd
7 filter-fwd
8 mangle-post
9 [nat-post]
Le paquet 2133 qui est rejeté passe par ces étapes:
Table 3-1 steps for the incoming FIN,ACK packet 2133
2 raw-pre
conntrack
3 mangle-pre
4 [nat-pre]
5 routing-decision -> destination local
6 mangle-input
7 filter-input
8 local process emits RST -> webserver
Table 3-2 steps for the outgoing RST packet 2134 in response to 2133
1 raw-out
2 routing decision
conntrack
3 mangle-out
reroute-check
4 [nat-out]
5 filter-out
6 mangle-post
7 nat-post
Ce qui est étrange, c'est que la décision de routage pour le paquet 2133 à l'étape 5 est maintenant différente de la décision de routage pour les autres paquets. Lors de l'analyse de requêtes qui fonctionnent, par exemple ne se bloquent pas, même le dernier FIN est correctement routé. Il semble que ce soit un bogue dans le noyau ou que la décision de routage soit en quelque sorte avec état.
MODIFIER
Une chose qui pourrait provoquer ces problèmes est le fait suivant, le trafic est acheminé entre le pare-feu et le LAN local, de sorte que le LAN client n'est pas directement connecté au pare-feu via L2.
+---------------------------+ +------------------+ +------------------------+
| | | Router | ( Lab network ) | |
( Internet ) -- + eth1 eth0 +-------+ +-- ( ) -+ Client 192.168.126.161 |
| 10.1.1.1 192.168.60.254 | | | ( 192.168.126.0/24 ) | |
+---------------------------+ +------------------+ +------------------------+
Dans cette image, 10.1.1.1 représente l'adresse IP externe du pare-feu, toutes les autres adresses sont les vraies adresses IP utilisées.
Voici la table de routage sur le pare-feu:
Destination Gateway Genmask Flags Metric Ref Use Iface
10.1.1.0 0.0.0.0 255.255.255.240 U 0 0 0 eth1
192.168.126.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.60.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 10.1.1.15 0.0.0.0 UG 0 0 0 eth1
Notez que 10.1.1.0 et gw 10.1.1.15 par défaut sont constitués, le reste est exactement le même que celui utilisé. J'ai dû ajouter manuellement la route 192.168.126.0/24 pour atteindre le réseau de laboratoire à partir de eth0 (192.168.60.254).
Voici quelques journaux détaillés sur la traversée de paquets pour le dernier paquet 2133 qui est rejeté en raison de son routage vers l'hôte local (par exemple le pare-feu).
[16406874.374588] raw pre IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374625] mangle pre IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374667] mangle in IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374699] filter in IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374780] mangle out IN= OUT=eth1 SRC=10.1.1.1 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=0 RES=0x00 RST URGP=0
[16406874.374807] mangle post IN= OUT=eth1 SRC=10.1.1.1 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=0 RES=0x00 RST URGP=0
[16406874.378813] mangle pre IN=eth0 OUT= MAC=00:02:b3:b9:ff:b4:00:90:1a:10:0c:dd:08:00 SRC=192.168.126.161 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=63 ID=35424 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=11680 RES=0x00 ACK URGP=0
[16406874.378863] mangle fwd IN=eth0 OUT=eth1 SRC=192.168.126.161 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=62 ID=35424 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=11680 RES=0x00 ACK URGP=0
Encore une fois, notre IP externe fw a été remplacée par 10.1.1.1 et l'IP du serveur Web en dehors du réseau NAT est remplacée par 172.16.1.2
EDIT Breaking News!
Ok, le dernier essai a été de SUPPRIMER le paquet RST, très très intéressant, j'ai ajouté une règle iptables qui a supprimé tous les paquets RST destinés au serveur Web sur lequel nous avons des problèmes pour demander des fichiers. Et ensuite, cela a fonctionné, par exemple, le dernier paquet FIN, ACK, PSH 2133 dans le journal ci-dessus est supprimé, mais comme le RST est supprimé, le serveur Web a le temps d'obtenir toutes les fourmis de l'ACK, puis décide de retransmettre le dernier paquet, le paquet 2133 à nouveau, et maintenant, il passe par le pare-feu puisque le module de contrack a maintenant vu les ACK revenir du client et autorise le dernier paquet ACK, FIN avec la charge utile finale.
C'est donc définitivement un problème de timing / fenêtre, ce fichier particulier, avec le timing des ACK du client, déclenche quelque chose dans conntrack qui rejette le paquet final du serveur web.
Jusqu'à présent, la recherche sur Google et la lecture des documents du noyau ne révèlent rien qui puisse provoquer ce comportement, la prochaine étape sera de lire le code source du noyau pour le module de routage / conntrack.
PROBLÈME RÉSOLU
Eh bien, au moins maintenant, nous savons exactement ce qui se passe et nous avons une solution de contournement qui résout le problème.
Sergey a souligné la très précieuse règle de correspondance état -m - état INVALID qui a beaucoup aidé dans le débogage.Je me rends maintenant compte qu'une configuration iptables sans règle explicite pour les paquets INVALID n'est pas complète, donc un comportement étrange semble parfois se produire.
Lorsque vous activez la connexion dans le module conntrack pour ce qui cause le paquet invalide, ce qui se passe est assez évident et j'ai eu mes soupçons à ce sujet.
[16659529.322465] nf_ct_tcp: SEQ is over the upper bound (over the window of the receiver) IN= OUT= SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=40874 DF PROTO=TCP SPT=80 DPT=55498 SEQ=658735108 ACK=1194081763 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
Encore une fois, 172.16.1.2 est le serveur Web externe (qui se comporte incorrectement) et 10.1.1.1 est l'adresse externe du pare-feu.
Le serveur Web envoie plus de données sur le câble que le client n'en a annoncé dans la fenêtre de réception (conntrack est plein d'état et le vérifie), il semble que ce soit lorsque le paquet FIN arrive que conntrack échoue car la fenêtre de réception est dépassée plus tôt.
Je pense que cela pourrait être dû à un déchargement TCP incorrect dans la carte réseau du serveur Web. Lorsque j'ai commencé à analyser cela, j'ai pris des captures sur le serveur Web et selon les traces tcpdump / wireShark, des trames jumbo ont été écrites par la couche TCP dans le noyau qui a ensuite été segmentée en plus petites trames avec MTU = 1500 par la carte réseau. Donc, évidemment, cela doit être résolu dans le serveur Web car ce n'est pas le comportement TCP correct d'envoyer plus de données que le récepteur n'a de publicités dans sa fenêtre de réception.
Polynôme et Sergey ont tous deux fourni des informations précieuses, mais Sergey m'a signalé le comportement exact du module conntrack / NAT en ce qui concerne la traversée de paquets.