Co ogranicza maksymalną liczbę połączeń na serwerze Linux?

89

Jaki parametr jądra lub inne ustawienia kontrolują maksymalną liczbę gniazd TCP, które można otworzyć na serwerze z systemem Linux? Jakie są wady udostępniania większej liczby połączeń?

Zauważyłem podczas testowania obciążenia serwera Apache za pomocą ab , że dość łatwo jest zmaksymalizować otwarte połączenia na serwerze. Jeśli zrezygnujesz z opcji -k ab, która pozwala na ponowne użycie połączenia i sprawi, że wyśle ​​ona więcej niż około 10 000 żądań, wtedy Apache obsłuży około 11 000 żądań, a następnie zatrzyma się na 60 sekund. Spojrzenie na dane wyjściowe netstat pokazuje 11 000 połączeń w stanie TIME_WAIT. Najwyraźniej jest to normalne. Połączenia są utrzymywane otwarte domyślnie przez 60 sekund, nawet po zakończeniu pracy z klientem ze względu na niezawodność TCP .

Wygląda na to, że byłby to łatwy sposób na wykonanie DoS serwera i zastanawiam się, jakie są typowe ustawienia i środki ostrożności.

Oto mój wynik testu:

# ab -c 5 -n 50000 http://localhost/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 5000 requests
Completed 10000 requests
apr_poll: The timeout specified has expired (70007)
Total of 11655 requests completed

Oto polecenie netstat, które uruchamiam podczas testu:

 # netstat --inet -p | grep "localhost:www" | sed -e 's/ \+/ /g' | cut -d' ' -f 1-4,6-7 | sort | uniq -c 
  11651 tcp 0 0 localhost:www TIME_WAIT -
      1 tcp 0 1 localhost:44423 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44424 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44425 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44426 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44428 SYN_SENT 7831/ab
Ben Williams
źródło

Odpowiedzi:

64

I w końcu znaleźć ustawienia, które naprawdę ograniczający liczbę połączeń: net.ipv4.netfilter.ip_conntrack_max. Ustawiono na 11776 i cokolwiek ustawię, to liczba żądań, które mogę obsłużyć w moim teście, zanim będę musiał czekać tcp_fin_timeoutsekundy na udostępnienie większej liczby połączeń. conntrackStół jest co jądro wykorzystuje do śledzenia stanu połączeń tak, raz jest pełny, jądro zaczyna upuszczenie pakiety i drukowanie to w dzienniku:

Jun  2 20:39:14 XXXX-XXX kernel: ip_conntrack: table full, dropping packet.

Następnym krokiem było zmusienie jądra do przetworzenia wszystkich połączeń w tym TIME_WAITstanie, zamiast upuszczania pakietów. Mogłem to zrobić albo przez włączenie, tcp_tw_recyclealbo zwiększenie, ip_conntrack_maxby było większe niż liczba portów lokalnych udostępnionych do połączeń przez ip_local_port_range. Wydaje mi się, że kiedy jądro znajdzie się poza portami lokalnymi, zaczyna ponownie przetwarzać połączenia. Wykorzystuje to więcej połączeń do śledzenia pamięci, ale wydaje się, że jest to lepsze rozwiązanie niż włączenie, tcp_tw_recycleponieważ dokumenty sugerują, że jest to niebezpieczne.

Dzięki tej konfiguracji mogę uruchomić ab przez cały dzień i nigdy nie zabraknie połączeń:

net.ipv4.netfilter.ip_conntrack_max = 32768
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_orphan_retries = 1
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_max_orphans = 8192
net.ipv4.ip_local_port_range = 32768    61000

tcp_max_orphansUstawienie nie ma żadnego wpływu na moich testów i nie wiem dlaczego. Myślałbym, że to zamknie połączenia w TIME_WAITstanie, gdy będzie ich 8192, ale nie robi to dla mnie.

Ben Williams
źródło
3
Gdzie konfigurujemy te parametry?
Codevalley,
2
@Codevalley To może być zależne od systemu, ale na Ubuntu Server są w /etc/sysctl.conf
Ben Williams
24

Naprawdę chcesz zobaczyć, co system plików / proc ma do zaoferowania w tym zakresie.

Na ostatniej stronie mogą Cię zainteresować:

  • / proc / sys / net / ipv4 / tcp_max_orphans , który kontroluje maksymalną liczbę gniazd posiadanych przez system nie dołączonym do czegoś. Zwiększenie tej liczby może zużywać aż 64 KB nieprzekraczalnej pamięci na gniazdo osierocone .
  • / proc / sys / net / ipv4 / tcp_orphan_retries , który kontroluje liczbę ponownych prób, zanim gniazdo zostanie osierocone i zamknięte. Na tej stronie znajduje się szczegółowa informacja o serwerach internetowych, która jest bezpośrednio dla Ciebie interesująca ...
Avery Payne
źródło
tcp_max_orphans jest interesujący, ale wygląda na to, że nie działa. Kiedy próbuję zmierzyć osierocone gniazda podczas testu, widzę ich 11 651, podczas gdy tcp_max_orphans wynosi 8 092. # netstat --inet -p | grep „localhost: www” | sed -e 's / \ + / / g' | cut -d '' -f 1-4,6-7 | sortuj | uniq -c 11651 tcp 0 0 localhost: www TIME_WAIT -
Ben Williams
Spójrz na ustawienie tcp_orphan_retries - idea jest taka, że ​​gniazda są „wygładzane” szybciej ...
Avery Payne
Sugestia Jaudera Ho + tcp_orphan_retries brzmi jak potencjalna wygrana dla twojej sytuacji.
Avery Payne
3

Nie sądzę, żeby można było to ustawić bezpośrednio. Obejmuje to kategorię strojenia TCP / IP. Aby dowiedzieć się, co możesz nastroić, spróbuj „man 7 tcp”. Sysctl ('man 8 sysctl') służy do ich ustawiania. „sysctl -a | grep tcp 'pokaże ci większość tego, co możesz dostroić, ale nie jestem pewien, czy pokaże wszystkie z nich. Ponadto, chyba że się to zmieni, otwarte gniazda TCP / IP wyglądają jak deskryptory plików. Więc ta i następna sekcja tego linku może być tym, czego szukasz.

Kyle Brandt
źródło
2

Spróbuj ustawić następujące ustawienia, a także ustawienie tcp_fin_timeout. To powinno zamknąć TIME_WAIT szybciej.

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
Jauder Ho
źródło
Ostrożnie tutaj! Przeżyłem ciężko. „Może to powodować upuszczanie ramek z równoważeniem obciążenia i translacją NAT, używaj tego tylko do serwera, który komunikuje się tylko przez sieć lokalną.” - wiki.archlinux.org/index.php/Sysctl
Henk
@Henk Chyba jest tcp_tw_recycleto potencjalnie niebezpieczne. tcp_tw_reusejest bezpieczniejszy i nie widzę powodu, aby używać ich jednocześnie.
Vladislav Rastrusny
2

Apache zapasowy (1) był predefiniowany do obsługi tylko 250 równoczesnych połączeń - jeśli chcesz więcej, możesz zmodyfikować jeden plik nagłówka, aby zezwolić na więcej równoczesnych sesji. Nie wiem, czy nadal tak jest w przypadku Apache 2.

Ponadto należy dodać opcję zezwalającą na ładowanie większej liczby otwartych deskryptorów plików dla konta, na którym działa Apache - czego nie zauważają poprzednie komentarze.

Zwróć uwagę na ustawienia pracownika i jakie limity czasu podtrzymywania masz w samym Apache, ile zapasowych serwerów masz uruchomionych jednocześnie i jak szybko te dodatkowe procesy giną.

rasjani
źródło
1

Możesz skrócić czas spędzony w stanie TIME_WAIT (Ustaw net.ipv4.tcp_fin_timeout). Możesz zastąpić Apache YAWS lub nginx lub czymś podobnym.

Kompromisy związane z większą liczbą połączeń zazwyczaj wiążą się z użyciem pamięci, a jeśli masz proces rozwidlania, wiele procesów potomnych, które zalewają procesor.

Devdas
źródło
1
tcp_fin_timeout nie służy do ustawiania czasu wygaśnięcia TIME-WAIT, którego nie można zmienić poza przebudową jądra, ale dla FIN, jak wskazuje nazwa.
Alexandr Kurilin
0

Bezwzględna liczba gniazd, które można otworzyć na jednym adresie IP, wynosi 2 ^ 16 i jest zdefiniowana przez TCP / UDP, a nie jądro.

Jason Tan
źródło
6
Nie, nie jest. Możesz otworzyć więcej, ponieważ port lokalny nie musi być unikalny, o ile adresy zdalne są różne. Co więcej, OP powiedział na serwer i możesz mieć> 1 adres na serwer.
MarkR