OpenVPN przez SOCKS5: zgodność wersji, transportu i DNS
Łańcuch SOCKS zawodzi, gdy wersja proxy, transport lub ścieżka DNS się nie zgadzają. Dopasuj SOCKS5, przenoś TCP i trzymaj łańcuch w jednej przestrzeni nazw.
Jedna z dróg wyjścia z tej stacji roboczej to proxy SOCKS, a OpenVPN za nim zgłasza przekroczenie czasu połączenia bez żadnych użytecznych szczegółów. Przeglądarka na tej samej maszynie działa przez to proxy, dane logowania są poprawne, a port odpowiada. Trzy rzeczy różnią się dość często, by sprawdzić je najpierw: wersja SOCKS, którą mówi proxy, transport wybrany przez klienta oraz miejsce, w którym odbywa się rozwiązywanie nazw. Potwierdź każdą z nich, zanim oskarżysz zaporę sieciową.
Dopasuj wersję SOCKS przed zaporą sieciową
Community OpenVPN mówi SOCKS5 dla socks-proxy. Skieruj go na proxy oferujące tylko SOCKS4, a połączenie TCP otworzy się i zawiśnie, bo klient czeka na odpowiedź na powitanie, którego druga strona nigdy nie analizuje. Z zewnątrz to zawieszenie wygląda dokładnie jak filtrowany port, dlatego pytanie o wersję pojawia się przed każdą regułą zapory. Jedno pobranie ze znajomością SOCKS rozstrzyga to jedną komendą.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
Zakończone żądanie dowodzi dwóch rzeczy naraz: proxy przyjęło żądanie SOCKS i rozwiązało nazwę. Schemat URL nie jest potrzebny, bo curl traktuje goły host jako HTTP, i to wystarcza do tego testu.
To pobranie wyklucza też awarię, którą ukrywa dziennik klienta. Proxy może zezwolić przeglądarce i mimo to odmówić miejscu docelowemu VPN, a wtedy odmowa następuje na CONNECT, przed jakimkolwiek uwierzytelnianiem VPN. OpenVPN zgłasza tylko przekroczenie czasu, więc własna odpowiedź proxy jest dowodem, którego potrzebujesz.
Transport musi być TCP po obu stronach
SOCKS5 przenosi tu strumień TCP, więc sam tunel potrzebuje proto tcp-client. Profil wciąż ustawiony na UDP nie zadziała tą drogą, bo klient nie używa trybu skojarzenia UDP tego protokołu. Przełączenie profilu to prawdziwa zmiana, a nie formalność: druga strona musi nasłuchiwać TCP na tym samym porcie. Potem ładunek staje się TCP w TCP, gdzie utracony segment jest wysyłany ponownie dwa razy i tempo spada, co sesje interaktywne odczuwają znacznie mocniej niż duże transfery.
proto tcp-client
remote gw.lab.example 8443
socks-proxy 127.0.0.1 9050
Ta dyrektywa przyjmuje host proxy, opcjonalny port i opcjonalny plik danych logowania. Umieść je w samym profilu, żeby kopia zachowywała się tak samo gdzie indziej.
Zamknij cały łańcuch w jednym kontenerze
Robienie łańcucha na hoście oznacza przejęcie jego trasy domyślnej i pozostawienie resolvera w stanie, którego nikt później nie wyjaśni. Przestrzeń nazw lub kontener ograniczają go zamiast tego, więc host zachowuje własną ścieżkę, a skok SOCKS i tunel żyją razem. W środku nic nie wstanie bez urządzenia tunelowego, praw do jego konfiguracji i osiągalnego proxy. Usługa Compose dostaje to z cap_add: NET_ADMIN i bind-montowanym /dev/net/tun.
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
Ta para jest węższa niż uruchamianie kontenera z pełnymi uprawnieniami, i to cały potrzebny dostęp do urządzenia. Klient Tor lub osobny kontener proxy może dostarczyć nasłuchującego. W obu przypadkach przypnij go do loopback i docieraj do niego z przestrzeni nazw przez host, zamiast wystawiać proxy do sieci.
Rozwiązywanie nazw to miejsce, w którym zawodzi izolacja
Tunel, który przenosi pakiety, a jednocześnie pyta resolver hosta, niczego nie odizolował. Dwie rzeczy czynią izolację prawdziwą: przestrzeń nazw ma własny resolver, a jego zapytania idą przez proxy lub tunel, nigdy przez interfejs fizyczny. Do testu użyj dwóch nazw: jednej istniejącej tylko za tunelem i drugiej publicznej, która powinna iść tą samą drogą.
docker compose exec vpn cat /etc/resolv.conf
docker compose exec vpn getent hosts internal.lab.example
Jeśli nazwa po drugiej stronie się rozwiązuje, a publiczna nie, łańcuch jest wybiórczy, a nie zepsuty, i różnica mówi, którą drogą poszło każde zapytanie. Jeśli obie rozwiązują się z hosta, ale żadna wewnątrz kontenera, kontener wciąż pożycza resolver hosta. Zapisz znaleziony plik resolvera, bo to jest ustawienie, które trzeba zmienić.
Udowodnij każdy skok po kolei
Lista jest krótka. Żądanie SOCKS5 dostaje odpowiedź, tunel dociera do nasłuchującego przez proxy, a pakiety opuszczające przestrzeń nazw niosą adres, którego oczekuje druga strona. Potwierdzaj po jednym, zamiast dokładać konfigurację. Gdy klient mówi „połączono”, a nic się nie rusza, zerwanie jest prawie zawsze w drugim lub trzecim fakcie.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
docker compose exec vpn ip route get 203.0.113.10
docker compose exec vpn getent hosts internal.lab.example
Zapisz kombinację, która zadziałała: wersja SOCKS, transport, resolver i ustawienia przestrzeni nazw. Rozwiązywanie tego łańcucha drugi raz z pamięci kosztuje więcej niż notatka. Trzymaj te cztery fakty w zgłoszeniu, a nie w czacie.
Łańcuch, który zgłasza „połączono” i nic nie przepuszcza, zwykle zawiódł na skoku, którego jeszcze nie udowodniłeś. Sprawdź ten skok, zanim dodasz kolejną warstwę.