Vezivanje jednog programa za VPN na Linuxu uglavnom je problem usmjeravanja, a pravilo firewalla odlučuje samo šta se događa nakon što je ruta odabrana. Ako uskladite UID programa u OUTPUT prije nego tunel dobije zadanu rutu, pravilo ispušta upravo onaj promet koji ste htjeli zaštititi. Isto pravilo ne vidi ni resolver proces koji odgovara na DNS upite programa. Postavite redoslijed kako treba i jedan račun bez privilegija postaje pouzdan birač razdvojenog tunela.

Dajte računu rutu prije presude

Podudaranje vlasnika odgovara na jedno pitanje: je li lokalni socket koji pripada ovom UID-u sastavio paket? Ono ne bira sučelje i ne može premjestiti promet koji glavna tablica već šalje kroz fizički NIC. Zato UID pravilo bez odgovarajuće rute blokira program umjesto da ga preusmjeri.

Pošaljite račun prvo kroz njegovu vlastitu tablicu, pa pustite firewall da potvrdi rezultat. Ovo radi na hostu čiji iproute2 razumije uidrange, što ip rule help javlja u jednom redu. Tablica 100 drži zadanu rutu kroz tunel, a pravilo šalje samo UID 1000 u tu tablicu. Sve ostalo ostaje na glavnoj tablici i nastavlja koristiti fizički link.

ip rule add uidrange 1000-1000 table 100
ip route add default dev tun0 table 100

Drugi račun kojem treba drugačiji tunel dobija tablicu 101 i svoje pravilo, jer dva profila ne mogu oba posjedovati zadanu rutu u istoj tablici. NetworkManager profili su sistemski, pa ovaj dio ostaje ručan, a pravila nestaju pri ponovnom pokretanju osim ako ih nešto ne vrati. Upišite tablice u boot skriptu pokraj definicije tunela kako ponovno povezivanje ne bi ostavilo jedan račun na pogrešnom putu.

Zašto izuzetak za loopback ubija tunel

Većina kopiranih verzija pravila ispušta svaki paket koji ne izlazi kroz loopback. Tunel nije loopback, pa taj oblik ispušta i promet tunela, a rezultat izgleda kao mrtav VPN, a ne kao greška firewalla.

Dok OUTPUT radi, kernel je već odabrao izlazno sučelje, pa -o se poredi s odgovorom rute, a ne sa zaglavljem paketa. Podudaranje vlasnika provjerava se samo u OUTPUT i POSTROUTING, a proslijeđeni paketi ne nose socket koji bi ono moglo čitati. Ta kombinacija znači da izuzetak mora imenovati sučelje tunela i negirati to podudaranje, umjesto da negira loopback.

Loopback ipak zaslužuje vlastiti ACCEPT iznad DROP-a, jer prvi DNS paket iz programa ide na lokalni stub preko lo. Postavite dva pravila u ovaj redoslijed i račun stiže do stuba, zatim tunela, i nigdje drugdje.

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 je zaseban skup pravila, a par samo za v4 ostavlja ip6tables netaknut. Program koji preferira AAAA zapise tada bi izašao kroz fizički link, a da nikad ne stigne do DROP-a. Preslikajte oba pravila u ip6tables, ili isključite IPv6 na hostu kada tunel ne nosi v6 adresu. Ručno dodana pravila također nestaju pri ponovnom pokretanju, pa ih sačuvajte s netfilter-persistent save ili ponovno izgradite istu logiku kao nftables tablicu koju učitava boot unit.

DNS odgovori stižu iz drugog procesa

Upit programa prema 127.0.0.53 prolazi ACCEPT za loopback i upravo tu podudaranje UID-a prestaje. Stub resolver prosljeđuje upit prema gore iz svog servisnog računa, pa pravilo vezano za vpnapp nikad ne vidi drugi upit. Ako resolver za link odabere LAN server, odgovori se vraćaju kroz fizički NIC dok vlastiti paketi programa ostaju u tunelu. Vidljiv rezultat je tunel koji radi s pokvarenim imenima ili imena koja vraća server koji niste odabrali.

Popravite razrješavanje imena na linku tunela, a ne u aplikaciji. Dajte profilu tunela DNS server i domenu usmjeravanja, pa potvrdite s resolvectl query i resolvectl status tun0 da ga resolver koristi za imena koja su važna. Unutar mrežnog imenskog prostora problem nestaje, jer resolver prostora poznaje samo tunel.

Provjerite pravilo sa samog računa

Pitajte kernel koju rutu dobija UID, pa uputite zahtjev kao taj račun i uporedite izlaznu adresu s adresom vlastitog računa. Ako oba prijave istu adresu, pravilo se podudara s nečim drugim, a ne s prometom koji ste testirali. Prva naredba ispod pokazuje traženje rute bez slanja paketa, što razdvaja grešku usmjeravanja od greške firewalla.

ip route get 1.1.1.1 uid 1000
sudo -u vpnapp curl -s https://ifconfig.co

Brojači pokazuju je li pravilo ikad opalilo. Pokrenite iptables -vnL OUTPUT, pročitajte broj paketa pokraj svakog pravila i tretirajte nulu pokraj DROP-a nakon stvarnog prometa kao grešku podudaranja.

Proslijeđeni promet stoji izvan ovog dizajna. Kontejner ili VM iza bridgea nema lokalni socket koji posjeduje vpnapp, pa se podudaranje vlasnika nikad ne aktivira i ti paketi slijede FORWARD politiku. Ako taj posao mora biti pokriven, testirajte ga odvojeno i napišite politiku vezanu za bridge ili adresu kontejnera. Dizajn drži kada tablica, izuzetak sučelja, resolver i v6 pravila svi pokazuju u istom smjeru; izostavite bilo koje od njih i račun ili curi, ili gubi vezu.

Povezani članci