OpenVPN per SOCKS5: suderinkite versiją, transportą ir DNS
SOCKS grandinė sugenda, kai proxy versija, transportas ar DNS kelias nesutampa. Naudokite SOCKS5, perneškite TCP ir laikykite grandinę namespace aplinkoje.
Vienas išėjimas iš šios darbo stoties yra SOCKS proxy, o už jo esantis OpenVPN praneša apie prisijungimo skirtąjį laiką be jokios naudingos informacijos. Naršyklė tame pačiame kompiuteryje veikia per tą proxy, prisijungimo duomenys teisingi, o prievadas atsako. Trys dalykai pakankamai dažnai skiriasi, kad juos reikėtų patikrinti pirmiausia: proxy kalbama SOCKS versija, kliento pasirinktas transportas ir kur vyksta vardų sprendimas. Patvirtinkite kiekvieną iš jų, prieš nuspręsdami, kad kalta užkarda.
Suderinkite SOCKS versiją prieš užkardą
Bendruomenės OpenVPN kalba SOCKS5, skirtą socks-proxy. Nukreipkite jį į proxy, kuris siūlo tik SOCKS4: TCP ryšys atsidaro, o tada sustoja, nes klientas laukia atsakymo į pasveikinimą, kurio kita pusė niekada neapdoroja. Iš išorės tas sustojimas atrodo lygiai kaip filtruojamas prievadas, todėl versijos klausimas kyla prieš bet kurią užkardos taisyklę. SOCKS suprantanti užklausa tai išsprendžia viena komanda.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
Baigta užklausa įrodo du dalykus iš karto: proxy priėmė SOCKS užklausą ir išsprendė vardą. URL schemos nereikia, nes curl pliką hostą traktuoja kaip HTTP, ko šiam testui pakanka.
Ta užklausa taip pat atmeta gedimą, kurį slepia kliento žurnalas. Proxy gali leisti naršyklę ir vis tiek atmesti VPN paskirties vietą; tokiu atveju atmetimas įvyksta ties CONNECT, prieš bet kokią VPN autentifikaciją. OpenVPN praneša tik apie skirtąjį laiką, todėl paties proxy atsakymas yra reikalingas įrodymas.
Transportas turi būti TCP abiejose pusėse
SOCKS5 čia perneša TCP srautą, todėl pačiam tuneliui reikia proto tcp-client. Profilis, vis dar nustatytas UDP, šiuo keliu neveiks, nes klientas nenaudoja protokolo UDP susiejimo režimo. Profilio pakeitimas yra tikras pokytis, o ne formalumas: kita pusė turi klausytis TCP tame pačiame prievade. Tada naudingoji apkrova tampa TCP TCP viduje, kur prarastas segmentas persiunčiamas du kartus ir tempas blogėja, ką interaktyvios sesijos pastebi daug labiau nei dideli perdavimai.
proto tcp-client
remote gw.lab.example 8443
socks-proxy 127.0.0.1 9050
Direktyva priima proxy hostą, pasirenkamą prievadą ir pasirenkamą prisijungimo duomenų failą. Įdėkite juos į patį profilį, kad kopija kitur elgtųsi identiškai.
Apribokite visą grandinę vienu konteineriu
Daryti grandinę hoste reiškia perimti jo numatytąjį maršrutą ir palikti resolverį būsenoje, kurios vėliau niekas negalės paaiškinti. Namespace arba konteineris tai apriboja, todėl hostas išlaiko savo kelią, o SOCKS šuolis ir tunelis gyvena kartu. Viduje niekas neįsijungia be tunelio įrenginio, teisių jį konfigūruoti ir pasiekiamo proxy. Compose paslauga tai gauna su cap_add: NET_ADMIN ir bind prijungtu /dev/net/tun.
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
Ši pora yra siauresnė nei konteinerio paleidimas su privilegijomis, ir tai yra visa reikalinga prieiga prie įrenginio. Klausytoją gali suteikti Tor klientas arba atskiras proxy konteineris. Abiem atvejais pririškite jį prie loopback ir pasiekite iš namespace per hostą, o ne atidengdami proxy tinklui.
Vardų sprendimas yra ten, kur izoliacija žlunga
Tunelis, kuris perneša paketus ir klausia hosto resolverio, nieko neišizoliavo. Du dalykai daro izoliaciją tikrą: namespace turi savo resolverį, o jo užklausos keliauja per proxy arba tunelį, niekada per fizinį sąsają. Testui naudokite du vardus: vieną, kuris egzistuoja tik už tunelio, ir viešą, kuris turėtų eiti tuo pačiu keliu.
docker compose exec vpn cat /etc/resolv.conf
docker compose exec vpn getent hosts internal.lab.example
Jei tolimosios pusės vardas išsprendžiamas, o viešas ne, grandinė yra selektyvi, o ne sulaužyta, ir skirtumas pasako, kurį kelią ėjo kiekviena užklausa. Jei abu išsprendžiami iš hosto, bet nė vienas konteinerio viduje, konteineris vis dar skolinasi hosto resolverį. Užsirašykite rastą resolverio failą, nes tai yra nustatymas, kurį reikia pakeisti.
Įrodykite kiekvieną šuolį iš eilės
Sąrašas trumpas. SOCKS5 užklausa gauna atsakymą, tunelis per proxy pasiekia savo klausytoją, o paketai, paliekantys namespace, neša adresą, kurio tikisi tolimoji pusė. Patvirtinkite kiekvieną atskirai, o ne sluoksniuodami daugiau konfigūracijos. Kai klientas sako prisijungęs, o niekas nejuda, lūžis beveik visada yra antrame ar trečiame fakte.
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
Užsirašykite veikusią kombinaciją: SOCKS versija, transportas, resolveris ir namespace nustatymai. Šios grandinės sprendimas antrą kartą iš atminties kainuoja daugiau nei užrašas. Laikykite tuos keturis faktus biliete, o ne pokalbio gijoje.
Grandinė, kuri praneša apie prisijungimą ir nieko nepraleidžia, paprastai sugenda tame šuolyje, kurio dar neįrodėte. Išbandykite tą šuolį prieš pridėdami dar vieną sluoksnį.