Dalsze działania: wygląda na to, że szybka seria rozłączeń zbiegająca się z kilkumiesięcznym uruchomieniem każdego serwera jest prawdopodobnie przypadkowa i służy jedynie ujawnieniu faktycznego problemu. Powodem, dla którego nie udało się ponownie połączyć, jest prawie na pewno wartość AliveInterval (odpowiedź kasperda). Użycie opcji ExitOnForwardFailure powinno pozwolić na prawidłowe przekroczenie limitu czasu przed ponownym połączeniem, co w większości przypadków powinno rozwiązać problem. Sugestia MadHattera (skrypt zabicia) jest prawdopodobnie najlepszym sposobem, aby upewnić się, że tunel może się ponownie połączyć, nawet jeśli wszystko inne zawiedzie.
Mam serwer (A) za zaporą ogniową, który inicjuje tunel zwrotny na kilku portach do małego DigitalOcean VPS (B), dzięki czemu mogę połączyć się z A za pośrednictwem adresu IP B. Tunel działał konsekwentnie przez około 3 miesiące, ale nagle zawiódł cztery razy w ciągu ostatnich 24 godzin. To samo zdarzyło się jakiś czas temu u innego dostawcy VPS - miesiące doskonałej pracy, a potem nagle wiele szybkich awarii.
Mam skrypt na komputerze A, który automatycznie wykonuje polecenie tunelowania ( ssh -R *:X:localhost:X address_of_B
dla każdego portu X), ale gdy się wykonuje, mówi Warning: remote port forwarding failed for listen port X
.
Przechodzenie do sshd /var/log/secure
na serwerze pokazuje następujące błędy:
bind: Address already in use
error: bind: Address already in use
error: channel_setup_fwd_listener: cannot listen to port: X
Rozwiązanie wymaga ponownego uruchomienia VPS. Do tego czasu wszystkie próby ponownego połączenia powodują wyświetlenie komunikatu „nieudane przekierowanie portu” i nie będą działać. Teraz jest tak, że tunel trwa tylko około 4 godzin przed zatrzymaniem.
Nic się nie zmieniło na VPS, a jest to maszyna do jednorazowego użytku dla jednego użytkownika, która służy tylko jako punkt końcowy tunelu zwrotnego. Działa z OpenSSH_5.3p1 na CentOS 6.5. Wygląda na to, że sshd nie zamyka portów na swoim końcu, gdy połączenie zostanie zerwane. Nie potrafię wyjaśnić, dlaczego lub dlaczego tak się stanie nagle po miesiącach prawie idealnej pracy.
Aby to wyjaśnić, najpierw muszę dowiedzieć się, dlaczego sshd odmawia nasłuchiwania portów po awarii tunelu, co wydaje się być spowodowane tym, że sshd pozostawia porty otwarte i nigdy ich nie zamyka. To wydaje się być głównym problemem. Po prostu nie jestem pewien, co spowodowałoby, że zachowałby się w ten sposób po miesiącach zachowań zgodnych z oczekiwaniami (tj. Natychmiastowym zamknięciu portów i umożliwieniu skryptu ponownego połączenia).
źródło
Odpowiedzi:
Zgadzam się z MadHatter, że prawdopodobnie będą to przekierowania portów z niedziałających połączeń ssh. Nawet jeśli twój obecny problem okaże się czymś innym, możesz spodziewać się, że prędzej czy później natkniesz się na takie niedziałające połączenia ssh.
Istnieją trzy sposoby, w jakie mogą wystąpić takie niedziałające połączenia:
Ustalenie, które z powyższych trzech zdarzeń ma miejsce, nie jest bardzo ważne, ponieważ istnieje metoda, która zajmie się wszystkimi trzema. To jest użycie komunikatów podtrzymujących.
Powinieneś spojrzeć na
ClientAliveInterval
słowo kluczowe dlasshd_config
iServerAliveInterval
interwał dlassh_config
lub~/.ssh/config
.Uruchamianie
ssh
polecenia w pętli może działać poprawnie. Dobrym pomysłem jest wstawienie trybu uśpienia w pętlę, aby nie zalać serwera, gdy połączenie z jakiegoś powodu nie powiedzie się.Jeśli klient ponownie się połączy przed zakończeniem połączenia na serwerze, możesz skończyć w sytuacji, gdy nowe połączenie ssh jest aktywne, ale nie ma przekierowania portów. Aby tego uniknąć, musisz użyć
ExitOnForwardFailure
słowa kluczowego po stronie klienta.źródło
-o ExitOnForwardFailure yes
właśnie tego potrzebowałem. Więc to jedna mniejsza rzecz, którą muszę zrozumieć. Pomyślałem, że zamierzam napisać skrypt w języku Python, aby przeanalizować te komunikaty ostrzegawcze. To jest o wiele prostsze. : DExitOnForwardFailure
podczas pisania mojej odpowiedzi. Dodałem go teraz do odpowiedzi.-o ExitOnForwardFailure=yes
(zwróć uwagę na znak równości). Więc jeśli ktoś się z tym spotka, nie kopiuj i wklej z mojego poprzedniego komentarza, to nie zadziała. : PMożesz znaleźć proces, który wiąże port na tym serwerze
Wydaje się bardzo prawdopodobne, że jest to na wpół nieużywane
sshd
, ale po co zakładać, kiedy można mieć dane? Jest to również dobry sposób, aby skrypt znalazł PID do wysłania sygnału 9 przed ponownym uruchomieniem tunelu.źródło
Dla mnie, gdy
ssh
tunel się rozłącza, połączenie się resetuje, więcssh
proces nadal blokuje się, pozostawiając mnie bez aktywnych tuneli i nie wiem dlaczego. Rozwiązaniem tego problemu jest umieszczeniessh
w tle-f
i tworzenie nowych połączeń bez czekania na zresetowanie starych połączeń.-o ExitOnForwardFailure=yes
Mogą być wykorzystane do LIMT liczby nowych procesów.-o ServerAliveInterval=60
Poprawia niezawodność bieżącego połączenia.Możesz powtarzać
ssh
polecenie często, powiedzmy, wcron
pętli lub w pętli skryptu, na przykład w następujący sposób: uruchamiamyssh
polecenie co 3 minuty:źródło
-o ExitOnForwardFailure=yes
było to, czego szukałem, wielkie dzięki!Z mojego doświadczenia wynika, że ssh ma trochę irytujący zwyczaj nie wychodzenia czysto, jeśli „coś” nadal działa na zdalnym systemie. Np. Zaczął się w tle. Możesz to odtworzyć poprzez:
Twój ssh wyloguje się, ale tak naprawdę nie zamknie sesji - dopóki proces zdalny nie zakończy się (czego nie zrobi, ponieważ jest to pętla „while true”). Może się zdarzyć, że dzieje się coś podobnego - twoja sesja ma zablokowany proces, który jest spawnowany przez ssh. Port pozostaje w użyciu i dlatego nie może zostać ponownie wykorzystany przez proces lokalny.
źródło
ssh -o ConnectTimeout=10 -o BatchMode=yes -gnN -R *:X:localhost:X root@$TUNSRV 1>>tunnel.log 2>&1 &
więc nic nie jest wykonywane przez SSH poza samym tunelem, szczególnie z powodu opcji -N. Cokolwiek pozostaje otwarte, odbywa się na zdalnym serwerze B za pomocą samego sshd.