Jak zapobiec zawieszaniu się połączenia TCP w sieci OpenVPN?

19

Dodano nowe szczegóły na końcu tego pytania; możliwe, że wyceluję przyczynę.

Mam skonfigurowaną w taptrybie sieć VPN opartą na UDP OpenVPN (potrzebuję, tapponieważ potrzebuję VPN do przekazywania pakietów multiemisji, co nie wydaje się możliwe w tunsieciach) z garstką klientów w Internecie. Mam częste zawieszanie się połączenia TCP przez VPN. Oznacza to, że ustanowię połączenie TCP (np. Połączenie SSH, ale inne protokoły mają podobne problemy), a w pewnym momencie sesji wydaje się, że ruch przestanie być przesyłany przez tę sesję TCP.

Wydaje się, że jest to związane z punktami, w których dochodzi do dużych transferów danych, takimi jak wykonanie lspolecenia w sesji SSH lub catdługi plik dziennika. Niektóre wyszukiwania Google wyświetlają szereg odpowiedzi, takich jak ta poprzednia, na Błąd serwera , wskazując, że prawdopodobnym winowajcą jest problem MTU: że w okresach dużego ruchu VPN próbuje wysyłać pakiety, które spadają gdzieś w rurze między Punkty końcowe VPN. Powyższa odpowiedź sugeruje użycie następujących ustawień konfiguracji OpenVPN w celu złagodzenia problemu:

fragment 1400
mssfix

Powinno to ograniczyć MTU używaną w sieci VPN do 1400 bajtów i naprawić maksymalny rozmiar segmentu TCP, aby zapobiec generowaniu większych pakietów. Wydaje się, że to nieco łagodzi problem, ale wciąż często zawieszam się. Próbowałem wielu rozmiarów jako argumentów do fragmentdyrektywy: 1200, 1000, 576, wszystkie z podobnymi wynikami. Nie mogę wymyślić żadnej dziwnej topologii sieci między dwoma końcami, która mogłaby wywołać taki problem: serwer VPN działa na maszynie pfSense podłączonej bezpośrednio do Internetu, a mój klient jest również podłączony bezpośrednio do Internetu w innej lokalizacji.

Jeszcze jeden dziwny element układanki: jeśli uruchomię tracepathnarzędzie, wydaje się, że to pomaga w rozwiązaniu problemu. Przykładowy przebieg wygląda następująco:

[~]$ tracepath -n 192.168.100.91
 1:  192.168.100.90                                        0.039ms pmtu 1500
 1:  192.168.100.91                                       40.823ms reached
 1:  192.168.100.91                                       19.846ms reached
     Resume: pmtu 1500 hops 1 back 64 

Powyższy przebieg odbywa się między dwoma klientami w sieci VPN: Zainicjowałem śledzenie od 192.168.100.90do miejsca docelowego 192.168.100.91. Oba klienty zostały skonfigurowane przy fragment 1200; mssfix;próbie ograniczenia MTU używanego w łączu. Powyższe wyniki wydają się sugerować, że tracepathbył w stanie wykryć MTU ścieżki 1500 bajtów między dwoma klientami. Zakładam, że byłby nieco mniejszy ze względu na ustawienia fragmentacji określone w konfiguracji OpenVPN. Uznałem ten wynik za dość dziwny.

Jeszcze bardziej nieznajomy: jeśli mam połączenie TCP w stanie utknięcia (np. Sesja SSH z listą katalogów, która zamarzła w środku), wówczas wykonanie powyższej tracepathkomendy powoduje ponowne uruchomienie połączenia ! Nie mogę znaleźć żadnego uzasadnionego wyjaśnienia, dlaczego tak jest, ale wydaje mi się, że może to wskazywać na rozwiązanie, które ostatecznie wyeliminuje problem.

Czy ktoś ma jakieś zalecenia dotyczące innych rzeczy do wypróbowania?

Edycja: wróciłem i spojrzałem na to nieco dalej i znalazłem tylko bardziej mylące informacje:

  • Ustawiłem połączenie OpenVPN na fragment o wielkości 1400 bajtów, jak pokazano powyżej. Następnie podłączyłem się do VPN z Internetu i użyłem Wireshark, aby sprawdzić pakiety UDP, które zostały wysłane na serwer VPN podczas wystąpienia przeciągnięcia. Żadna z nich nie była większa niż podana liczba 1400 bajtów, więc fragmentacja wydaje się działać poprawnie.

  • Aby sprawdzić, czy wystarczy nawet 1400-bajtowa jednostka MTU, wysłałem polecenie ping do serwera VPN za pomocą następującego polecenia (Linux):

    ping <host> -s 1450 -M do
    

    To (jak sądzę) wysyła pakiet 1450 bajtów z wyłączoną fragmentacją (przynajmniej zweryfikowałem, że nie działało, jeśli ustawiłem na oczywiście zbyt dużą wartość, np. 1600 bajtów). Te wydają się działać dobrze; Bez problemu otrzymuję odpowiedzi od hosta.

Więc może to wcale nie jest problem MTU. Jestem tylko zdezorientowany, co to może być!

Edycja 2: Królicza nora wciąż się pogłębia: teraz trochę bardziej odizolowałem problem. Wydaje się, że jest to związane z dokładnym systemem operacyjnym, z którego korzysta klient VPN. Udało mi się zduplikować problem na co najmniej trzech komputerach z systemem Ubuntu (wersje od 12.04 do 13.04). Mogę niezawodnie powielić zawieszenie połączenia SSH w ciągu około minuty, po prostu wykonując catduży plik dziennika.

Jeśli jednak wykonam ten sam test, używając komputera CentOS 6 jako klienta, nie widzę problemu! Testowałem przy użyciu dokładnie takiej samej wersji klienta OpenVPN, jak na maszynach Ubuntu. Mogę catrejestrować pliki przez wiele godzin bez zawieszania się połączenia. Wydaje się, że zapewnia to pewien wgląd w ostateczną przyczynę, ale po prostu nie jestem pewien, co to za wgląd.

Sprawdziłem ruch przez VPN za pomocą Wireshark. Nie jestem ekspertem od TCP, więc nie jestem pewien, co sądzić o krwawych szczegółach, ale najważniejsze jest to, że w pewnym momencie pakiet UDP zostaje odrzucony z powodu ograniczonej przepustowości łącza internetowego, powodując retransmisje TCP wewnątrz tunel VPN. Na kliencie CentOS retransmisje odbywają się poprawnie i wszystko przebiega pomyślnie. Jednak w pewnym momencie w przypadku klientów Ubuntu zdalny koniec zaczyna w kółko ponownie przesyłać ten sam segment TCP (wraz ze wzrostem opóźnienia transmisji między kolejnymi retransmisjami). Klient wysyła do każdej retransmisji coś, co wygląda na prawidłowe ACK TCP, ale zdalny koniec nadal okresowo przesyła ten sam segment TCP. To rozszerza się w nieskończoność i przeciągnięcia połączenia. Moje pytanie brzmi:

  • Czy ktoś ma jakieś zalecenia dotyczące rozwiązywania problemów i / lub określania podstawowej przyczyny problemu TCP? To tak, jakby zdalny koniec nie akceptował wiadomości ACK wysyłanych przez klienta VPN.

Jedną wspólną różnicą między węzłem CentOS a różnymi wydaniami Ubuntu jest to, że Ubuntu ma znacznie nowszą wersję jądra Linuksa (od 3.2 w Ubuntu 12.04 do 3.8 w 13.04). Wskaźnik do jakiegoś nowego błędu jądra? Zakładam, że gdyby tak było, to nie byłbym jedynym, który doświadcza problemu; Nie wydaje mi się, żeby było to szczególnie egzotyczne ustawienie.

Jason R.
źródło
Routing pakietów multiemisji przez tunsieć powinien być możliwy poprzez uruchamianie demonów routingu multiemisji (takich jak pimd ) i umożliwienie serwerowi OpenVPN korzystania z --topologyopcji ustawionych na „podsieć” - patrz instrukcja
kostix
Czy klient lub serwer VPN wskazuje coś w dziennikach w momencie wystąpienia tych problemów?
mgorven
@mgorven: Zdecydowanie nie na kliencie. Będę musiał popracować, aby uzyskać dzienniki serwera.
Jason R
@mgorven: W końcu miałem okazję do tego wrócić. Gdy tak się dzieje, w dziennikach klienta lub serwera nic nie ma. To naprawdę zaskakujące.
Jason R
1
Czy jest jakaś możliwość, że klienci, którzy zamrażają, mają lokalne zapory ogniowe, które upuszczają pakiety potrzebne do fragmentacji ICMP, a gdzie te, które tego nie robią, nie robią i dlatego fragmentują poprawnie?
MadHatter obsługuje Monikę

Odpowiedzi:

10

To polecenie rozwiązuje to dla mnie:

$ sudo ip link set dev tun0 mtu 1350 && echo ":)"

Możesz zweryfikować ustawienia tun0 za pomocą

$ ip a s

Twoje zdrowie!

Sebastián A. La Spina
źródło
Po stronie klienta czy serwera?
Matt
Wielkie dzięki! @Matt, zależy od tego, gdzie znajduje się problem. Dla nas było na serwerze, ale może być po stronie klienta. Również wartość może się różnić, możesz ją przetestować, ping <host> -s 1350 -M doaby znaleźć odpowiednią wartość
Eino Gourdin
2

Wyłącz skalowanie okien w TCP za pomocą:

sysctl -w net.ipv4.tcp_window_scaling=0

Po wykonaniu tej czynności SSH do systemów Debian / Ubuntu przez VPN działa dobrze dla mnie.

Mifpi
źródło
0

W systemie Windows za pomocą Putty musisz zmienić MTU, przechodząc do połączenia lokalnego dla połączenia VPN -> szczegóły interfejsu sieciowego (adapter Windows TAP lub coś w tym stylu) -> Zaawansowane -> Właściwości -> MTU (zmień na coś niższa niż 1500). Może być konieczne ponowne połączenie. To działało dla mnie w systemie Windows i Putty

Nick_K
źródło