Perché un server non dovrebbe inviare un pacchetto SYN / ACK in risposta a un pacchetto SYN?


46

Ultimamente, siamo venuti a conoscenza di un problema di connessione TCP che è principalmente limitato agli utenti Mac e Linux che navigano nei nostri siti Web.

Dal punto di vista dell'utente, si presenta come un tempo di connessione molto lungo ai nostri siti Web (> 11 secondi).

Siamo riusciti a rintracciare la firma tecnica di questo problema, ma non possiamo capire perché sta accadendo o come risolverlo.

Fondamentalmente, ciò che sta accadendo è che la macchina del client sta inviando il pacchetto SYN per stabilire la connessione TCP e il server Web lo riceve, ma non risponde con il pacchetto SYN / ACK. Dopo che il client ha inviato molti pacchetti SYN, il server risponde infine con un pacchetto SYN / ACK e tutto va bene per il resto della connessione.

E, naturalmente, il kicker del problema: è intermittente e non si verifica continuamente (sebbene avvenga tra il 10-30% delle volte)

Stiamo usando Fedora 12 Linux come sistema operativo e Nginx come server web.

Schermata dell'analisi dei cavi

Schermata dell'analisi dei cavi

Aggiornare:

La disattivazione del ridimensionamento delle finestre sul client ha impedito il verificarsi del problema. Ora ho solo bisogno di una risoluzione lato server (non possiamo fare in modo che tutti i client lo facciano) :)

Aggiornamento finale:

La soluzione era quella di spegnere sia il TCP window scaling e il protocollo TCP timestamp sui nostri server che sono accessibili al pubblico.


1
Penso che avremo bisogno di vedere un po 'di successo.
coredump,

Hai qualche acl o regole basato su DNS inverso? Potrebbe essere necessario esaminare più della semplice connessione tra client e server. Forse sta scadendo una ricerca DNS?
Zoredache,

@coredump: ecco una schermata dell'analisi WireShark che mostra il problema i.imgur.com/Bnzrm.png (non riuscivo a capire come esportare solo il flusso ....)
codemonkey

@Zoredache: no, non abbiamo acls o regole basate su DNS inverso. Questo è un server web pubblico e permettiamo a tutti di accedervi
codemonkey,

Solo un sospetto, ma stai facendo qualche tipo di limitazione della velocità di connessione in entrata sul server? Dire, con iptables?
Steven lunedì

Risposte:


15

Abbiamo avuto lo stesso identico problema. La sola disabilitazione dei timestamp TCP ha risolto il problema.

sysctl -w net.ipv4.tcp_timestamps=0

Per rendere permanente questa modifica, effettuare una registrazione /etc/sysctl.conf.

Prestare molta attenzione alla disabilitazione dell'opzione TCP Window Scale. Questa opzione è importante per fornire le massime prestazioni su Internet. Qualcuno con una connessione da 10 megabit / sec avrà un trasferimento non ottimale se il tempo di andata e ritorno (sostanzialmente uguale al ping) è superiore a 55 ms.

Abbiamo davvero notato questo problema quando c'erano più dispositivi dietro lo stesso NAT. Ho il sospetto che il server potrebbe essere stato confuso vedendo i timestamp da dispositivi Android e macchine OSX contemporaneamente poiché hanno messo valori completamente diversi nei campi timestamp.


4
Nel caso in cui qualcun altro finisca qui attraverso la stessa tana del coniglio che ho appena abbattuto: prima di disattivare i timestamp TCP o il ridimensionamento delle finestre, che potrebbero avere gravi conseguenze sulle prestazioni su un collegamento ad alto traffico, controlla se tcp_tw_recycle è il tuo problema: stackoverflow .com / questions / 8893888 /…
nephtes

12

Nel mio caso il seguente comando ha risolto il problema con risposte SYN / ACK mancanti dal server Linux:

sysctl -w net.ipv4.tcp_tw_recycle=0

Penso che sia più corretto della disabilitazione dei timestamp TCP, poiché i timestamp TCP sono utili per prestazioni elevate (PAWS, ridimensionamento delle finestre, ecc.).

La documentazione sull'affermazione tcp_tw_recycleesplicita che non è consigliabile abilitarlo, poiché molti router NAT conservano i timestamp e quindi si attiva PAWS, poiché i timestamp dello stesso IP non sono coerenti.

   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.

1
buona spiegazione qui: vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux Sul lato server, non abilitare net.ipv4.tcp_tw_recycle a meno che tu non sia abbastanza sicuro di non avere mai dispositivi NAT nel miscuglio.
Gnought il

1
Nel mio caso, net.ipv4.tcp_tw_recycleè la vera ragione. Grazie.
bluearrow il

tcp_tw_recycle è stato rimosso nei kernel recenti. C'è un'altra soluzione simile? @nephtes implica che disabilitare il timestamp fa male alle prestazioni.
MappaM

Poiché tcp_tw_recycle è stato rimosso, il problema non dovrebbe ripresentarsi poiché si è verificato solo con un valore non predefinito di tcp_tw_recycle.
lav

5

Mi chiedo, ma perché per il pacchetto SYN (frame # 539; quello che è stato accettato), i campi WS e TSV mancano nella colonna "Info"?

WS è il ridimensionamento delle finestre TCP e TSV è il valore data / ora . Entrambi si trovano nel campo tcp.options e Wireshark dovrebbe comunque mostrarli se sono presenti. Forse lo stack TCP / IP client ha rinviato diversi pacchetti SYN all'ottavo tentativo e questo è stato il motivo per cui è stato improvvisamente riconosciuto?

Potresti fornirci i valori interni del frame 539? SYN / ACK viene sempre per un pacchetto SYN che non ha WS abilitato?


@Ansis: ecco alcune schermate per i dettagli del fotogramma 539 (ho dovuto farlo in due parti): i.imgur.com/D84GC.png & i.imgur.com/4riq3.png
codemonkey

@codemonkey: il tuo ottavo pacchetto SYN sembra essere diverso dai primi sette pacchetti SYN. Il server risponde con SYN / ACK al SYN del client solo quando il campo tcp.options ha una dimensione di 8 byte (I primi sette pacchetti SYN probabilmente hanno tcp.options di dimensione 20 byte.)? È possibile disabilitare il ridimensionamento delle finestre TCP sul lato client per vedere se il problema scompare? Sembra un problema con lo stack TCP / IP sul lato server o il firewall configurato in modo errato da qualche parte ...
Hans Solo

@Ansis: sì, lo guardo da quando l'hai sottolineato e tutti gli altri pacchetti SYN sono 24 byte. Proverò a disabilitare il ridimensionamento delle finestre sul client e tornerò con i risultati al mattino.
codemonkey

@Ansis: la disattivazione del ridimensionamento di Windows sul client ha impedito il verificarsi del problema. Grazie! Tuttavia, ora ho bisogno di capire come risolvere questo problema sul lato server (poiché non possiamo fare in modo che tutti i nostri client disabilitino il ridimensionamento di Windows) :) Il server in questione ha net.ipv4.tcp_windows_scaling = 1
codemonkey

@Codemonkey: concordo sul fatto che disabilitare WS su tutti i client non è una soluzione, ma almeno abbiamo individuato il problema in WS / Packet Size. Per trovare ulteriormente la causa dovremmo esaminare come è configurato il firewall. È possibile stabilire connessioni TCP con WS a diverse porte TCP? Da diversi IP di origine?
Hans Solo,

4

Ci siamo appena imbattuti nello stesso identico problema (ci è voluto davvero un po 'di tempo per bloccarlo sul server senza inviare syn-ack).

"La soluzione era disattivare il ridimensionamento di tcp windows e i timestamp di tcp sui nostri server che sono accessibili al pubblico".


2

Per portare avanti quanto affermato da Ansis, ho riscontrato problemi come questo quando il firewall non supporta il ridimensionamento TCP di Windows. Quale marca / modello firewall è tra questi due host?


Il firewall è un box Fedora 13 che utilizza iptables. net.ipv4.tcp_windows_scaling è impostato su 1 anche su questa macchina
codemonkey

2

Il SYN / ACK mancante potrebbe essere causato da limiti troppo bassi della protezione SYNFLOOD sul firewall. Dipende dal numero di connessioni create dall'utente del server. L'uso di spdy ridurrebbe il numero di connessioni e potrebbe aiutare in situazioni in cui lo net.ipv4.tcp_timestampsspegnimento non aiuta.


1

Questo è il comportamento di un socket TCP in ascolto quando il suo backlog è pieno.

Ngnix consente di impostare l'argomento backlog da ascoltare nella configurazione: http://wiki.nginx.org/HttpCoreModule#listen

ascolta 80 backlog = num

Prova a impostare num su qualcosa di più grande di quello predefinito, come 1024.

Non garantisco che una coda di ascolto completa sia effettivamente il tuo problema, ma questa è una buona prima cosa da verificare.


grazie per il consiglio. Lo proverò. Abbiamo impostato il backlog a livello di sistema operativo, ma non esplicitamente nella configurazione di Nginx. Aggiornerò con il risultato.
codemonkey,

non ha cambiato affatto il comportamento. Indovina, non è il problema? o l'unico problema ...
codemonkey

1
il parametro backlog a livello di applicazione controlla la dimensione della coda per le connessioni tcp completate, ovvero l'handshake a 3 vie terminata, ovvero la sincronizzazione ricevuta, quindi non corrisponde alla situazione OP
ygrek,

1

Ho appena scoperto che i client TCP Linux cambiano il loro pacchetto SYN dopo 3 tentativi e rimuovono l'opzione di ridimensionamento delle finestre. Immagino che gli sviluppatori del kernel abbiano pensato che questa sia una causa comune di errore di connessione in Internet

Spiega perché questi client riescono a connettersi dopo 11 secondi (il TCP SYN senza finestre si verifica dopo 9 secondi nel mio breve test con le impostazioni predefinite)


0

Ho avuto un problema simile, ma nel mio caso è stato calcolato erroneamente il checksum TCP. Il client era dietro un veth e stava eseguendo ethtool -K veth0 rx off tx off ha fatto il trucco.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.