Comment un pare-feu tuerait-il une connexion TCP sans RST ou FIN? [fermé]

8

La situation est comme ceci:

http client ----> corporate firewall ----> http server

En raison d'une keepalive, le serveur et le client garderaient les connexions TCP ouvertes et le client utiliserait un pool de connexions pour les requêtes HTTP.

Le pare-feu a une règle pour "tuer" les connexions TCP de longue date après 1 heure. Le problème est que notre client HTTP ne détecterait pas que la connexion TCP a été détruite et il a essayé de réutiliser des connexions essentiellement mortes qui de notre côté ressemblaient au client "pendu" après un certain temps. Une demande se bloquerait, puis la suivante fonctionnerait, probablement parce qu'une nouvelle connexion a été établie.

La question ici est quel est le mécanisme avec lequel le pare-feu tue les connexions TCP d'une manière que notre client HTTP n'a pas pu les détecter. J'ai essayé de reproduire ce comportement localement de plusieurs manières:

  1. Tuez les connexions TCP sur notre routeur vyos, Wireshark du côté client a capturé TCP FIN-ACK. D'accord
  2. Tuez la connexion TCP côté client dans TCPView sous Windows, Wireshark a détecté TCP RST côté client. D'accord
  3. Bloquer le port après une connexion établie au pare-feu côté client, a entraîné une exception de réinitialisation de socket. D'accord

J'ai un vidage Wireshark côté serveur et j'ai essayé de trouver si le pare-feu envoie un FIN ou RST avec ip.dst==serverip && (tcp.flags.reset==1 || tcp.flags.fin==1)mais rien ne s'est affiché.

De plus, la capture Wireshark côté client montre le problème lors de la sortie de la requête HTTP, suivie par une douzaine de retransmissions TCP, ne conduisant finalement nulle part.

Le client HTTP est un client HTTP natif Java et / ou Jetty (essayé les deux), les deux n'ont pas réussi à détecter une connexion TCP morte. Je voudrais reproduire le comportement localement, mais je ne peux pas comprendre de quelle manière douteuse le pare-feu tue les connexions, donc je cherche des réponses possibles.

cen
la source
8
Déposez simplement le paquet dans le pare-feu, c'est-à-dire ne le transférez pas à la destination et ne définissez aucun FIN, RST, etc.
Steffen Ullrich
Vous devez modifier votre question pour inclure le modèle et la configuration du pare-feu (masquer les mots de passe et les adresses publiques).
Ron Maupin
"Le pare-feu a une règle pour" tuer "les connexions TCP de longue date après 1 heure." Cela ressemble à une règle de pare-feu vraiment bizarre.
reirab
@RonMaupin Je le ferais déjà si je le savais ou si j'avais accès
cen
Malheureusement, les questions sur les réseaux sur lesquels vous n'avez aucun contrôle direct sont explicitement hors sujet ici.
Ron Maupin

Réponses:

11

Vous ne mentionnez pas le type de pare-feu, mais je soupçonne le plus simplement de laisser tomber les paquets.

J'ai un vidage Wireshark côté serveur et j'ai essayé de savoir si le pare-feu envoie un FIN ou RST avec ip.dst == serverip && (tcp.flags.reset == 1 || tcp.flags.fin == 1) mais rien est apparu.

Ce qui tendrait à le confirmer.

Ron Trunk
la source
Malheureusement, je ne connais aucune information sur le pare-feu car il s'agit d'un réseau interne. Une suggestion sur la façon de reproduire cela localement (de préférence côté client)?
cen
1
Si votre objectif est de créer un banc d'essai, vous pouvez exécuter un pare-feu logiciel sur un PC ou acheter un pare-feu matériel peu coûteux. Bloquer la connexion semble être une chose simple à faire.
Ron Trunk
5

Très probablement, le pare-feu vient de supprimer le paquet sans envoyer de paquet RST, probablement après avoir atteint une valeur d'expiration de session quelconque. Il s'agit généralement d'un comportement configurable.

Personnellement, je préfère que ce paquet RST soit envoyé précisément parce qu'il aide les clients à se comporter normalement, mais j'ai entendu des arguments selon lesquels cela ne devrait pas être fait sur des pare-feu orientés vers l'extérieur pour éviter de fournir tout type de rétroaction à des attaquants potentiels.

J'ai vu cette cause causer plusieurs problèmes car les clients ne gèrent généralement pas ce type de scénario de manière très élégante. Essentiellement, ils continuent à réessayer via la session TCP d'origine (qui est maintenant morte) et n'essaient jamais d'en rétablir une nouvelle. Finalement, un délai d'attente côté client se déclenche et l'utilisateur reçoit un message d'erreur désagréable. La configuration appropriée de Keepalive HTTP pour l'application peut aider à résoudre ce problème.

Jeremy Gibbons
la source
L'envoi d'un FIN ou d'un RST nécessiterait que l'implémentation du pare-feu garde une trace des numéros de séquence sur la connexion (car elle doit remplir ces données dans le paquet FIN / RST). En revanche, une politique "il suffit de le supprimer" signifierait que l'implémentation du pare-feu a juste besoin de stocker les 4 tuple et de le tuer lorsque le temps de 1 heure est écoulé.
mere3ortal
Je peux comprendre le raisonnement pour un réseau externe, mais pour un réseau interne, cela semble carrément mauvais.
cen
C'est mal de faire ça avec état. Ne supprimez complètement que si rien ne doit écouter sur ce port pour cette plage IP.
Joshua
@Joshua, je suis entièrement d'accord pour dire que c'est mal, précisément parce que j'ai dû réparer le gâchis que cela a causé. Pourtant, cela arrive avec des équipes SecOps suffisamment paranoïaques ...
Jeremy Gibbons
4

@Ron Trunk est exactement correct, presque certainement la connexion ouverte est abandonnée soit activement (règle de refus insérée) ou passivement (supprimée des connexions connues et non autorisée à être recréée sans syn). Un des commentaires a suggéré de l'essayer vous-même. Voici une recette pour le faire en utilisant des espaces de noms de réseau Linux. Il suppose que le transfert IP est activé dans le noyau de votre hôte, que vous êtes root et probablement d'autres choses.

# Create network namespacs
ip netns add one; ip netns add two; ip netns add three
# Create interfaces between namespaces
ip link add dev i12 type veth peer name i21
ip link add dev i32 type veth peer name i23
# Bring interfaces up and assign them to respective namespaces
ip link set dev i12 netns one up
ip link set dev i21 netns two up
ip link set dev i32 netns three up
ip link set dev i23 netns two up
# Assign IP addresses
ip netns exec one ip addr add 1.1.1.1/24 dev i12
ip netns exec two ip addr add 1.1.1.2/24 dev i21
ip netns exec three ip addr add 3.3.3.3/24 dev i32
ip netns exec two ip addr add 3.3.3.2/24 dev i23
# Add routes when necessary
ip netns exec one ip route add default via 1.1.1.2
ip netns exec three ip route add default via 3.3.3.2

Vous avez alors besoin de trois fenêtres / coques / écrans / terminaux. Exécutez chaque commande ci-dessous dans un terminal distinct:

  • Commencez à écouter sur le serveur: ip netns exec three socat TCP-LISTEN:5001 STDIO
  • Commencez à transmettre sur le client: ip netns exec one socat STDIO TCP:3.3.3.3:5001

Notez qu'après avoir exécuté ces commandes, tout ce que vous tapez dans une fenêtre sera reflété dans l'autre, et vice-versa (après avoir appuyé sur retour). Si ce n'est pas vrai, vous devrez peut-être activer le transfert IP.

  • Instanciez la règle de refus: ip netns exec two iptables -I FORWARD -j DROP

Ensuite, rien de ce que vous tapez ne sera autorisé.

Vous pouvez simuler une méthode de suppression moins active avec des règles de transfert (non testées) comme:

ip netns exec two iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
ip netns exec two iptables -A FORWARD -m tcp -p tcp -dport 5001 --tcp-flags ALL SYN -j ACCEPT
ip netns exec two iptables -A FORWARD -j DROP

Voir /unix/127081/conntrack-tcp-timeout-for-state-stablished-not-working et https://www.kernel.org/doc/Documentation/networking/nf_conntrack-sysctl .txt pour des informations sur la façon d'ajuster les délais d'attente - bien qu'il ne soit pas clair pour moi que iptables supporte nativement une durée de vie de connexion maximale; Je crois que tous les délais d'attente sont des délais d'attente inactifs.

Nettoyez avec ip netns del one; ip netns del two; ip netns del three

Seth Robertson
la source
Les configurations hôte / serveur / VM sont hors sujet ici.
Ron Maupin
@Ron Maupin: Mais la création d'un banc d'essai réseau pour tester une théorie de l'ingénierie réseau est-elle hors sujet?
Seth Robertson
Il y a certaines choses, comme la configuration des périphériques réseau (routeur, commutateurs, etc.), ou l'utilisation de quelque chose comme Pacet Tracer ou GNS3 pour simuler quelque chose, sont sur le sujet. La configuration des hôtes / serveurs / VMS est hors sujet ici. Leur fonctionnement et leurs systèmes d'exploitation ne font pas partie du réseau. L'OP doit inclure le modèle et la configuration du pare-feu afin que nous puissions voir si nous pouvons vous aider.
Ron Maupin
1

Le pare-feu peut envoyer un paquet ICMP indiquant que la cible était inaccessible. Pour tout sauf TCP, c'est la seule indication d'erreur possible, par exemple l'envoi d'un paquet à un port UDP fermé générera un message "destination inaccessible" avec le code anomalie réglé sur "port inaccessible".

Il est également possible d'envoyer des messages "port inaccessible" en réponse aux paquets TCP, cela met également fin à la connexion, mais quiconque analyse les vidages de paquets remarquera que cela est inhabituel, car la convention TCP est d'indiquer les ports fermés avec un RST.

L'expéditeur doit mapper tous les paquets d'erreur ICMP reçus vers la connexion d'origine et les traiter de manière appropriée, de sorte qu'un paquet d'erreur généré par le pare-feu peut également être utilisé pour mettre fin à une connexion TCP. Le paquet ICMP contient une copie des en-têtes du paquet incriminé pour permettre ce mappage.

Simon Richter
la source