Jag började utifrån, så som en användare skulle göra: skrev in namnet i telefonens webbläsare på mobildata och såg anslutningen hänga tills den tog timeout. Namnet löstes upp, så DNS var okej. Även hemrouterns port-forward-sida var en återvändsgränd, för dess WAN-adress var 100.64.31.42, och det är ingen adress som en operatör dirigerar till mig från internet. Den siffran förklarar hela felet: linjen ligger bakom carrier-grade NAT, så den publika adressen på min sida av tunneln tillhör operatören. Det som följer är vägen jag gick från den hängande fliken till en tjänst som svarar.

Börja hos klienten och arbeta inåt

Innan du ändrar någon regel, bevisa var kedjan stannar. På laptopen körde jag dig +short files.example.net och fick tillbaka VPS:ens adress, vilket uteslöt gammal DNS på min maskin. Sedan tog curl -v --connect-timeout 5 files.example.net:5022 timeout i stället för att nekas. Den skillnaden spelar roll: en timeout betyder oftast att paket tappas på vägen, medan ett nekande betyder att något svarade och sa nej.

Nästa hopp inåt var VPS:en själv. ss -ltnp visade inget som lyssnade på 5022, vilket var väntat innan DNAT-regeln fanns. På samma maskin bekräftade wg show (eller ip -br a show tun0 för OpenVPN) att hempeeren var uppe med en färsk handskakning. Är peeren nere hjälper ingen NAT-regel, och den gröna lampan på hemrouterns VPN-sida betyder ingenting.

Bekräfta att hemlinjen verkligen ligger bakom CGNAT

Jämför adressen som routern rapporterar på sitt WAN-gränssnitt med vad en extern tjänst ser. Allt i 100.64.0.0/10, alltså 100.64.x.x till 100.127.x.x, är shared address-området från RFC 6598 och går inte att nå från internet. Du kommer till samma slutsats när routern påstår en vanlig privat adress och en publik uppslagning ger något orelaterat. En CGNAT-linje kan också komma med en publik adress som bara håller till nästa lease, så att en port forward verkar fungera i en timme och sedan tystnar.

Vissa operatörer delar faktiskt ut en riktig publik adress men blockerar inkommande 80 och 443 på privatabonnemang. Är din tjänst enbart webb och WAN-adressen verkligen publik, fråga supporten innan du bygger en relay. Är den inte det gäller designen nedan för varje port lika, och det är värt att avsluta experimentet på routersidan: translatom i operatörens nät avslutar anslutningen innan den någonsin når ditt WAN-gränssnitt.

Peka namnet mot VPS:ens adress

DNS vidarebefordrar ingen trafik, så A-posten för tjänsten måste innehålla VPS:ens publika adress. En A-post mot 192.168.1.20 löses bara användbart upp för klienter som redan är inne i VPN:en; från internet löses den upp till en adress som ingen kan dirigera. För VPS:ens egen adminåtkomst håller jag ett separat namn, så att jag aldrig blandar ihop vilken värd en post pekar på.

Om både VPS:en och hemmaboxen serverar HTTP, ge var och en sitt eget namn och låt VPS:en avgöra vem som svarar. Att vika ihop dem till ett namn och hoppas att proxyn väljer rätt backend är precis så du felsöker fel värd en eftermiddag.

DNAT:a en port, lämna SSH på 22

Det direkta alternativet är destination NAT på VPS:en. Slå på forwarding för den körande kärnan och behåll hemserverns tunneladress i regeln, inte dess LAN-adress:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -p tcp -d 198.51.100.10 --dport 5022 -j DNAT --to-destination 10.8.0.2

Låt SSH till VPS:en själv stanna på 22 och forwarda en annan port, till exempel 5022, till hemmaskinen. Forwardar du 22 till en box som är nere förlorar du den enda vägen som hade kunnat laga den. Samma logik gäller proxyn: håll VPS:ens hanteringsport utanför relay-reglerna.

Gör reglerna beständiga när de fungerar. På Debian eller Ubuntu skriver apt install iptables-persistent och sedan netfilter-persistent save dem till /etc/iptables/rules.v4. På en firewalld-värd är motsvarigheten en permanent forward-port på zonen, som behöver firewall-cmd --reload innan den gäller. Regler som bara lever i minnet försvinner vid leverantörens första underhållsreboot, oftast vid en dålig timme.

Laga returvägen, eller slippa behöva den

DNAT skriver bara om destinationen. Hemservern ser en anslutning från den ursprungliga klientadressen, och om dess default route pekar på hemroutern lämnar svaret huset via WAN:en där operatörens translatom tappar det. Den asymmetrin var det andra felet jag råkade ut för, efter att DNAT-regeln såg helt korrekt ut.

Två åtgärder fungerar. Ge hemmaboxen en policy-route så att trafik från tunneln går tillbaka genom tunneln:

ip rule add from 10.8.0.2 table 100
ip route add default dev wg0 table 100

Eller låt VPS:en skriva om källan så att svaret har en adress den kan nå, och låt conntrack vända tillbaka det på vägen ut:

iptables -t nat -A POSTROUTING -d 10.8.0.2 -p tcp --dport 5022 -j SNAT --to-source 10.8.0.1

SNAT-varianten döljer den riktiga klientadressen för hemservern, så applikationsloggarna visar 10.8.0.1 som peer. Skicka vidare originaladressen på applikationslagret, eller acceptera att loggning per klient går förlorad, men bestäm det medvetet i stället för att upptäcka det under en incident.

Kontrollera hela vägen utifrån

Verifiera från ett nät som varken är VPS:en eller huset: en telefon på mobildata, eller ett billigt skal någon annanstans. nc -vz files.example.net 5022 bör rapportera en lyckad anslutning, och openssl s_client -connect files.example.net:443 -servername files.example.net bör visa certifikatet för det publika namnet. Kontrollera sedan leverantörens security group eller molnbrandvägg. En DNAT-regel som aldrig ser ett paket blockeras oftast ett lager ovanför värden.

Till sist: bestäm vad som händer när tunneln faller. En DNAT-regel fortsätter ta emot anslutningar och matar dem tyst in i en död tunnel, vilket ser precis ut som en trasig tjänst. En health check på VPS:en som nekar porten medan peeren är nere kostar några rader och sparar en timme gissande. Sluta sedan redigera regler och titta på det i ett dygn innan du litar på det.

Relaterade artiklar