Udgiv en hjemmeserver via en VPS, når CGNAT blokerer porte
Vejen fra browser til hjemmeboks: bevis at linjen ligger bag CGNAT, peg DNS mod VPS'en, DNAT én port, ret returvejen og verificér udefra.
Jeg startede udefra, som en bruger ville gøre: skrev navnet i telefonens browser på mobildata og så forbindelsen hænge, indtil den timede ud. Navnet blev opløst, så DNS var i orden. Hjemmerouterens port-forward-side var også en blindgyde, for dens WAN-adresse var 100.64.31.42, og det er ikke en adresse, som en udbyder ruter til mig fra internettet. Det tal forklarer hele fejlen: linjen ligger bag carrier-grade NAT, så den offentlige adresse på min side af tunnelen tilhører udbyderen. Det følgende er den vej, jeg gik fra den hængende fane til en tjeneste, der svarer.
Start ved klienten og arbejd indad
Før du ændrer nogen regel, skal du bevise, hvor kæden stopper. På laptop'en kørte jeg dig +short files.example.net og fik VPS'ens adresse tilbage, hvilket udelukkede forældet DNS på min maskine. Derefter timede curl -v --connect-timeout 5 files.example.net:5022 ud i stedet for at blive afvist. Den forskel betyder noget: en timeout betyder som regel, at pakker bliver tabt undervejs, mens en afvisning betyder, at noget svarede og sagde nej.
Næste hop indad var VPS'en selv. ss -ltnp viste intet, der lyttede på 5022, hvilket var ventet, før DNAT-reglen fandtes. På samme maskine bekræftede wg show (eller ip -br a show tun0 for OpenVPN), at hjemme-peeren var oppe med et frisk handshake. Er peeren nede, hjælper ingen NAT-regel, og den grønne lampe på hjemmerouterens VPN-side betyder intet.
Bekræft, at hjemmelinjen virkelig ligger bag CGNAT
Sammenlign den adresse, routeren rapporterer på sit WAN-interface, med det, en ekstern tjeneste ser. Alt i 100.64.0.0/10, altså 100.64.x.x til 100.127.x.x, er shared address-området fra RFC 6598 og kan ikke nås fra internettet. Du når samme konklusion, når routeren påstår en almindelig privat adresse, og et offentligt opslag returnerer noget ubeslægtet. En CGNAT-linje kan også komme med en offentlig adresse, der kun holder til næste lease, så en port forward ser ud til at virke en time og derefter stille dør.
Nogle udbydere giver faktisk en rigtig offentlig adresse, men blokerer indgående 80 og 443 på privatabonnementer. Er din tjeneste kun web, og er WAN-adressen virkelig offentlig, så spørg supporten, før du bygger en relay. Er den ikke, gælder designet nedenfor for hver port lige meget, og det er værd at stoppe eksperimentet på routersiden: translatoren i udbyderens net afslutter forbindelsen, før den nogensinde når dit WAN-interface.
Peg navnet mod VPS'ens adresse
DNS videresender ikke trafik, så A-recorden for tjenesten skal indeholde VPS'ens offentlige adresse. En A-record mod 192.168.1.20 opløses kun brugbart for klienter, der allerede er inde i VPN'en; fra internettet opløses den til en adresse, ingen kan rute. Til VPS'ens egen admin-adgang holder jeg et separat navn, så jeg aldrig forveksler, hvilken vært en record peger på.
Hvis både VPS'en og hjemmeboksen serverer HTTP, så giv hver sit eget navn og lad VPS'en afgøre, hvem der svarer. At folde dem sammen til ét navn og håbe, at proxyen vælger det rigtige backend, er netop sådan du fejlretter den forkerte vært en hel eftermiddag.
DNAT én port, lad SSH blive på 22
Den direkte mulighed er destination NAT på VPS'en. Slå forwarding til for den kørende kerne, og hold hjemmeserverens tunneladresse i reglen, ikke dens LAN-adresse:
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
Lad SSH til VPS'en selv blive på 22, og forward en anden port, for eksempel 5022, til hjemmemaskinen. Forwarder du 22 til en boks, der er nede, mister du den eneste vej, der kunne have rettet det. Samme logik gælder proxyen: hold VPS'ens administrationsport uden for relay-reglerne.
Gør reglerne permanente, når de virker. På Debian eller Ubuntu skriver apt install iptables-persistent og derefter netfilter-persistent save dem til /etc/iptables/rules.v4. På en firewalld-vært er modstykket en permanent forward-port på zonen, som kræver firewall-cmd --reload, før den gælder. Regler, der kun lever i hukommelsen, forsvinder ved udbyderens første vedligeholdelsesreboot, som regel på et dårligt tidspunkt.
Ret returvejen, eller undgå at få brug for den
DNAT omskriver kun destinationen. Hjemmeserveren ser en forbindelse fra den oprindelige klientadresse, og hvis dens default route peger på hjemmerouteren, forlader svaret huset via WAN'et, hvor udbyderens translator taber det. Den asymmetri var den anden fejl, jeg ramte, efter at DNAT-reglen så helt korrekt ud.
To rettelser virker. Giv hjemmeboksen en policy-route, så trafik fra tunnelen går tilbage gennem tunnelen:
ip rule add from 10.8.0.2 table 100
ip route add default dev wg0 table 100
Eller lad VPS'en omskrive kilden, så svaret har en adresse, den kan nå, og lad conntrack vende det tilbage på vejen ud:
iptables -t nat -A POSTROUTING -d 10.8.0.2 -p tcp --dport 5022 -j SNAT --to-source 10.8.0.1
SNAT-versionen skjuler den rigtige klientadresse for hjemmeserveren, så applikationsloggene viser 10.8.0.1 som peer. Send originaladressen videre på applikationslaget, eller accepter at miste logning per klient, men beslut det bevidst i stedet for at opdage det under en hændelse.
Tjek hele vejen udefra
Verificér fra et netværk, der hverken er VPS'en eller huset: en telefon på mobildata eller en billig shell et andet sted. nc -vz files.example.net 5022 bør rapportere en vellykket forbindelse, og openssl s_client -connect files.example.net:443 -servername files.example.net bør vise certifikatet for det offentlige navn. Tjek derefter udbyderens security group eller cloud-firewall. En DNAT-regel, der aldrig ser en pakke, blokeres som regel et lag over værten.
Til sidst: beslut, hvad der sker, når tunnelen falder. En DNAT-regel bliver ved med at tage imod forbindelser og fører dem stille ind i en død tunnel, hvilket ser præcis ud som en defekt tjeneste. Et health check på VPS'en, der afviser porten, mens peeren er nede, koster et par linjer og sparer en time med gætteri. Hold derefter op med at redigere regler og se på det i et døgn, før du stoler på det.