Dynamische SSH-doorsturing als SOCKS-proxy over je VPN
Een app die alleen SOCKS spreekt, heeft geen proxy-eindpunt op een gewone VPN. Twee sprongen, één loopback-listener en één naamopzoeking die de SSH-server zelf moet doen.
Een applicatie die alleen SOCKS spreekt, heeft niets om mee te praten op een gewone VPN, omdat de tunnel pakketten draagt en de app een proxy-eindpunt wil. OpenSSH kan dat eindpunt leveren wanneer de eigenaar van de toegang het toestaat, omdat dynamische doorsturing één SSH-sessie in een lokale proxy verandert. Daarna zijn er twee sprongen die apart moeten blijven: de tunnel die de SSH-host bereikt, en de verbinding die die host daarna opent. Ze scheiden verklaart zowel waarom de regeling werkt als wat ze nooit zal doen.
Wat de SSH-listener wel en niet wordt
Dynamische doorsturing laat de SSH-client lokaal luisteren en SOCKS4 of SOCKS5 spreken met alles wat verbindt. Elk verzoek noemt een bestemming en de SSH-server opent de volgende verbinding, waardoor de opzoeking van de bestemming aan de overkant kan gebeuren. Dat is TCP-doorsturing op applicatieniveau, geen VPN voor het hele apparaat. Het draagt geen UDP-associatie, geen ICMP, en niets voor applicaties die proxy-instellingen volledig negeren. De sprong van de SSH-server naar de applicatie zit ook niet in je tunnel, wat telt wanneer de bestemming alleen verkeer van bekende netwerken aanvaardt.
De voorwaarden zijn echt: een route naar de SSH-host, een geautoriseerd account, een geverifieerde hostsleutel van de server en toestemming om door te sturen. Geen ervan wordt door de proxy gemaakt, en de laatste ontbreekt meestal het eerst. Bevestig alle vier voordat je iets anders debugt, want vanaf de client ziet de fout er hetzelfde uit, welke ook ontbreekt.
Start het op loopback met een expliciete poort
Kies een ongebruikte lokale poort en bind die expliciet aan loopback in plaats van het adres weg te laten. De drie opties hieronder bestaan elk om één reden.
ssh -D 127.0.0.1:1080 -NT -o ControlPath=none -o ExitOnForwardFailure=yes \
[email protected]
-N slaat het externe commando over en -T slaat de pseudoterminal over, zodat de sessie alleen bestaat om door te sturen. ExitOnForwardFailure laat de client afsluiten wanneer de listener niet gemaakt kan worden, in plaats van te draaien zonder de doorsturing die je vroeg. ControlPath=none houdt de sessie buiten een bestaande gemultiplextde verbinding die zijn eigen doorsturingen kan toevoegen. Loopback houdt de listener buiten het LAN, maar op een gedeelde machine is dat geen autorisatiegrens, omdat andere lokale processen hem ook kunnen bereiken. De referentie van de OpenSSH-client documenteert al deze opties, en de loopback-waarschuwing volgt uit wat een luisterende socket is.
Stuur namen door de proxy, niet eromheen
Een SOCKS5-client kan de bestemming zelf oplossen of de proxy vragen het te doen, en die keuze bepaalt welke resolver antwoordt. Met socks5h stuurt curl de hostnaam door de proxy, zodat de opzoeking op de SSH-server gebeurt. Met gewone socks5 lost de laptop eerst op en reist alleen de verbinding, wat het doel stil ondermijnt wanneer de naam intern is. Het verzoek hieronder maakt ook de lijst zonder proxy leeg, zodat een geërfde NO_PROXY-waarde het niet om de proxy heen kan leiden.
curl -sS --noproxy '' --proxy socks5h://127.0.0.1:1080 https://app.corp.example/health
Certificaatvalidatie en de eigen login van de applicatie gelden nog steeds, omdat de proxy geen van beide vervangt. Er blijven twee opzoekingen: de laptop moet de SSH-host bereiken via het toegestane VPN- en DNS-pad, en de SSH-server moet de applicatienaam zelf oplossen. De tweede is apart te testen voordat er verkeer door de proxy gaat.
ssh [email protected] getent hosts app.corp.example
Bewijs één toegestane bestemming en sluit dan de sessie
Test een bestemming die het beleid toestaat en een die het zou moeten weigeren, want een werkende doorsturing bewijst alleen dat de listener werkt en niets meer. De applicatie ziet het bronadres dat de SSH-server kiest, en dat is niet het tunneladres van je laptop. Waar de andere kant verbindingen op bron logt, is dat verschil het eerste dat je controleert wanneer een verzoek wordt geweigerd.
Stop de sessie via het proces dat hem bezit in plaats van een ongerelateerde shell te doden. Bevestig daarna dat de listener weg is, want een poort die nog antwoordt is een sessie die je niet echt hebt gesloten. Verwijder alleen de proxy-instelling die deze oefening heeft ingevoerd, en laat de rest van de applicatieconfiguratie met rust. Een onbeheerde terminal met een doorstuurregel is geen dienst, en een permanente proxy vereist een goedgekeurde levenscyclus, geen vergeten venster.
ss -ltn | grep 1080
Storingen die deze regeling niet kan oplossen
Sommige symptomen wijzen rechtstreeks op de grenzen hierboven, en ze vroeg herkennen bespaart een middag proxy-debuggen. De tabel koppelt wat je ziet aan wat het meestal betekent. Alles in de laatste kolom is een ontwerpvraag, geen configuratiefout.
| 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 |
De eerste drie rijen zijn degene die mensen verkeerd diagnosticeren, omdat elk een verbindingspoging oplevert in plaats van een fout over de proxy zelf. Een naam die op de laptop oplost zegt niets over de resolver van de server, en de storing wordt in plaats daarvan gelezen als een certificaat- of timeoutprobleem. Applicaties met alleen UDP staan buiten het ontwerp, niet erbinnen kapot, en geen extra ssh-optie verandert dat. De browserrij is de gebruikelijke herinnering dat proxy-instellingen per applicatie gelden. De laatste rij is de reden dat de afsluitcontrole bestaat: een poort die nog luistert betekent dat iets anders hem nu bezit.