Ang pag-pin ng isang programa sa VPN sa Linux ay pangunahing problema sa routing, at ang firewall rule ay nagpapasya lamang kung ano ang mangyayari pagkatapos mapili ang ruta. Kung itutugma mo ang UID ng programa sa OUTPUT bago magkaroon ng default na ruta ang tunnel, itinatapon ng rule ang mismong trapik na gusto mong protektahan. Hindi rin nakikita ng parehong rule ang proseso ng resolver na sumasagot sa mga DNS query ng programa. Ayusin ang pagkakasunod-sunod at ang isang account na walang pribilehiyo ay magiging maaasahang tagapili ng hatian na tunnel.

Bigyan ng ruta ang account bago ang hatol

Sinasagot ng pagtutugma ng may-ari ang isang tanong: itinayo ba ng lokal na socket na pag-aari ng UID na ito ang packet? Hindi ito pumipili ng interface at hindi nito maigagalaw ang trapik na ipinapadala na ng pangunahing talahanayan sa pisikal na NIC. Kaya hinaharangan ng UID rule na walang tugmang ruta ang programa sa halip na i-redirect ito.

Ipadala muna ang account sa sarili nitong talahanayan, at pagkatapos ay hayaang kumpirmahin ng firewall ang resulta. Gumagana ito sa host na nauunawaan ng iproute2 nito ang uidrange, na ip rule help ay nag-uulat sa isang linya. Ang talahanayan 100 ay may default na ruta sa tunnel, at ang rule ay nagpapadala lamang ng UID 1000 sa talahanayang iyon. Ang lahat ng iba ay nananatili sa pangunahing talahanayan at patuloy na gumagamit ng pisikal na link.

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

Ang pangalawang account na nangangailangan ng ibang tunnel ay makakakuha ng talahanayan 101 at sariling rule, dahil hindi maaaring parehong magmay-ari ng default na ruta sa iisang talahanayan ang dalawang profile. Ang mga profile ng NetworkManager ay pang-system, kaya mananatiling manwal ang bahaging ito, at mawawala ang mga rule sa reboot maliban kung may magbalik sa mga ito. Isulat ang mga talahanayan sa boot script sa tabi ng depinisyon ng tunnel upang ang muling pagkonekta ay hindi makapag-iwan ng isang account sa maling landas.

Bakit pinapatay ng loopback exception ang tunnel

Itinatapon ng karamihan ng kinopyang bersyon ng rule ang bawat packet na hindi lumalabas sa loopback. Ang tunnel ay hindi loopback, kaya itinatapon din ng anyong iyon ang trapik ng tunnel, at ang resulta ay mukhang patay na VPN at hindi pagkakamali ng firewall.

Kapag tumatakbo ang OUTPUT, napili na ng kernel ang exit interface, kaya -o ay inihahambing sa sagot ng ruta at hindi sa header ng packet. Ang pagtutugma ng may-ari ay tinitingnan lamang sa OUTPUT at POSTROUTING, at ang mga naipasa na packet ay walang socket na mababasa nito. Ang kombinasyong iyon ay nangangahulugang dapat pangalanan ng exception ang interface ng tunnel at tanggihan ang pagtutugmang iyon, sa halip na tanggihan ang loopback.

Karapat-dapat pa rin ang loopback sa sarili nitong ACCEPT sa ibabaw ng DROP, dahil ang unang DNS packet mula sa programa ay patungo sa lokal na stub sa pamamagitan ng lo. Ilagay ang dalawang rule sa ganitong pagkakasunod-sunod, at maabot ng account ang stub, pagkatapos ang tunnel, at wala nang iba.

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

Ang IPv6 ay hiwalay na set ng rule, at ang pares na para lamang sa v4 ay iniiwan ang ip6tables na hindi ginalaw. Ang programang mas gusto ang AAAA record ay lalabas sa pisikal na link nang hindi umaabot sa DROP. Ipakita ang parehong rule sa ip6tables, o i-disable ang IPv6 sa host kapag walang dala na v6 address ang tunnel. Ang mga rule na idinagdag sa kamay ay nawawala rin sa reboot, kaya i-save ang mga ito gamit ang netfilter-persistent save o buuin muli ang parehong lohika bilang nftables table na nilo-load ng boot unit.

Ang mga sagot ng DNS ay nagmumula sa ibang proseso

Ang query ng programa sa 127.0.0.53 ay dumadaan sa loopback ACCEPT, at doon humihinto ang pagtutugma ng UID. Ang stub resolver ay nagpapasa pataas mula sa sarili nitong service account, kaya ang rule na nakakabit sa vpnapp ay hindi kailanman nakakakita ng ikalawang query. Kung pipiliin ng resolver ang isang LAN server para sa link, babalik ang mga sagot sa pisikal na NIC habang ang sariling packet ng programa ay nananatili sa tunnel. Ang nakikitang resulta ay gumaganang tunnel na may sirang pangalan, o mga pangalang sinasagot ng server na hindi mo pinili.

Ayusin ang resolusyon ng pangalan sa link ng tunnel, hindi sa application. Bigyan ang profile ng tunnel ng DNS server at routing domain, pagkatapos ay kumpirmahin gamit ang resolvectl query at resolvectl status tun0 na ginagamit ito ng resolver para sa mahahalagang pangalan. Sa loob ng namespace ng network, nawawala ang problema, dahil alam lamang ng resolver ng namespace ang tunnel.

Suriin ang rule mula sa account mismo

Tanungin ang kernel kung anong ruta ang nakukuha ng UID, pagkatapos ay gumawa ng kahilingan bilang account na iyon at ihambing ang exit address sa address ng sarili mong account. Kung pareho silang nag-uulat ng parehong address, ang rule ay tumutugma sa iba pa kaysa sa trapik na sinubukan mo. Ipinapakita ng unang utos sa ibaba ang paghahanap ng ruta nang hindi nagpapadala ng packet, na naghihiwalay ng routing error sa firewall error.

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

Ipinapakita ng mga counter kung ang isang rule ay naging aktibo. Patakbuhin ang iptables -vnL OUTPUT, basahin ang bilang ng packet sa tabi ng bawat rule, at ituring na matching error ang zero sa tabi ng DROP pagkatapos ng tunay na trapik.

Ang naipasang trapik ay nasa labas ng disenyong ito. Ang container o VM sa likod ng bridge ay walang lokal na socket na pag-aari ng vpnapp, kaya hindi kailanman nag-a-activate ang pagtutugma ng may-ari at ang mga packet na iyon ay sumusunod sa patakarang FORWARD. Kung kailangang masakop ang workload na iyon, subukan ito nang hiwalay at sumulat ng patakarang nakakabit sa bridge o address ng container. Nananatili ang disenyo kapag ang talahanayan, ang exception ng interface, ang resolver at ang mga rule ng v6 ay lahat tumuturo sa parehong direksyon; iwanan ang alinman sa mga ito at ang account ay tumutulo o nawawalan ng koneksyon.

Kaugnay na mga artikulo