Pradėjau iš išorės, kaip tai darytų naudotojas: įvedžiau vardą telefono naršyklėje mobiliaisiais duomenimis ir žiūrėjau, kaip ryšys kabo, kol baigėsi laikas. Vardas išspręsdavo, taigi DNS buvo tvarkingas. Namų maršrutizatoriaus portų persiuntimo puslapis taip pat buvo aklavietė, nes jo WAN adresas rodė 100.64.31.42, o tai nėra adresas, į kurį tiekėjas mane maršrutizuoja iš interneto. Šis skaičius paaiškina visą gedimą: linija yra už carrier-grade NAT, todėl viešas adresas manojo tunelio pusėje priklauso tiekėjui. Toliau pateikiamas kelias, kurį nuėjau nuo tos pakibusios kortelės iki tarnybos, kuri atsako.

Pradėk nuo kliento ir eik į vidų

Prieš keisdamas bet kurią taisyklę, įrodyk, kur grandinė sustoja. Nešiojamame kompiuteryje paleidau dig +short files.example.net ir gavau VPS adresą atgal, o tai atmetė pasenusį DNS mano mašinoje. Tada curl -v --connect-timeout 5 files.example.net:5022 baigėsi laikas, o ne buvo atsisakyta. Šis skirtumas svarbus: laiko pabaiga dažniausiai reiškia, kad paketai metami kelyje, o atsisakymas reiškia, kad kažkas atsakė ir pasakė ne.

Kitas žingsnis į vidų buvo pats VPS. ss -ltnp nerodė nieko, kas klausytųsi 5022, ko ir tikėtasi iki DNAT taisyklės atsiradimo. Toje pačioje mašinoje wg show (arba ip -br a show tun0 OpenVPN atveju) patvirtino, kad namų peer veikia ir turi naują handshake. Jei peer neveikia, nė viena NAT taisyklė nepadės, o žalia lemputė namų maršrutizatoriaus VPN puslapyje nieko nereiškia.

Patvirtink, kad namų linija tikrai yra už CGNAT

Palygink adresą, kurį maršrutizatorius praneša savo WAN sąsajoje, su tuo, ką mato išorinė tarnyba. Viskas 100.64.0.0/10, tai yra nuo 100.64.x.x iki 100.127.x.x, yra bendrų adresų diapazonas iš RFC 6598 ir iš interneto nepasiekiamas. Prie tos pačios išvados prieisi, kai maršrutizatorius teigia turįs įprastą privatų adresą, o viešas patikrinimas grąžina kažką nesusijusio. CGNAT linija gali turėti ir viešą adresą, galiojantį tik iki kito lease, todėl porto persiuntimas atrodo veikiantis valandą ir paskui tyliai miršta.

Kai kurie tiekėjai tikrai duoda tikrą viešą adresą, bet blokuoja įeinančius 80 ir 443 portus namų planuose. Jei tavo tarnyba tik žiniatinklinė, o WAN adresas tikrai viešas, paklausk palaikymo, prieš statydamas relay. Jei ne, žemiau pateikta schema vienodai taikoma kiekvienam portui, ir verta sustabdyti eksperimentą maršrutizatoriaus pusėje: vertėjas tiekėjo tinkle užbaigia ryšį anksčiau, nei jis pasiekia tavo WAN sąsają.

Nukreipk vardą į VPS adresą

DNS neperduoda srauto, todėl tarnybos A įrašas turi turėti viešą VPS adresą. A įrašas į 192.168.1.20 naudingai išspręstas tik klientams, kurie jau yra VPN; iš interneto jis išspręstas į adresą, kurio niekas negali maršrutizuoti. Administracinei prieigai prie paties VPS laikau atskirą vardą, kad niekada nesupainiočiau, kuriam pagrindiniam kompiuteriui priklauso įrašas.

Jei HTTP teikia ir VPS, ir namų mašina, duok kiekvienam savo vardą ir leisk VPS nuspręsti, kas atsako. Sujungti juos į vieną vardą ir tikėtis, kad proxy pasirinks tinkamą backend, yra būtent tai, kaip praleidi visą popietę derindamas ne tą kompiuterį.

Vienas portas per DNAT, SSH lieka 22

Tiesioginis variantas yra paskirties NAT VPS. Įjunk forwarding veikiančiam branduoliui ir laikyk taisyklėje namų serverio tunelio adresą, o ne jo LAN adresą:

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

Palik SSH į patį VPS 22, o kitą portą, pavyzdžiui 5022, persiųsk į namų mašiną. Jei persiusi 22 į išjungtą mašiną, prarasi vienintelį kelią, kuris galėjo ją sutaisyti. Ta pati logika galioja proxy: laikyk VPS valdymo portą už relay taisyklių ribų.

Padaryk taisykles nuolatinėmis, kai jos pradės veikti. Debian arba Ubuntu apt install iptables-persistent ir tada netfilter-persistent save įrašo jas į /etc/iptables/rules.v4. Hoste su firewalld atitikmuo yra nuolatinis porto persiuntimas zonoje, kuriam prieš pritaikymą reikia firewall-cmd --reload. Taisyklės, gyvenančios tik atmintyje, dingsta per pirmą tiekėjo techninės priežiūros perkrovimą, dažniausiai netinkamą valandą.

Sutvarkyk grįžtamąjį kelią arba išvengk jo poreikio

DNAT perrašo tik paskirties adresą. Namų serveris mato ryšį iš pradinio kliento adreso, ir jei jo numatytasis maršrutas veda į namų maršrutizatorių, atsakymas išeina per namų WAN, kur tiekėjo vertėjas jį numeta. Ta asimetrija buvo antras gedimas, su kuriuo susidūriau, kai DNAT taisyklė atrodė visiškai teisinga.

Du pataisymai veikia. Duok namų mašinai politikos maršrutą, kad srautas iš tunelio grįžtų per tunelį:

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

Arba leisk VPS perrašyti šaltinį, kad atsakymas turėtų adresą, kurį jis gali pasiekti, ir leisk conntrack jį apversti išėjime:

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

SNAT variantas slepia tikrą kliento adresą nuo namų serverio, todėl programos žurnaluose kaip peer rodomas 10.8.0.1. Perduok pradinį adresą programos lygmenyje arba priimk, kad žurnalavimas pagal klientą bus prarastas, bet nuspręsk sąmoningai, o ne atrask per incidentą.

Patikrink visą kelią iš išorės

Tikrink iš tinklo, kuris nėra nei VPS, nei namai: telefonas mobiliaisiais duomenimis arba pigus shell kitur. nc -vz files.example.net 5022 turėtų pranešti apie sėkmingą ryšį, o openssl s_client -connect files.example.net:443 -servername files.example.net turėtų parodyti viešo vardo sertifikatą. Tada patikrink tiekėjo security group arba debesų užkardą. DNAT taisyklė, kuri niekada nemato paketo, paprastai blokuojama vienu sluoksniu aukščiau kompiuterio.

Galiausiai nuspręsk, kas nutinka, kai tunelis nukrenta. DNAT taisyklė toliau priima ryšius ir tyliai siunčia juos į negyvą tunelį, o tai atrodo lygiai kaip sugedusi tarnyba. Būsenos patikra VPS, kuri atmeta portą, kol peer neveikia, kainuoja kelias eilutes ir sutaupo valandą spėlionių. Po to nustok redaguoti taisykles ir stebėk tai parą, prieš pasitikėdamas.

Susiję straipsniai