Eén route naar buiten vanaf dit werkstation is een SOCKS-proxy, en OpenVPN erachter meldt een verbindingstime-out zonder enige bruikbare informatie. De browser op dezelfde machine werkt via die proxy, de inloggegevens kloppen en de poort antwoordt. Drie dingen verschillen vaak genoeg om eerst te controleren: de SOCKS-versie die de proxy spreekt, het transport dat de client koos en de plek waar naamresolutie plaatsvindt. Bevestig elk daarvan voordat u de firewall de schuld geeft.

Stem de SOCKS-versie af vóór de firewall

Community OpenVPN spreekt SOCKS5 voor socks-proxy. Wijs het naar een proxy die alleen SOCKS4 biedt en de TCP-verbinding opent en stokt, omdat de client wacht op antwoord op een begroeting die de andere kant nooit parseert. Van buiten lijkt die stilstand precies op een gefilterde poort, daarom komt de versievraag vóór elke firewallregel. Eén ophaalactie met SOCKS-kennis beslecht het met één commando.

curl --socks5-hostname 127.0.0.1:9050 gw.lab.example

Een voltooid verzoek bewijst twee dingen tegelijk: de proxy accepteerde het SOCKS-verzoek en hij loste de naam op. Er is geen URL-schema nodig, omdat curl een kale host als HTTP behandelt, en dat is genoeg voor deze test.

Die ophaalactie sluit ook het falen uit dat het clientlog verbergt. Een proxy kan de browser toestaan en de VPN-bestemming alsnog weigeren, en dan gebeurt de weigering bij CONNECT, vóór enige VPN-authenticatie. OpenVPN meldt alleen een time-out, dus het eigen antwoord van de proxy is het bewijs dat u nodig hebt.

Het transport moet aan beide kanten TCP zijn

SOCKS5 draagt hier een TCP-stream, dus de tunnel zelf heeft proto tcp-client nodig. Een profiel dat nog op UDP staat werkt niet via dit pad, omdat de client de UDP-associatiemodus van het protocol niet gebruikt. Het profiel omzetten is een echte wijziging en geen formaliteit: de andere kant moet op TCP op dezelfde poort luisteren. Daarna wordt de lading TCP in TCP, waar een verloren segment twee keer opnieuw wordt verzonden en het tempo verslechtert, wat interactieve sessies veel sterker merken dan grote overdrachten.

proto tcp-client
remote gw.lab.example 8443
socks-proxy 127.0.0.1 9050

De richtlijn neemt de proxyhost, een optionele poort en een optioneel inloggegevensbestand. Zet die in het profiel zelf, zodat een kopie elders zich hetzelfde gedraagt.

Sluit de hele keten op in één container

De keten op de host doen betekent de standaardroute overnemen en de resolver achterlaten in een staat die niemand later kan verklaren. Een namespace of container begrenst hem in plaats daarvan, zodat de host zijn eigen pad houdt terwijl de SOCKS-hop en de tunnel samen leven. Binnen komt niets op zonder tunnelapparaat, rechten om dat apparaat te configureren en een bereikbare proxy. Een Compose-service krijgt dat met cap_add: NET_ADMIN en een bind-gemounte /dev/net/tun.

cap_add:
  - NET_ADMIN
devices:
  - /dev/net/tun:/dev/net/tun

Dat paar is smaller dan de container privileged draaien, en het is de hele benodigde apparaattoegang. Een Tor-client of een aparte proxycontainer kan de luisteraar leveren. Bind het in beide gevallen aan loopback en bereik het vanuit de namespace via de host in plaats van de proxy aan het netwerk bloot te stellen.

Naamresolutie is waar de isolatie faalt

Een tunnel die pakketten draagt maar toch de resolver van de host vraagt, heeft niets geïsoleerd. Twee dingen maken de isolatie echt: de namespace heeft een eigen resolver, en de query's gaan via de proxy of de tunnel, nooit over de fysieke interface. Gebruik twee namen voor de test: een die alleen achter de tunnel bestaat en een publieke die hetzelfde pad zou moeten volgen.

docker compose exec vpn cat /etc/resolv.conf
docker compose exec vpn getent hosts internal.lab.example

Als de naam aan de andere kant wordt opgelost en de publieke niet, is de keten selectief in plaats van stuk, en het verschil vertelt welk pad elke query nam. Als beide vanaf de host worden opgelost maar geen enkele binnen de container, leent de container nog steeds de resolver van de host. Noteer het resolverbestand dat u vond, want dat is de instelling die moet veranderen.

Bewijs elke hop op volgorde

De lijst is kort. Een SOCKS5-verzoek krijgt antwoord, de tunnel bereikt zijn luisteraar via de proxy en pakketten die de namespace verlaten dragen het adres dat de andere kant verwacht. Bevestig er één per keer in plaats van meer configuratie op te stapelen. Als de client verbonden zegt en niets beweegt, zit de breuk bijna altijd in het tweede of derde feit.

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

Schrijf de combinatie op die werkte: SOCKS-versie, transport, resolver en namespace-instellingen. Deze keten een tweede keer uit het geheugen oplossen kost meer dan de notitie. Houd die vier feiten in de ticket en niet in de chat.

Een keten die verbonden meldt en niets doorlaat, is meestal mislukt bij de hop die u nog niet hebt bewezen. Test die hop voordat u nog een laag toevoegt.

Gerelateerde artikelen