Vienos programos priskyrimas VPN Linux sistemoje pirmiausia yra maršrutizavimo problema, o ugniasienės taisyklė tik nusprendžia, kas nutinka pasirinkus maršrutą. Jei OUTPUT faile sutapatinsite programos UID anksčiau, nei tunelis turės numatytąjį maršrutą, taisyklė išmes būtent tą srautą, kurį norėjote apsaugoti. Ta pati taisyklė nemato ir resolver proceso, kuris atsako į programos DNS užklausas. Sudėliokite tvarką teisingai, ir viena paskyra be privilegijų taps patikimu padalinto tunelio parinkikliu.

Duokite paskyrai maršrutą prieš nuosprendį

Savininko atitikimas atsako į vieną klausimą: ar paketą sukūrė vietinis lizdas, priklausantis šiam UID? Jis neparenka sąsajos ir negali perkelti srauto, kurį pagrindinė lentelė jau siunčia per fizinę NIC. Todėl UID taisyklė be atitinkamo maršruto blokuoja programą, o ne peradresuoja ją.

Pirmiausia praleiskite paskyrą per jos pačios lentelę, o tada leiskite ugniasienei patvirtinti rezultatą. Tai veikia pagrindiniame kompiuteryje, kurio iproute2 supranta uidrange, ką ip rule help praneša viena eilute. 100 lentelė laiko numatytąjį maršrutą per tunelį, o taisyklė siunčia tik UID 1000 į tą lentelę. Viskas kita lieka pagrindinėje lentelėje ir toliau naudoja fizinę jungtį.

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

Antra paskyra, kuriai reikia kito tunelio, gauna 101 lentelę ir savo taisyklę, nes du profiliai negali abu turėti numatytojo maršruto toje pačioje lentelėje. NetworkManager profiliai yra sistemos lygmens, todėl ši dalis lieka rankinė, o taisyklės dingsta perkraunant, jei kažkas jų neatkuria. Įrašykite lenteles į paleidimo scenarijų šalia tunelio aprašo, kad pakartotinis prisijungimas nepaliktų vienos paskyros neteisingame kelyje.

Kodėl loopback išimtis užmuša tunelį

Dauguma nukopijuotų taisyklės versijų išmeta kiekvieną paketą, kuris neišeina per loopback. Tunelis nėra loopback, todėl ta forma išmeta ir tunelio srautą, o rezultatas atrodo kaip negyvas VPN, o ne ugniasienės klaida.

Kai OUTPUT veikia, branduolys jau pasirinko išėjimo sąsają, todėl -o lyginamas su maršruto atsakymu, o ne su paketo antrašte. Savininko atitikimas tikrinamas tik OUTPUT ir POSTROUTING, o persiųsti paketai neturi lizdo, kurį jis galėtų perskaityti. Šis derinys reiškia, kad išimtis turi įvardyti tunelio sąsają ir paneigti tą atitikimą, o ne paneigti loopback.

Loopback vis tiek nusipelno savo ACCEPT virš DROP, nes pirmasis programos DNS paketas eina į vietinį stub per lo. Sudėkite dvi taisykles šia tvarka, ir paskyra pasiekia stub, tada tunelį, ir nieko daugiau.

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 yra atskiras taisyklių rinkinys, o pora, skirta tik v4, palieka ip6tables nepaliestą. Programa, kuri pirmenybę teikia AAAA įrašams, tada išeitų per fizinę jungtį taip ir nepasiekusi DROP. Atspindėkite abi taisykles ip6tables, arba išjunkite IPv6 pagrindiniame kompiuteryje, kai tunelis neturi v6 adreso. Rankiniu būdu pridėtos taisyklės taip pat dingsta perkraunant, todėl išsaugokite jas su netfilter-persistent save arba atkurkite tą pačią logiką kaip nftables lentelę, kurią įkelia paleidimo blokas.

DNS atsakymai ateina iš kito proceso

Programos užklausa į 127.0.0.53 praeina loopback ACCEPT, ir būtent ten UID atitikimas sustoja. Stub resolver persiunčia aukštyn iš savo paslaugos paskyros, todėl taisyklė, susieta su vpnapp niekada nemato antros užklausos. Jei resolver jungčiai pasirenka LAN serverį, atsakymai grįžta per fizinę NIC, o pačios programos paketai lieka tunelyje. Matomas rezultatas yra veikiantis tunelis su sulaužytais vardais, arba vardai, kuriuos atsako jūsų nepasirinktas serveris.

Taisykite vardų sprendimą tunelio jungtyje, o ne programoje. Suteikite tunelio profiliui DNS serverį ir maršrutizavimo domeną, tada patvirtinkite su resolvectl query ir resolvectl status tun0 kad resolver jį naudoja svarbiems vardams. Tinklo vardų erdvėje problema dingsta, nes erdvės resolver žino tik tunelį.

Patikrinkite taisyklę iš pačios paskyros

Paklauskite branduolio, kokį maršrutą gauna UID, tada atlikite užklausą kaip ta paskyra ir palyginkite išėjimo adresą su savo paskyros adresu. Jei abu praneša tą patį adresą, taisyklė atitinka ką nors kita, o ne tą srautą, kurį išbandėte. Pirmoji komanda žemiau parodo maršruto paiešką nesiunčiant paketo, kas atskiria maršrutizavimo klaidą nuo ugniasienės klaidos.

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

Skaitikliai rodo, ar taisyklė kada nors suveikė. Paleiskite iptables -vnL OUTPUT, perskaitykite paketų skaičių prie kiekvienos taisyklės ir nulį prie DROP po tikro srauto laikykite atitikimo klaida.

Persiųstas srautas yra už šios konstrukcijos ribų. Konteineris ar VM už tilto neturi vietinio lizdo, kuris priklausytų vpnapp, todėl savininko atitikimas niekada nesuveikia ir tie paketai vietoj to vadovaujasi FORWARD politika. Jei tą apkrovą reikia padengti, išbandykite ją atskirai ir parašykite politiką, susietą su tiltu ar konteinerio adresu. Konstrukcija laikosi, kai lentelė, sąsajos išimtis, resolver ir v6 taisyklės visos rodo ta pačia kryptimi; palikite bet kurią iš jų, ir paskyra arba nuteka, arba praranda ryšį.

Susiję straipsniai