Pourquoi un serveur n'enverrait-il pas un paquet SYN / ACK en réponse à un paquet SYN?

46

Dernièrement, nous avons pris conscience d’un problème de connexion TCP qui se limitait principalement aux utilisateurs de Mac et Linux qui naviguaient sur nos sites Web.

Du point de vue de l'utilisateur, il se présente comme un temps de connexion très long avec nos sites Web (> 11 secondes).

Nous avons réussi à retrouver la signature technique de ce problème, mais nous ne savons pas pourquoi cela se produit ni comment le résoudre.

En gros, ce qui se passe, c'est que la machine du client envoie le paquet SYN pour établir la connexion TCP et que le serveur Web le reçoit, mais ne répond pas avec le paquet SYN / ACK. Une fois que le client a envoyé de nombreux paquets SYN, le serveur répond finalement avec un paquet SYN / ACK et tout va bien pour le reste de la connexion.

Et, bien sûr, la solution au problème: il est intermittent et ne se produit pas tout le temps (bien que cela se produise entre 10 et 30% du temps)

Nous utilisons Fedora 12 Linux comme système d’exploitation et Nginx comme serveur Web.

Capture d'écran de Wireshark

Capture d'écran de Wireshark

Mise à jour:

La désactivation de la mise à l'échelle de la fenêtre sur le client a permis d'éviter le problème. Maintenant, j'ai juste besoin d'une résolution côté serveur (nous ne pouvons pas obliger tous les clients à le faire) :)

Mise à jour finale:

La solution consistait à désactiver la mise à l'échelle TCP et la mise à l'échelle des fenêtres et les horodatages TCP sur nos serveurs accessibles au public.

codemonkey
la source
1
Je pense que nous aurons besoin de voir quelque chose se passer.
Coredump
Avez-vous des règles ou des règles basées sur le DNS inversé? Vous devrez peut-être examiner davantage que la seule connexion entre le client et le serveur. Peut-être qu'une recherche DNS arrive à expiration?
Zoredache
@coredump: voici une capture d'écran de l'analyse wirehark qui montre le problème i.imgur.com/Bnzrm.png (je ne savais pas comment exporter uniquement le flux ...)
codemonkey
@Zoredache: non, nous n'avons pas de règles ou de règles basées sur le DNS inversé. Ceci est un serveur web public et nous permettons à tout le monde d'y accéder
codemonkey
Juste une intuition, mais faites-vous une sorte de limitation du débit de connexion entrante sur le serveur? Dis, avec iptables?
Steven lundi

Réponses:

15

Nous avons eu exactement le même problème. Le simple fait de désactiver les horodatages TCP a résolu le problème.

sysctl -w net.ipv4.tcp_timestamps=0

Pour rendre ce changement permanent, entrez une entrée dans /etc/sysctl.conf.

Faites très attention à la désactivation de l'option TCP Window Scale. Cette option est importante pour offrir une performance maximale sur Internet. Quelqu'un avec une connexion de 10 mégabits / s effectuera un transfert sous-optimal si le temps aller-retour (essentiellement identique à celui du ping) est supérieur à 55 ms.

Nous avons vraiment remarqué ce problème lorsqu'il y avait plusieurs périphériques derrière le même NAT. Je soupçonne que le serveur a peut-être été dérouté de voir les horodatages des appareils Android et des ordinateurs OSX en même temps, car ils inséraient des valeurs complètement différentes dans les champs d'horodatage.

mcdizzle
la source
4
Dans le cas où quelqu'un d'autre se retrouverait ici par le même trou de lapin que je viens de perdre: Avant de désactiver les horodatages TCP ou la mise à l'échelle des fenêtres, ce qui peut avoir de graves conséquences sur les performances d'un lien à fort trafic, vérifiez si tcp_tw_recycle est votre problème: stackoverflow .com / questions / 8893888 /…
nephtes
12

Dans mon cas, la commande suivante a résolu le problème de réponses SYN / ACK manquantes du serveur Linux:

sysctl -w net.ipv4.tcp_tw_recycle=0

Je pense que c'est plus correct que de désactiver les horodatages TCP, car ceux-ci sont utiles pour des performances élevées (PAWS, dimensionnement de fenêtre, etc.).

La documentation sur tcp_tw_recycleindique explicitement qu'il n'est pas recommandé de l'activer, car de nombreux routeurs NAT conservent les horodatages et donc, le démarrage de PAWS, car les horodatages de la même adresse IP ne sont pas cohérents.

   tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
          Enable fast recycling of TIME_WAIT sockets.  Enabling this
          option is not recommended for devices communicating with the
          general Internet or using NAT (Network Address Translation).
          Since some NAT gateways pass through IP timestamp values, one
          IP can appear to have non-increasing timestamps.  See RFC 1323
          (PAWS), RFC 6191.
lav
la source
1
bonne explication ici: vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux Du côté serveur, n'activez pas net.ipv4.tcp_tw_recycle sauf si vous êtes sûr de ne pas avoir de périphérique NAT dans le mélange.
Gnought
1
Dans mon cas, net.ipv4.tcp_tw_recyclec'est la vraie raison. Merci.
bluearrow
tcp_tw_recycle a été supprimé des noyaux récents. Y a-t-il une autre solution semblable? @nephtes implique que la désactivation de l'horodatage nuit aux performances.
MappaM
Puisque tcp_tw_recycle a été supprimé, le problème ne devrait plus se produire car il ne s'est produit qu'avec une valeur autre que la valeur par défaut de tcp_tw_recycle.
Lav
5

Je me demandais simplement, mais pourquoi pour le paquet SYN (trame # 539; celle qui a été acceptée), les champs WS et TSV sont manquants dans la colonne "Info"?

WS correspond à TCP Window Scaling et TSV correspond à Timestamp Value . Les deux d'entre eux se trouvent dans le champ tcp.options et Wireshark devrait toujours leur montrer s'ils sont présents. Peut-être que la pile TCP / IP du client a envoyé un paquet SYN différent lors de la 8ème tentative et que cela a été la raison pour laquelle il a été soudainement reconnu?

Pourriez-vous nous fournir les valeurs internes du cadre 539? Est-ce que SYN / ACK vient toujours pour un paquet SYN sur lequel WS n'est pas activé?

Hans Solo
la source
@Ansis: voici quelques captures d'écran pour les détails de la monture 539 (le faire en deux parties): i.imgur.com/D84GC.png & i.imgur.com/4riq3.png
codemonkey
@codemonkey: Votre 8ème paquet SYN semble être différent des sept premiers paquets SYN. Le serveur répond-il avec SYN / ACK au SYN du client que lorsque le champ tcp.options est d'une taille de 8 octets (les sept premiers paquets SYN ont probablement tcp.options d'une taille de 20 octets)? Pouvez-vous désactiver la mise à l'échelle de la fenêtre TCP côté client pour voir si le problème disparaît? Cela ressemble à un problème de pile TCP / IP côté serveur ou de pare-feu mal configuré quelque part ...
Hans Solo
@Ansis: Oui, je suis en train de regarder cela depuis que vous l'avez signalé et tous les autres paquets SYN ont 24 octets. Je vais essayer de désactiver la mise à l'échelle de la fenêtre sur le client et de vérifier les résultats le lendemain matin.
codemonkey
@Ansis: désactiver le redimensionnement de Windows sur le client a permis d'éviter que le problème ne se produise. Merci! Cependant, je dois maintenant trouver un moyen de résoudre ce problème côté serveur (étant donné que tous nos clients ne peuvent pas désactiver la mise à l'échelle de Windows) :) Le serveur en question a effectivement net.ipv4.tcp_windows_scaling = 1
codemonkey
@ Codemonkey: Je conviens que la désactivation de WS sur tous les clients n'est pas une solution, mais nous avons au moins suivi le problème en fonction des problèmes liés à WS / Packet Size. Pour rechercher plus en détail la cause, nous devrions examiner la configuration de votre pare-feu. Pouvez-vous établir des connexions TCP avec WS sur différents ports TCP? De différentes sources IP?
Hans Solo
4

Nous venons tout juste de rencontrer exactement le même problème (il a vraiment fallu un certain temps pour l’épingler au serveur sans envoyer de syn-ack).

"La solution consistait à désactiver la mise à l'échelle des fenêtres TCP et les horodatages TCP sur nos serveurs accessibles au public."

Alex Li
la source
2

Pour continuer sur ce que Ansis a déclaré, j'ai vu des problèmes comme celui-ci lorsque le pare-feu ne prend pas en charge TCP Windows Scaling. Quel est le pare-feu de marque / modèle entre ces deux hôtes?

joeqwerty
la source
Le pare-feu est une boîte Fedora 13 utilisant iptables. net.ipv4.tcp_windows_scaling est défini sur 1 sur cette machine également
codemonkey
2

Le SYN / ACK manquant peut être dû à des limites trop basses de votre protection SYNFLOOD sur le pare-feu. Cela dépend du nombre de connexions créées par votre utilisateur sur le serveur. L'utilisation de spdy réduirait le nombre de connexions et pourrait aider dans les cas où net.ipv4.tcp_timestampséteindre n'aide pas.

brablc
la source
1

C'est le comportement d'un socket TCP à l'écoute lorsque son backlog est plein.

Ngnix permet de définir l'argument du backlog à écouter dans la configuration: http://wiki.nginx.org/HttpCoreModule#listen

écouter 80 backlog = num

Essayez de définir num sur un paramètre supérieur à la valeur par défaut, par exemple 1024.

Je ne garantis pas qu’une file d’écoute complète est votre problème, mais c’est une bonne première chose à vérifier.

Akramer
la source
Merci pour le conseil. Je vais l'essayer. Nous avons défini le backlog au niveau du système d'exploitation, mais pas explicitement dans Nginx config. Je mettrai à jour avec le résultat.
Codemonkey
cela n'a pas changé le comportement du tout. Devinez, ce n'est pas le problème? ou le seul problème ...
codemonkey
1
paramètre de backlog au niveau de l'application contrôle la taille de la file d'attente pour les connexions TCP terminées, c'est-à-dire que l'établissement de la liaison à 3 voies est terminé, c'est-à-dire que le syn-ack est reçu - il ne correspond donc pas à la situation de l'OP
ygrek
1

Je viens de découvrir que les clients Linux TCP changent leur paquet SYN après 3 tentatives et suppriment l'option Window Scaling. Je suppose que les développeurs du noyau ont compris qu'il s'agissait d'une cause fréquente d'échec de connexion sur Internet.

Cela explique pourquoi ces clients parviennent à se connecter après 11 secondes (le SYN SYN sans fenêtre se produit après 9 secondes dans mon bref test avec les paramètres par défaut)

Jeroen van Bemmel
la source
0

J'ai eu un problème similaire, mais dans mon cas, c'est la somme de contrôle TCP qui a été mal calculée. Le client était derrière un veth et exécuter ethtool -K veth0 rx off tx off a fait l'affaire.

Baroudi Safwen
la source