Risposte:
Un ACK TCP di base dice "Ho ricevuto tutti i byte fino a X." ACK selettivo ti consente di dire "Ho ricevuto i byte XY e VZ".
Quindi, ad esempio, se un host ti inviasse 10.000 byte e 3000-5000 byte andassero persi durante il trasporto, ACK direbbe "Ho ottenuto tutto fino a 3000". L'altra estremità dovrebbe inviare nuovamente byte 3001-10000. SACK potrebbe dire "Ho ricevuto 1000-2999 e 5001-10000" e l'host avrebbe semplicemente inviato il 3000-5000.
Questo è ottimo su un collegamento ad alta larghezza di banda, perdita (o ritardo elevato). Il problema è che può causare gravi problemi di prestazioni in circostanze specifiche. I normali ACK TCP faranno sì che il server tratti una connessione ad alta larghezza di banda e con perdita di dati con guanti per bambini (invia 500 byte, aspetta, invia 500 byte, aspetta, ecc.). SACK consente di adattarsi al ritardo elevato perché sa esattamente quanti pacchetti sono stati effettivamente persi.
Qui è dove possono succedere cose brutte. Un utente malintenzionato può forzare il server a mantenere una lunga coda di ritrasmissione per lungo tempo, quindi elaborare quella dannata faccenda ancora e ancora e ancora. Questo può danneggiare la CPU, consumare RAM e consumare più larghezza di banda di quanto dovrebbe. In poche parole, un sistema leggero può avviare un DoS contro un server più robusto.
Se il tuo server è robusto e non serve file di grandi dimensioni, sei abbastanza ben isolato da questo.
Se stai principalmente servendo una rete intranet o un altro gruppo di utenti a bassa latenza, SACK non acquista nulla e può essere disattivato per motivi di sicurezza senza perdita di prestazioni.
Se si utilizza un collegamento a larghezza di banda ridotta (ad esempio 1 Mbps o meno come regola empirica completamente arbitraria), SACK può causare problemi nelle normali operazioni saturando la connessione e deve essere disattivato.
Alla fine, dipende da te. Considera cosa stai servendo, a chi, da cosa, e valuta il grado del tuo rischio rispetto agli effetti sulle prestazioni di SACK.
C'è una grande panoramica di SACK e la sua vulnerabilità qui.
Un altro motivo per cui TCP SACK è spesso disabilitato è che esiste una quantità incredibile di dispositivi di rete che non riescono a gestire correttamente questa opzione. Lo vediamo continuamente con un prodotto di trasferimento file ad alta velocità che forniamo che utilizza TCP. Il problema più comune è quello dei dispositivi gateway che fanno cose come randomizzare i numeri di sequenza per i pacchetti TCP che transitano attraverso il dispositivo da reti interne a esterne, ma che non "non randomizzano" le opzioni TCP SACK che potrebbero essere inviate dal telecomando fine. Se i valori SACK effettivi non vengono convertiti in valori corretti da questi dispositivi, la sessione TCP non verrà mai completata di fronte alla perdita di pacchetti quando l'estremità remota tenta di utilizzare SACK per ottenere i vantaggi ACK selettivi.
Probabilmente questo sarebbe un problema minore se le persone dovessero applicare in modo più aggressivo la manutenzione preventiva del software a questa attrezzatura, ma tendono a non farlo.
Posso confermare per amara esperienza che tcp_sack = 1 causa il trasferimento di dati in stallo su sftp / rsync / scp ecc. Con file superiori a circa 12 MB quando si utilizzano determinati dispositivi firewall Cisco ASA.
OGNI volta sarebbe bloccato.
Stavamo trasferendo su un collegamento dedicato a 100 Mbps tra l'host A e l'host B in due diversi data center, entrambi utilizzando firewall Cisco e scambiando hardware con centos.
Questo può essere in qualche modo mitigato modificando le dimensioni del buffer, ad esempio non sono riuscito a trasferire il file da 1 GB tramite sftp dall'host A all'host B a meno che non imposti il buffer sftp su 2048, ma potrei indipendentemente se l'host B stava estraendo il file da A.
Esperimenti con lo stesso file usando rsync e l'ottimizzazione del buffer di invio / ricezione mi hanno permesso di alzare circa 70 mb di un file da 1 GB trasferito da A a B.
Tuttavia, la risposta definitiva è stata disabilitare tcp_sack sull'host A. Inizialmente impostando tcp_sack = 0 nel kernel al volo - ma alla fine - l'ho aggiunto al mio /etc/sysctl.conf