Slik bind du éin Linux-app til ein VPN med UID-reglar
Ein UID-regel ser berre lokale soklar, og det vanlege loopback-unntaket drep tunnelen. Rut kontoen fyrst, og filtrer og stadfest deretter kvart steg.
Å binde eitt program til eit VPN på Linux er mest eit ruteproblem, og brannmurregelen avgjer berre kva som skjer etter at ruta er vald. Viss du matchar UID-en til programmet i OUTPUT før tunnelen eig standardruta, slepp regelen nettopp den trafikken du ville verne. Same regel ser heller ikkje resolverprosessen som svarar på DNS-spurnadene til programmet. Få rekkjefølgja rett, og éin konto utan rettar blir ein påliteleg veljar for den delte tunnelen.
Gi kontoen ei rute før ein dom
Eigar-matchinga svarar på eitt spørsmål: bygde ein lokal sokkel som høyrer til denne UID-en, pakken? Ho vel ikkje grensesnitt, og ho kan ikkje flytte trafikk som hovudtabellen allereie sender ut gjennom den fysiske NIC-en. Derfor blokkerer ein UID-regel utan samsvarande rute programmet i staden for å omdirigere det.
Send kontoen gjennom sin eigen tabell fyrst, og la deretter brannmuren stadfeste resultatet. Dette verkar på ein vert der iproute2 forstår uidrange, noko ip rule help melder på éi linje. Tabell 100 held ei standardrute gjennom tunnelen, og regelen sender berre UID 1000 til den tabellen. Alt anna blir på hovudtabellen og brukar framleis den fysiske lenkja.
ip rule add uidrange 1000-1000 table 100 ip route add default dev tun0 table 100
Ein annan konto som treng ein annan tunnel får tabell 101 og sin eigen regel, fordi to profilar ikkje kan eige standardruta i same tabell samtidig. NetworkManager-profilar er systemomfattande, så denne delen blir manuell, og reglane forsvinn ved omstart med mindre noko gjenopprettar dei. Skriv tabellane i eit oppstartsskript ved sida av tunneldefinisjonen, slik at ein gjenoppkopling ikkje kan etterlate éin konto på feil veg.
Kvifor loopback-unntaket drep tunnelen
Dei fleste kopierte versjonane av regelen slepp kvar pakke som ikkje går ut gjennom loopback. Tunnelen er ikkje loopback, så den forma slepp også tunneltrafikken, og resultatet ser ut som ein død VPN og ikkje som ein brannmurfeil.
Når OUTPUT køyrer, har kjernen allereie valt eit utgangsgrensesnitt, så -o blir samanlikna med svaret frå ruta og ikkje med pakkehovudet. Eigar-matchinga blir berre konsultert i OUTPUT og POSTROUTING, og videresende pakkar ber ingen sokkel som ho kan lese. Den kombinasjonen tyder på at unntaket må namngje grensesnittet til tunnelen og negere den matchinga, i staden for å negere loopback.
Loopback fortener framleis sin eigen ACCEPT over DROP, fordi den første DNS-pakken frå programmet går til den lokale stubben via lo. Set dei to reglane i denne rekkjefølgja, og kontoen når stubben, deretter tunnelen, og ingenting anna.
iptables -I OUTPUT 1 -o lo -m owner --uid-owner vpnapp -j ACCEPT iptables -A OUTPUT -m owner --uid-owner vpnapp ! -o tun0 -j DROP
IPv6 er eit eige regelsett, og eit par berre for v4 lèt ip6tables stå urørt. Eit program som føretrekk AAAA-poster, ville då gå ut gjennom den fysiske lenkja utan å nå DROP i det heile. Spegl begge reglane i ip6tables, eller slå av IPv6 på verten når tunnelen ikkje ber noka v6-adresse. Reglar som blir lagde til manuelt, forsvinn også ved omstart, så lagre dei med netfilter-persistent save eller bygg same logikk på nytt som ein nftables-tabell som oppstartseininga lastar.
DNS-svar kjem frå ein annan prosess
Spurnaden frå programmet til 127.0.0.53 passerer loopback-ACCEPT, og det er der UID-matchinga stoppar. Stub-resolveren videresender oppover frå sin eigen tenestekonto, så ein regel knytt til vpnapp ser aldri den andre spurnaden. Viss resolveren vel ein LAN-server for lenkja, kjem svara tilbake over den fysiske NIC-en medan pakkane til programmet sjølv blir i tunnelen. Det synlege resultatet er ein fungerande tunnel med øydelagde namn, eller namn svara av ein server du ikkje valde.
Rett namneoppløysinga på lenkja til tunnelen, ikkje i applikasjonen. Gi tunnelprofilen ein DNS-server og eit rutingsdomene, og stadfest deretter med resolvectl query og resolvectl status tun0 at resolveren brukar den for namna som betyr noko. Inne i eit nettverksnamnerom forsvinn problemet, fordi resolveren i namnerommet berre kjenner tunnelen.
Kontroller regelen frå sjølve kontoen
Spør kjernen kva rute ein UID får, og lag deretter ein førespurnad som den kontoen og samanlikn utgangsadressa med adressa til din eigen konto. Viss begge rapporterer same adresse, matchar regelen noko anna enn trafikken du testa. Den første kommandoen nedanfor viser ruteoppslaget utan å sende ein pakke, noko som skil ein ruteleik frå ein brannmurfeil.
ip route get 1.1.1.1 uid 1000 sudo -u vpnapp curl -s https://ifconfig.co
Teljarar viser om ein regel nokon gong vart utløyst. Køyr iptables -vnL OUTPUT, les pakketalet ved sida av kvar regel, og handsam ein null ved DROP etter ekte trafikk som ein matchfeil.
Videresend trafikk ligg utanfor dette designet. Ein container eller VM bak ei bru har ingen lokal sokkel eigd av vpnapp, så eigar-matchinga blir aldri utløyst, og dei pakkane følgjer i staden FORWARD-policyen. Viss den arbeidsmengda skal dekkjast, test ho separat og skriv ein policy knytt til brua eller containeradressa. Designet held når tabellen, grensesnittunntaket, resolveren og v6-reglane alle peikar same veg; utelat éin av dei, og kontoen lekker eller mistar tilkoplinga.