Zelfs een laptop achter de NAT van de provider kan een collega bedienen, zolang de VPN-server als ontmoetingspunt fungeert. Twee mechanismen komen daar: de client kiest naar buiten en vraagt de server een luisterende poort vast te houden, of de server publiceert een poort en vertaalt die de tunnel in. Beide lossen hetzelfde bereikbaarheidsprobleem op en gedragen zich anders bij uitval, toezicht en logging. Drie voorwaarden bepalen welke in je opstelling thuishoort.

Twee vormen, een ontmoetingspunt

In de eerste vorm opent de client een SSH-sessie naar buiten en vraagt de server op een gekozen poort te luisteren, waarbij elke verbinding via die sessie teruggaat. Op de server wordt niets doorgestuurd en er vindt geen pakketvertaling plaats, dus de enige vereisten zijn een SSH-account, een toegestane doorstuurt en een firewallregel voor de poort. De dienst blijft gebonden aan loopback op de client, wat meestal is wat je wilt.

ssh -N -R 8081:127.0.0.1:8080 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 [email protected]

In de tweede vorm bezit de server de openbare poort en herschrijft elke verbinding naar het tunneladres van de client. Dat vereist ingeschakelde IP-doorsturing, een bestemmingsvertaling aan de inkomende kant en een bronvertaling aan de uitgaande kant, en het blijft werken wanneer er geen SSH-sessie is. De poort is van de server en niet van een sessie, en dat is de eigenschap die de meeste praktijkgevallen beslist.

Geen van beide vormen is van zichzelf veiliger. Beide stellen een dienstpoort bloot aan iedereen die het openbare adres van de server kan bereiken, en beide blijven afhankelijk van de eigen authenticatie van de dienst.

Voorwaarde een: moet de poort langer leven dan de sessie

Een omgekeerde doorstuurt leeft precies zo lang als de SSH-sessie die hem heeft gemaakt. Als de verbinding wegvalt, verdwijnt de luisteraar en ziet de collega een geweigerde verbinding in plaats van een traag pad. Toezicht op het commando met een systemd-unit en een herstartbeleid lost dat op, en ExitOnForwardFailure=yes maakt een mislukte binding meteen zichtbaar in plaats van een sessie zonder doorstuurt achter te laten.

Een vertaalde poort overleeft herstarts als de regels worden bewaard, maar hij hangt ervan af dat de client hetzelfde tunneladres houdt. Een dynamische pool die de laptop na opnieuw verbinden een ander adres geeft, wijst de regel stil naar niets. Reserveer eerst het tunneladres, schrijf dan de regel, en behandel beide als een wijziging.

Als de dienst om drie uur 's nachts moet antwoorden zonder dat iemand kijkt, is de vorm met de door de server gepubliceerde poort degene met de minste bewegende delen, omdat het enige proces dat moet blijven draaien de tunnel zelf is.

Voorwaarde twee: van wie zijn de firewall en de logboeken

De omgekeerde vorm houdt al het beleid op twee plaatsen. sshd beslist via AllowTcpForwarding of doorschakelingen op afstand ueberhaupt zijn toegestaan, en GatewayPorts beslist of de luisteraar aan loopback of aan elk adres bindt. Met de standaardwaarde no kan een collega buiten de server de poort niet bereiken ook al is de doorstuurt gelukt, en dat ziet eruit als een kapotte tunnel terwijl het in werkelijkheid een bindadres is.

sudo ss -ltn '( sport = :8081 )'
sudo grep -E '^(GatewayPorts|AllowTcpForwarding)' /etc/ssh/sshd_config

De vertaalde vorm vereist ingeschakelde doorsturing en twee regels, en de tweede regel is waar de meeste recepten fout gaan. De bronvertaling beperken tot de conntrack-toestand DNAT betekent dat alleen de verbindingen die de bestemmingsregel heeft gemaakt worden herschreven, in plaats van elk pakket dat de server de tunnel in stuurt.

sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8081 -j DNAT --to-destination 10.88.0.6:8080
sudo iptables -t nat -A POSTROUTING -o tun0 -m conntrack --ctstate DNAT -j SNAT --to-source 10.88.0.1

Die herschrijving vernietigt ook de toerekening. Daarna ziet de client elke aanroeper als het tunneladres van de server, wat elke snelheidslimiet per adres in een emmer samenvat en verbergt wie wat heeft gestuurd. Als toerekening ertoe doet, beeindig de verbinding dan op de server of houd de toestemmingsbeslissing daar en geef een identiteit door in een header die de dienst vertrouwt. Kiezen tussen die twee oplossingen hangt ervan af of de dienst ueberhaupt een proxy-header leest.

Voorwaarde drie: een poort of veel, en van wie is de naam

Een dienst op een poort is het geval waarin de omgekeerde doorstuurt op inspanning wint. Je hebt een commando, een account en een firewallregel nodig, en opruimen is de sessie beeindigen. Meerdere diensten op hetzelfde openbare adres duwen je naar de door de server gepubliceerde vorm, omdat elke omgekeerde doorstuurt zijn eigen serverpoort nodig heeft en de verzameling met elke dienst groeit.

Namen maken het ingewikkelder. Een omgekeerde doorstuurt kan achter een TCP-proxy zitten die op SNI routeert, terwijl een vertaalde poort meestal een poort per dienst is. Als de dienst zelf TLS beeindigt en de oorspronkelijke hostnaam nodig heeft, behoudt de proxy-aanpak die en behoudt de DNAT-aanpak die alleen als de dienst die naam op die poort accepteert.

Schrijf op welke van de drie voorwaarden de vorm heeft bepaald. Anders zal de volgende persoon die een tweede dienst toevoegt dezelfde vergelijking met minder context opnieuw openen.

Beslis en test dan van buitenaf

Test het pad vanaf een netwerk dat geen route naar de laptop heeft, en kijk naar de tellers op de server terwijl het verzoek loopt. Testen vanaf de server naar zijn eigen openbare adres bewijst hier niets, omdat het pakket lokaal ontstaat en nooit de inkomende vertaalhaak bereikt, dus de test kan slagen terwijl het echte pad kapot is.

sudo iptables -t nat -L PREROUTING -n -v
sudo tcpdump -ni any 'tcp port 8081' -c 20

Tellers die vlak blijven betekenen dat het pakket de regel nooit heeft bereikt, wat op de provider of de hostfirewall wijst. Tellers die bewegen terwijl de dienst weigert, wijzen op de eigen firewall van de client of het adres waarop de dienst luistert. Een tunnel die het pakket draagt maar niets teruggeeft, is een route- of terugwegprobleem, en geen van deze drie uitkomsten mag worden opgelost door de clientadapter te bewerken. Schrijf op welke teller bewoog voordat je iets verandert, want de volgende test heeft die basislijn nodig.

Als de vorm eenmaal werkt, leg dan de poort, de eigenaar en de toezichtmethode vast naast de tunnelconfiguratie. Een bereikbaarheidsoplossing die alleen in iemands shellgeschiedenis bestaat, is een herstart verwijderd van een herhaald incident.

Gerelateerde artikelen