Cum să rulezi un singur proces Linux în afara unui tunel WireGuard
Dă unui program propriul context de rețea ca să părăsească un host WireGuard cu tunel complet, apoi repară regulile de redirecționare și marcare care îl blochează.
Nu poți excepta un program de la un host WireGuard cu tunel complet editând rute. Rutele aleg o cale după destinație, iar ceea ce vrei să excepți este un proces, așa că nucleul nu are cu ce să compare. Abordarea viabilă este să dai acelui proces propriul context de rețea: un spațiu de nume cu interfața, adresele și ruta implicită proprii, conectat la host printr-o pereche veth. Am rulat asta pe Ubuntu 24.04 cu wireguard-tools 1.0.20210914, iar spațiul de nume nu a fost niciodată problema — politica de redirecționare a hostului și regulile de marcare ale tunelului au fost.
Mai întâi alege tipul de context de care ai nevoie
În practică apar două forme. Dacă hostul rulează un tunel complet și un program trebuie să iasă pe calea ISP-ului, construiești un al doilea spațiu de nume, îl conectezi la host și lași hostul să redirecționeze și să traducă traficul pentru el. Dacă un spațiu de nume poartă deja o interfață VPN și ai nevoie doar de o comandă pornită în el, acesta este cazul obișnuit de ip netns exec și cea mai mare parte a muncii de rutare este deja făcută.
Niciuna dintre forme nu îți dă o regulă limitată la un singur identificator de proces. Netfilter potrivește adrese, porturi, marcaje și interfețe; nu există tabelă de rutare pe proces. Marcarea poate direcționa traficul, dar marcajul trebuie aplicat pe pachete pe care le-ai identificat deja, iar aceasta este aceeași problemă un nivel mai jos. Un spațiu de nume separă întreaga stivă pentru acel arbore de procese, și de aceea este răspunsul obișnuit.
Dacă cerința este într-adevăr ca nimic să nu iasă din tunel, oprește tunelul. Spațiul de nume există pentru cazul mixt: un program afară, tot restul înăuntru, pe aceeași mașină, în același timp.
Construiește al doilea context și conectează-l la host
Un aspect ilustrativ: hostul are o interfață WireGuard care poartă ruta implicită și un spațiu de nume de rețea numit clearnet conectat la host printr-o pereche veth. Adresele de mai jos sunt exemple.
ip netns add clearnet
ip link add veth-clear-out type veth peer name veth-clear-in
ip addr add 192.168.100.1/24 dev veth-clear-out
ip link set veth-clear-out up
ip link set veth-clear-in netns clearnet
ip netns exec clearnet ip addr add 192.168.100.2/24 dev veth-clear-in
ip netns exec clearnet ip link set veth-clear-in up
ip netns exec clearnet ip route add default via 192.168.100.1
Acel spațiu de nume poate ajunge acum la host și la nimic altceva. Hostul trebuie să redirecționeze traficul și să rescrie adresa sursă, pentru că 192.168.100.0/24 este privată și routerul din amonte nu are nicio rută înapoi în ea:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o <wan-interface> -j MASQUERADE
Confirmă partea spațiului de nume înainte de a continua.ip netns exec clearnet ip route ar trebui să arate ruta veth și ruta implicită prin 192.168.100.1, iar un ping către acea adresă ar trebui să răspundă. Dacă pingul către adresa hostului eșuează, adresele sau starea legăturii sunt greșite și nicio regulă de firewall nu va ajuta.
Când numele se rezolvă dar nu se întoarce nimic, citește FORWARD
Eșecul clasic arată ca un bug de rutare: spațiul de nume rezolvă un nume, pachetul iese și nu sosește niciodată un răspuns. Pe hosturi cu o politică FORWARD de DROP — așa fac mai multe distribuții și majoritatea imaginilor întărite — pachetul este aruncat pe drum, iar eroarea tipărită de aplicație nu spune nimic despre filtrare.
Citește lanțul înainte de a adăuga ceva:
iptables -S FORWARD
nft list chain inet filter forward
Apoi admite traficul în ambele direcții, cu contoare, ca să poți vedea dacă regula a potrivit vreodată:
iptables -A FORWARD -i veth-clear-out -o <wan-interface> -j ACCEPT
iptables -A FORWARD -i <wan-interface> -o veth-clear-out -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
watch -n1 'iptables -L FORWARD -v -n'
O regulă cu un contor de pachete zero nu este pe cale. Fie numele interfețelor diferă de ce ai presupus, fie o regulă anterioară din lanț a acceptat, a aruncat sau a returnat pachetul prima. Repară ordinea, nu textul regulii.
Traficul de răspuns este jumătatea pe care oamenii o uită. Regula de retur are nevoie de același nume veth plus o potrivire a stării conexiunii, sau de o acceptare simplă a interfeței dacă ții politica deschisă. Adaugă doar regula de ieșire și simptomul original revine, cu regula ta nouă stând acolo și părând corectă.
Ține regulile de marcare ale tunelului departe de calea nouă
Acest pas transformă un spațiu de nume funcțional într-unul care scurge. Instalările WireGuard instalează de obicei o politică de marcă de firewall împreună cu propriile reguli de rutare și o tabelă dedicată, așa că pachetele nemarcate cad înapoi în tabela principală, iar cele marcate folosesc tabela tunelului. Traficul redirecționat din spațiul de nume este evaluat față de rutarea pe politici la ieșire și, în funcție de cum au fost scrise acele reguli, poate ajunge în tabela tunelului.
Două adăugiri separă căile. Întoarce-te devreme în lanțul mangle pentru subrețeaua spațiului de nume și adaugă o regulă bazată pe sursă care pune acea subrețea în tabela principală:
iptables -t mangle -I PREROUTING -s 192.168.100.0/24 -j RETURN
ip rule add from 192.168.100.0/24 lookup main priority 100
Prioritatea 100 se ordonează înaintea regulilor tunelului pe hostul meu, așa că pentru acea sursă decide tabela obișnuită. Nu copia numărul orbește: prioritățile pe care wg-quick le instalează diferă între versiuni și între configurațiile IPv4 și IPv6, așa că rulează ip rule show și alege o prioritate care cade înaintea regulilor tunelului pe mașina ta.
Verifică cu o căutare specifică sursei în loc să te bazezi pe lista de reguli:
ip route get 1.1.1.1 from 192.168.100.2
ip netns exec clearnet ip route get 1.1.1.1
Dacă prima comandă raportează interfața WireGuard, regula nouă nu este încă înaintea politicii tunelului. Dacă raportează interfața WAN în timp ce a doua arată încă ruta implicită veth, hostul și spațiul de nume nu sunt de acord și ar trebui să recitești ambele tabele de rutare.
Pornește procesul care deschide conexiunea
Pornirea comenzii este o linie, dar pornește procesul care creează efectiv socketul.ip netns exec clearnet curl -s https://ifconfig.me este cel mai mic test cinstit: arată adresa pe care spațiul de nume o prezintă lumii, nu pe cea pe care ar folosi-o hostul.
Pentru un serviciu, atașează spațiul de nume după cale, ca procesul să rămână în el toată viața:
[Service]
NetworkNamespacePath=/run/netns/clearnet
Aplicațiile grafice sunt locul unde abordarea pe o linie eșuează în tăcere. Un browser pornit din meniu predă adesea cererea unei instanțe care rulează deja în afara spațiului de nume, așa că fereastra nouă apare și traficul iese tot prin tunel. Dă-i un profil separat ca să se creeze într-adevăr o instanță nouă, apoi verifică contextul procesului în loc să ghicești:
readlink /proc/$(pgrep -f clearnet-profile | head -1)/ns/net
readlink /run/netns/clearnet
Cele două ieșiri trebuie să coincidă. Aceeași verificare funcționează pentru orice program de lungă durată și merită făcută o dată pe aplicație în loc să presupui că lansatorul a făcut ce intenționai.
Rezolvarea numelor are nevoie de propria decizie. Crearea unui spațiu de nume nu îi dă o configurație de resolver; fișierele pe spațiu de nume sunt acceptate prin /etc/netns/<name>/resolv.conf iar fără unul moștenești un comportament ușor de citit greșit. IPv6 are nevoie de același tratament: dacă spațiul de nume nu are rută implicită v6 în timp ce aplicația preferă v6, cererile se pot bloca înainte de a reveni, ceea ce arată ca un tunel stricat.
Verifică încadrarea, nu doar adresa de ieșire
O adresă publică funcțională dovedește ruta, nu întreaga cerință. Parcurge restul în această ordine:
ip netns exec clearnet ip route get 1.1.1.1arată ruta implicită veth, nu interfața WireGuard.- Contoarele FORWARD de pe ambele reguli cresc în timp ce o cerere rulează.
- Procesul aplicației raportează inode-ul spațiului de nume pe care îl aștepți.
- După o repornire spațiul de nume există înainte ca serviciul să pornească; o unitate care rulează mai devreme eșuează sau, mai rău, rulează în afara spațiului de nume.
Apoi decide ce trebuie să se întâmple când tunelul cade. Spațiul de nume continuă să funcționeze, ceea ce este scopul exercițiului și totodată riscul: programul exceptat rămâne conectat în timp ce tot restul se oprește. Notează asta ca decizie de politică și fii clar despre ce nu acoperă excepția — identitatea contului, starea salvată a browserului și furnizorul tău de DNS stau toate în afara sferei unui spațiu de nume de rețea, iar tratarea excepției ca anonimat este greșeala care supraviețuiește configurației.