Jakie są konsekwencje ustawienia tcp_tw_recycle / reuse na 1?

10

W moim pliku konfiguracyjnym ustawiłem opcję tcp_tw_recycle / reuse na 1.

Jakie są tego konsekwencje?

Czy ponowne użycie gniazda TCP może stanowić zagrożenie dla bezpieczeństwa? tj. 2 różne połączenia, z których oba potencjalnie mogą wysyłać dane?

Czy nadaje się do krótkotrwałych połączeń z niewielką szansą na ponowne połączenie?

uzupełnianie kodowe
źródło
Oczywiste pytanie brzmi: czego oczekujesz od tej zmiany?
Robert Munteanu,
1
@RobertMunteanu powiązany z: serverfault.com/questions/342501/…
uzupełnianie kodowe

Odpowiedzi:

24

Domyślnie, gdy oba tcp_tw_reusei tcp_tw_recyclesą wyłączone, jądro będzie upewnić się, że gniazda w TIME_WAITstanie pozostanie w tym stanie wystarczająco długo - wystarczająco długo, aby mieć pewność, że pakiety należące do połączeń przyszłości nie będą mylone z późnych pakietów starego połączenia.

Gdy włączysz tcp_tw_reuse, gniazda w TIME_WAITstanie mogą być używane przed ich wygaśnięciem, a jądro spróbuje upewnić się, że nie dojdzie do kolizji w odniesieniu do numerów sekwencji TCP. Jeśli włączysz tcp_timestamps(inaczej PAWS, dla ochrony przed zawiniętymi numerami sekwencji), upewni się, że kolizje te nie będą miały miejsca. Musisz jednak włączyć znaczniki czasu TCP na obu końcach (przynajmniej tak rozumiem). Zobacz definicję tcp_twsk_unique dla szczegółów krwawych.

Po włączeniu tcp_tw_recyclejądro staje się znacznie bardziej agresywne i przyjmuje założenia dotyczące znaczników czasu używanych przez zdalne hosty. Będzie śledził ostatni znacznik czasu używany przez każdy zdalny host mający połączenie w TIME_WAITstanie) i pozwoli na ponowne użycie gniazda, jeśli znacznik czasu prawidłowo się zwiększył. Jeśli jednak znacznik czasu używany przez host zmieni się (tzn. Wypaczy się w czasie), SYNpakiet zostanie po cichu odrzucony, a połączenie nie zostanie nawiązane (zobaczysz błąd podobny do „limitu czasu połączenia”). Jeśli chcesz zanurzyć się w kodzie jądra, definicja tcp_timewait_state_process może być dobrym punktem wyjścia.

Teraz znaczniki czasu nigdy nie powinny cofać się w czasie; chyba że:

  • host zostanie zrestartowany (ale wtedy, zanim wróci, TIME_WAITgniazdo prawdopodobnie wygasło, więc nie będzie problemu);
  • adres IP jest szybko ponownie wykorzystywany przez coś innego ( TIME_WAITpołączenia pozostaną trochę, ale prawdopodobnie inne połączenia zostaną naruszone TCP RST, co zwolni miejsce);
  • translacja adresów sieciowych (lub firewall smarty-pants) jest zaangażowana w połączenie.

W tym drugim przypadku możesz mieć wiele hostów za tym samym adresem IP, a zatem różne sekwencje znaczników czasu (lub wspomniane znaczniki czasu są losowo przydzielane przy każdym połączeniu przez zaporę). W takim przypadku niektóre hosty nie będą mogły połączyć się losowo, ponieważ są mapowane na port, dla którego TIME_WAITsegment serwera ma nowszą sygnaturę czasową. Dlatego dokumenty mówią, że „urządzenia NAT lub moduły równoważenia obciążenia mogą zacząć upuszczać ramki z powodu ustawienia”.

Niektóre osoby zalecają pozostawienie w tcp_tw_recyclespokoju, ale włączanie tcp_tw_reusei obniżanietcp_timewait_len . Zgadzam się :-)

jpetazzo
źródło
świetne wyjaśnienie
yanglei
6

Właśnie mnie ugryzł, więc może ktoś mógłby skorzystać z mojego bólu i cierpienia. Po pierwsze, zaangażowany link z dużą ilością informacji: http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html

W szczególności:

Jedynym rezultatem tego braku dokumentacji jest to, że znajdujemy liczne przewodniki po tuningu, które zalecają ustawienie obu tych ustawień na 1, aby zmniejszyć liczbę wpisów w stanie CZAS OCZEKIWANIA. Jednak, jak stwierdzono na stronie podręcznika tcp (7), opcja net.ipv4.tcp_tw_recycle jest dość problematyczna dla serwerów publicznych, ponieważ nie obsługuje połączeń z dwóch różnych komputerów za tym samym urządzeniem NAT, co jest trudnym problemem wykryj i czekam na ugryzienie:

Korzystałem z tego, że włączono je z powodzeniem, aby zapewnić możliwie małe opóźnienie, haproxy łączność od klientów do klastra MySql NDB. To było w prywatnej chmurze i żadne połączenia z żadnego do żadnego nie miały żadnego NAT w miksie. Przypadek użycia miał sens, zmniejsz opóźnienie dla klientów promienia uderzających w NDB przez haproxy tak bardzo, jak to tylko możliwe. Tak się stało.

Zrobiłem to jeszcze raz w publicznym systemie haproxy, równoważąc obciążenie ruchem sieciowym, tak naprawdę nie badając wpływu (głupi, prawda ?!) i odkryłem po wielu problemach i ściganiu duchów, które:

  • Stworzy chaos dla klientów łączących się przez NAT.
  • Identyfikacja jest prawie niemożliwa, ponieważ jest całkowicie losowa, przerywana, a objawy uderzą w klienta A w zupełnie innych (lub nie) czasach niż klient B itp.

Po stronie klienta będą widzieć okresy, w których nie będą już otrzymywać odpowiedzi na pakiety SYN, czasem tu i tam, a czasem przez długi czas. Znowu losowo.

Krótka historia, w moim niedawnym, bolesnym doświadczeniu, polega na pozostawieniu ich samych / wyłączonych na publicznych serwerach, bez względu na rolę!

Prochowiec
źródło
4

Od 'man 7 tcp' Zobaczysz to:

   tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
          Enable fast recycling of TIME_WAIT sockets.  Enabling this option is not recommended since this causes problems when working with NAT
          (Network Address Translation).

   tcp_tw_reuse (Boolean; default: disabled; since Linux 2.4.19/2.6)
          Allow  to  reuse  TIME_WAIT  sockets  for  new connections when it is safe from protocol viewpoint.  It should not be changed without
          advice/request of technical experts.

Niewiele tam pomocy. Ta wersja ma również dobry wgląd:

/programming/6426253/tcp-tw-reuse-vs-tcp-tw-recycle-which-to-use-or-both

Ale nie konkretne informacje o tym, dlaczego ponowne użycie jest bezpieczniejsze niż recykling. Podstawowa odpowiedź jest taka, że ​​tcp_tw_reuse pozwoli na skorzystanie z tego samego gniazda, jeśli jest już jedno w TIME_WAIT z tymi samymi parametrami TCP i jest w stanie, w którym nie oczekuje się dalszego ruchu (wierzę, że po wysłaniu FIN ). Z drugiej strony tcp_tw_recycle ponownie użyje gniazd w TIME_WAIT z tymi samymi parametrami niezależnie od stanu, co może dezorientować stanowe zapory ogniowe, które mogą oczekiwać różnych pakietów.

tcp_tw_reuse można wykonać selektywnie w kodzie, ustawiając opcję gniazda SO_REUSEADDR, udokumentowaną man 7 socketjako:

   SO_REUSEADDR
          Indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses.  For  AF_INET
          sockets  this means that a socket may bind, except when there is an active listening socket bound to the address.  When the listening
          socket is bound to INADDR_ANY with a specific port then it is not possible to bind to this port for any local address.   Argument  is
          an integer boolean flag.
Spamapy
źródło
1
Czy jesteś pewien, że SO_REUSEADDRjest to powiązane tcp_tw_reuse? O ile mi wiadomo, SO_REUSEADDRma zastosowanie tylko wtedy, gdy chcesz bind(), tcp_tw_reusei poinstruuje jądro, aby ponownie użyło portu lokalnego gniazda w TIME_WAITstanie, jeśli będzie musiało utworzyć nowe połączenie wychodzące.
jpetazzo
Nie, nie jestem pewien. :-P
SpamapS