Warum würde ein Server als Antwort auf ein SYN-Paket kein SYN / ACK-Paket senden?

46

In letzter Zeit sind wir auf ein TCP-Verbindungsproblem aufmerksam geworden, das sich hauptsächlich auf Mac- und Linux-Benutzer beschränkt, die auf unseren Websites surfen.

Aus Benutzersicht ergibt sich eine sehr lange Verbindungszeit zu unseren Websites (> 11 Sekunden).

Wir haben es geschafft, die technische Signatur dieses Problems zu finden, können aber nicht herausfinden, warum es passiert oder wie es behoben werden kann.

Grundsätzlich passiert, dass der Client das SYN-Paket sendet, um die TCP-Verbindung herzustellen, und der Webserver es empfängt, aber nicht mit dem SYN / ACK-Paket antwortet. Nachdem der Client viele SYN-Pakete gesendet hat, antwortet der Server schließlich mit einem SYN / ACK-Paket und für den Rest der Verbindung ist alles in Ordnung.

Und natürlich der Kicker des Problems: Es tritt nur sporadisch auf und kommt nicht immer vor (obwohl es in 10-30% der Fälle vorkommt).

Wir verwenden Fedora 12 Linux als Betriebssystem und Nginx als Webserver.

Screenshot der Wireshark-Analyse

Screenshot der Wireshark-Analyse

Aktualisieren:

Das Deaktivieren der Fensterskalierung auf dem Client hat das Problem verhindert. Jetzt brauche ich nur eine serverseitige Auflösung (wir können nicht alle Clients dazu bringen, dies zu tun) :)

Endgültiges Update:

Die Lösung bestand darin, sowohl die TCP-Fensterskalierung als auch die TCP-Zeitstempel auf unseren öffentlich zugänglichen Servern zu deaktivieren.

Codemonkey
quelle
1
Ich denke, wir müssen sehen, wie etwas davon passiert.
Coredump
Haben Sie Acls oder Regeln, die auf Reverse-DNS basieren? Möglicherweise müssen Sie sich mehr als nur die Verbindung zwischen dem Client und dem Server ansehen. Möglicherweise läuft eine DNS-Suche aus?
Zoredache
@coredump: Hier ist ein Screenshot der Wireshark-Analyse, die das Problem i.imgur.com/Bnzrm.png zeigt ( ich konnte nicht herausfinden, wie ich nur den Stream exportiere ...)
codemonkey
@Zoredache: Nein, wir haben keine Acls oder Regeln, die auf Reverse DNS basieren. Dies ist ein öffentlich zugänglicher Webserver, auf den jeder zugreifen kann
codemonkey
Nur eine Vermutung, aber machen Sie irgendeine Art von Beschränkung der eingehenden Verbindungsrate auf dem Server? Sprich mit Iptables?
Steven Montag

Antworten:

15

Wir hatten genau das gleiche Problem. Nur das Deaktivieren von TCP-Zeitstempeln löste das Problem.

sysctl -w net.ipv4.tcp_timestamps=0

Um diese Änderung dauerhaft zu machen, geben Sie einen Eintrag in ein /etc/sysctl.conf.

Seien Sie sehr vorsichtig beim Deaktivieren der TCP Window Scale-Option. Diese Option ist wichtig, um eine maximale Leistung über das Internet zu erzielen. Jemand mit einer 10-Megabit / Sek.-Verbindung hat eine suboptimale Übertragung, wenn die Umlaufzeit (im Grunde wie Ping) mehr als 55 ms beträgt.

Wir haben dieses Problem wirklich bemerkt, als sich mehrere Geräte hinter demselben NAT befanden. Ich vermute, dass der Server möglicherweise verwirrt war, wenn Zeitstempel von Android-Geräten und OSX-Computern gleichzeitig angezeigt wurden, da sie völlig unterschiedliche Werte in die Zeitstempelfelder eingaben.

mcdizzle
quelle
4
Für den Fall, dass jemand anderes durch dasselbe Kaninchenloch gerät, in das ich gerade geraten bin: Bevor Sie TCP-Zeitstempel oder Fensterskalierung deaktivieren, die schwerwiegende Auswirkungen auf die Leistung einer stark frequentierten Verbindung haben können, überprüfen Sie, ob tcp_tw_recycle Ihr Problem ist: stackoverflow .com / questions / 8893888 /…
nephtes
12

In meinem Fall hat der folgende Befehl das Problem mit fehlenden SYN / ACK-Antworten vom Linux-Server behoben:

sysctl -w net.ipv4.tcp_tw_recycle=0

Ich denke, es ist richtiger als das Deaktivieren von TCP-Zeitstempeln, da TCP-Zeitstempel für eine hohe Leistung (PAWS, Fensterskalierung usw.) nützlich sind .

In der Dokumentation zu wird tcp_tw_recycleausdrücklich darauf hingewiesen, dass die Aktivierung nicht empfohlen wird, da bei vielen NAT-Routern Zeitstempel beibehalten werden und daher PAWS aktiviert wird, da Zeitstempel derselben IP nicht konsistent sind.

   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
quelle
1
Eine gute Erklärung finden Sie hier: vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux Aktivieren Sie auf der Serverseite net.ipv4.tcp_tw_recycle nur, wenn Sie sich ziemlich sicher sind, dass Sie niemals NAT-Geräte haben in der Mischung.
Gnought
1
In meinem Fall net.ipv4.tcp_tw_recycleist das der wahre Grund. Vielen Dank.
Bluearrow
tcp_tw_recycle wurde in den letzten Kerneln entfernt. Gibt es eine andere Lösung? @nephtes bedeutet, dass das Deaktivieren des Zeitstempels die Leistung beeinträchtigt.
6.
Da tcp_tw_recycle entfernt wurde, sollte das Problem nicht erneut auftreten, da es nur bei einem nicht standardmäßigen Wert von tcp_tw_recycle auftrat.
Lav
5

Ich frage mich nur, warum für das SYN-Paket (Frame # 539; das, das akzeptiert wurde) die Felder WS und TSV in der Spalte "Info" fehlen?

WS ist TCP Window Scaling und TSV ist Timestamp Value . Beide befinden sich im Feld tcp.options und Wireshark sollte sie weiterhin anzeigen, wenn sie vorhanden sind. Vielleicht hat der TCP / IP-Stapel des Clients beim achten Versuch ein anderes SYN-Paket gesendet, und aus diesem Grund wurde es plötzlich bestätigt?

Können Sie uns interne Werte für Frame 539 bereitstellen? Kommt das SYN / ACK immer für ein SYN-Paket, für das WS nicht aktiviert ist?

Hans Solo
quelle
@Ansis: Hier einige Screenshots zu den Details von Frame 539 (musste in zwei Teilen erstellt werden): i.imgur.com/D84GC.png & i.imgur.com/4riq3.png
codemonkey
@codemonkey: Ihr 8. SYN-Paket scheint sich von den ersten sieben SYN-Paketen zu unterscheiden. Reagiert der Server nur dann mit SYN / ACK auf das SYN des Clients, wenn das Feld "tcp.options" eine Größe von 8 Byte hat (die ersten sieben SYN-Pakete haben wahrscheinlich tcp.options mit einer Größe von 20 Byte)? Können Sie die TCP-Fensterskalierung auf der Clientseite deaktivieren, um festzustellen, ob das Problem behoben ist? Scheint wie ein Problem mit TCP / IP-Stack auf der Serverseite oder einer falsch konfigurierten Firewall irgendwo ...
Hans Solo
@Ansis: Ja, das habe ich mir angesehen, seit du darauf hingewiesen hast und alle anderen SYN-Pakete sind 24 Bytes groß. Ich werde versuchen, die Fensterskalierung auf dem Client zu deaktivieren und morgens die Ergebnisse erneut einzuchecken.
Codemonkey
@Ansis: Das Deaktivieren der Windows-Skalierung auf dem Client hat das Problem verhindert. Vielen Dank! Aber jetzt muss ich herausfinden , wie dies auf der Serverseite zu beheben (da wir nicht alle unsere Kunden deaktivieren Fenster Skalierung machen kann) :) Der betreffende Server hat net.ipv4.tcp_windows_scaling = 1
codemonkey
@Codemonkey: Ich stimme zu, dass das Deaktivieren von WS auf allen Clients keine Lösung ist, aber wir haben das Problem zumindest bis zu Problemen mit der WS- / Paketgröße verfolgt. Um die Ursache genauer zu bestimmen, sollten wir untersuchen, wie Ihre Firewall konfiguriert ist. Können Sie mit WS TCP-Verbindungen zu verschiedenen TCP-Ports herstellen? Von verschiedenen Quell-IPs?
Hans Solo
4

Wir sind auf genau dasselbe Problem gestoßen (es hat wirklich eine ganze Weile gedauert, es an den Server anzuheften, der keine Synchronisierung sendet).

"Die Lösung bestand darin, die TCP-Windows-Skalierung und die TCP-Zeitstempel auf unseren öffentlich zugänglichen Servern zu deaktivieren."

Alex Li
quelle
2

Um weiterzumachen, was Ansis gesagt hat, habe ich Probleme wie diese gesehen, wenn die Firewall TCP Windows Scaling nicht unterstützt. Welche Marken- / Modell-Firewall befindet sich zwischen diesen beiden Hosts?

Joeqwerty
quelle
Die Firewall ist eine Fedora 13-Box, die iptables verwendet. net.ipv4.tcp_windows_scaling wird auch auf diesem Rechner auf 1 gesetzt
codemonkey
2

Das fehlende SYN / ACK kann durch zu niedrige Grenzwerte Ihres SYNFLOOD-Schutzes auf der Firewall verursacht werden. Dies hängt davon ab, wie viele Verbindungen Ihr Serverbenutzer herstellt. Die Verwendung von spdy würde die Anzahl der Verbindungen verringern und könnte in Situationen hilfreich sein, in denen das net.ipv4.tcp_timestampsAusschalten nicht hilft.

brablc
quelle
1

Dies ist das Verhalten eines empfangsbereiten TCP-Sockets, wenn sein Rückstand voll ist.

In Ngnix kann das Backlog-Argument zum Abhören in der Konfiguration festgelegt werden: http://wiki.nginx.org/HttpCoreModule#listen

listen 80 backlog = num

Versuchen Sie, num auf einen Wert zu setzen, der größer als der Standardwert ist, z. B. 1024.

Ich kann nicht garantieren, dass eine vollständige Warteschlange tatsächlich Ihr Problem ist, aber dies ist eine gute erste Sache, die Sie überprüfen sollten.

akramer
quelle
Danke für den Tipp. Ich werde es ausprobieren. Wir haben das Backlog auf Betriebssystemebene festgelegt, jedoch nicht explizit in der Nginx-Konfiguration. Ich werde mit dem Ergebnis aktualisieren.
Codemonkey
es hat das Verhalten überhaupt nicht verändert. Rate mal, es ist nicht das Problem? oder das einzige Problem ...
Codemonkey
1
Anwendungsebene Rückstand Parameter steuern Größe der Warteschlange für abgeschlossen TCP - Verbindungen , dh 3-Wege - Handshake abgeschlossen, dh syn-ack empfangen - so ist es nicht OP Situation überein
ygrek
1

Ich habe gerade festgestellt, dass Linux-TCP-Clients ihr SYN-Paket nach drei Versuchen ändern und die Option für die Fensterskalierung entfernen. Ich denke, die Kernel-Entwickler haben herausgefunden, dass dies eine häufige Ursache für Verbindungsfehler im Internet ist

Hier wird erklärt, warum diese Clients nach 11 Sekunden eine Verbindung herstellen können (die fensterlose TCP-SYN erfolgt nach 9 Sekunden in meinem kurzen Test mit den Standardeinstellungen).

Jeroen van Bemmel
quelle
0

Ich hatte ein ähnliches Problem, aber in meinem Fall wurde die TCP-Prüfsumme falsch berechnet. Der Client war hinter einem veth und das Ausführen von ethtool -Kveth0 rx off tx off hat den Trick gemacht.

Baroudi Safwen
quelle