Dynamiczne przekierowanie SSH jako proxy SOCKS ponad Twoim VPN
Aplikacja, która mówi tylko SOCKS, nie ma punktu końcowego proxy w zwykłym VPN. Dwa skoki, jeden odbiornik loopback i jedno wyszukanie nazwy, które serwer SSH musi wykonać sam.
Aplikacja, która mówi tylko SOCKS, nie ma z kim rozmawiać w zwykłym VPN, ponieważ tunel przenosi pakiety, a aplikacja chce punktu końcowego proxy. OpenSSH może zapewnić taki punkt, gdy właściciel dostępu na to pozwoli, ponieważ dynamiczne przekierowanie zamienia jedną sesję SSH w lokalne proxy. Potem są dwa skoki, które trzeba trzymać osobno: tunel docierający do hosta SSH i połączenie, które ten host otwiera dalej. Ich rozdzielenie wyjaśnia zarówno to, dlaczego układ działa, jak i to, czego nigdy nie zrobi.
Czym odbiornik SSH się staje, a czym nie
Dynamiczne przekierowanie każe klientowi SSH nasłuchiwać lokalnie i mówić SOCKS4 lub SOCKS5 do wszystkiego, co się połączy. Każde żądanie nazywa cel, a serwer SSH otwiera dalsze połączenie, dlatego wyszukanie celu może odbyć się po drugiej stronie. To przekierowanie TCP na poziomie aplikacji, a nie VPN dla całego urządzenia. Nie przenosi żadnego powiązania UDP, ani ICMP, ani niczego dla aplikacji, które całkowicie ignorują ustawienia proxy. Skok z serwera SSH do aplikacji też nie leży w Twoim tunelu, co ma znaczenie, gdy cel przyjmuje ruch tylko ze znanych sieci.
Wymagania wstępne są realne: trasa do hosta SSH, autoryzowane konto, zweryfikowany klucz hosta serwera i zgoda na przekierowywanie. Żadnego z nich nie tworzy proxy, a ostatni zwykle brakuje jako pierwszy. Potwierdź wszystkie cztery, zanim zaczniesz diagnozować cokolwiek innego, bo z punktu widzenia klienta błąd wygląda tak samo, którego by nie brakowało.
Uruchom go na loopbacku z jawnym portem
Wybierz nieużywany port lokalny i przypisz go jawnie do loopbacku, zamiast pomijać adres. Trzy opcje poniżej istnieją każda z jednego powodu.
ssh -D 127.0.0.1:1080 -NT -o ControlPath=none -o ExitOnForwardFailure=yes \
[email protected]
-N pomija zdalne polecenie, a -T pomija pseudoterminal, więc sesja istnieje tylko po to, by przekierowywać. ExitOnForwardFailure każe klientowi zakończyć się, gdy odbiornika nie da się utworzyć, zamiast działać bez żądanego przekierowania. ControlPath=none trzyma sesję poza istniejącym połączeniem multipleksowanym, które mogłoby dodać własne przekierowania. Loopback trzyma odbiornik poza LAN-em, ale na współdzielonej maszynie nie jest to granica autoryzacji, bo inne lokalne procesy też mogą do niego dotrzeć. Dokumentacja klienta OpenSSH opisuje wszystkie te przełączniki, a ostrzeżenie o loopbacku wynika z tego, czym jest nasłuchujący gniazdo.
Wysyłaj nazwy przez proxy, a nie obok niego
Klient SOCKS5 może sam rozwiązać cel albo poprosić o to proxy, i ten wybór decyduje, który resolver odpowie. Z socks5h curl wysyła nazwę hosta przez proxy, więc wyszukanie odbywa się na serwerze SSH. Ze zwykłym socks5 laptop najpierw rozwiązuje, a podróżuje tylko połączenie, co po cichu niweczy sens, gdy nazwa jest wewnętrzna. Żądanie poniżej czyści też listę bez proxy, więc odziedziczona wartość NO_PROXY nie może poprowadzić go obok proxy.
curl -sS --noproxy '' --proxy socks5h://127.0.0.1:1080 https://app.corp.example/health
Walidacja certyfikatu i własne logowanie aplikacji nadal obowiązują, bo proxy nie zastępuje żadnego z nich. Zostają dwa wyszukania: laptop musi dotrzeć do hosta SSH dozwoloną ścieżką VPN i DNS, a serwer SSH musi sam rozwiązać nazwę aplikacji. To drugie można sprawdzić osobno, zanim jakikolwiek ruch przejdzie przez proxy.
ssh [email protected] getent hosts app.corp.example
Udowodnij jeden dozwolony cel, a potem zamknij sesję
Sprawdź cel, który polityka dopuszcza, i ten, który powinna odrzucić, bo działające przekierowanie dowodzi tylko, że odbiornik działa, i niczego więcej. Aplikacja widzi adres źródłowy wybierany przez serwer SSH, a to nie jest adres tunelu Twojego laptopa. Gdzie druga strona rejestruje połączenia według źródła, ta różnica jest pierwszą rzeczą do sprawdzenia, gdy żądanie zostanie odrzucone.
Zatrzymaj sesję przez proces, który nią zarządza, zamiast zabijać niepowiązaną powłokę. Potem potwierdź, że odbiornika nie ma, bo port, który nadal odpowiada, to sesja, której naprawdę nie zamknąłeś. Usuń tylko to ustawienie proxy, które wprowadziło to ćwiczenie, a resztę konfiguracji aplikacji zostaw w spokoju. Nienadzorowany terminal trzymający regułę przekierowania nie jest usługą, a stałe proxy wymaga zatwierdzonego cyklu życia, a nie zapomnianego okna.
ss -ltn | grep 1080
Awarie, których ten układ nie naprawi
Niektóre objawy wskazują wprost na powyższe granice, a wczesne ich rozpoznanie oszczędza popołudnie debugowania proxy. Tabela łączy to, co widzisz, z tym, co to zwykle oznacza. Wszystko w ostatniej kolumnie jest pytaniem o projekt, a nie błędem konfiguracji.
| What you see | What it usually means | Where to look |
|---|---|---|
| The app connects and nothing follows | It ignores proxy settings entirely | Its own network settings, not the SSH session |
| A name resolution error for the destination | The SSH server cannot resolve it | Server resolver and search domains |
| A UDP-only application fails | Dynamic forwarding carries TCP only | This arrangement cannot serve it |
| curl works, the browser does not | The browser is not using the socks5h endpoint | Browser proxy configuration |
| The listener answers after the session ended | Another process owns port 1080 | The ss output, then the owning process |
Pierwsze trzy wiersze to te, które ludzie diagnozują źle, bo każdy daje próbę połączenia, a nie błąd dotyczący samego proxy. Nazwa, która rozwiązuje się na laptopie, nic nie mówi o resolverze serwera, a awaria jest czytana jako problem z certyfikatem lub przekroczeniem czasu. Aplikacje tylko z UDP stoją poza projektem, a nie zepsute w jego wnętrzu, i żadna dodatkowa opcja ssh tego nie zmienia. Wiersz o przeglądarce to zwykłe przypomnienie, że ustawienia proxy dotyczą każdej aplikacji osobno. Ostatni wiersz jest powodem, dla którego istnieje kontrola zamknięcia: port, który nadal nasłuchuje, oznacza, że teraz należy do czegoś innego.