Remediați DNS-ul oaspetelui libvirt blocat de un firewall VPN bazat pe marcaje
Un firewall VPN bazat pe marcaje aruncă DNS-ul oaspetelui înainte ca un lanț de filtrare să-l vadă. O singură regulă cu prioritate mangle marchează interogarea și răspunsul, fără a vă deschide rețeaua locală.
Oaspeții din rețeaua libvirt implicită rezolvă numele perfect până când interfața WireGuard apare, iar apoi fiecare căutare se blochează în același loc. dnsmasq ascultă încă pe 192.168.122.1:53, oaspetele are încă acea adresă ca resolver, iar interogarea tot ajunge. Ce s-a schimbat este că interogarea upstream a gazdei însăși, sau răspunsul la ea, este acum aruncată de o regulă evaluată înaintea oricărui lanț de filtrare la care v-ați gândi să editați. Ieșirea este un marcaj aplicat suficient de devreme, pe o conexiune pe care răspunsul o moștenește.
Oaspeții pierd DNS în momentul în care tunelul apare
Confirmați forma înainte de a schimba ceva. Opriți tunelul, rulați dig @192.168.122.1 example.com dintr-un oaspete și urmăriți că răspunde. Ridicați tunelul, repetați și urmăriți că expiră. Această pereche de rezultate elimină într-un singur pas o rețea libvirt stricată, o adresă de resolver greșită și un dnsmasq mort.
Apoi uitați-vă la partea gazdei. Dacă dnsmasq înregistrează interogarea și redirecționarea ei upstream, pachetul a ajuns și eșecul este pe ieșire. Dacă dnsmasq nu înregistrează nimic, interogarea oaspetelui este aruncată la intrare, iar excepția aparține unui alt hook decât cel pe care îl marchează acest articol.
De ce o regulă accept dintr-un lanț ulterior nu se declanșează niciodată
Un firewall VPN bazat pe marcaje decide uitându-se la marcajul pachetului sau la marcajul conexiunii, nu la adresa dumneavoastră sursă. Orice ajunge pe interfața fizică fără marcajul așteptat este refuzat, iar refuzul are loc în setul de reguli care deține testul de marcaj. ip saddr 192.168.122.0/24 accept linie adăugată într-un lanț ulterior pur și simplu nu este consultată niciodată pentru acel pachet, de aceea regula evidentă pare corectă și nu schimbă nimic.
Lărgirea ei până când ceva funcționează este a doua capcană. Acceptarea întregii subrețele libvirt pe calea de intrare a gazdei deschide fiecare serviciu al gazdei pentru oaspeți, când nevoia reală este un singur port.
Mecanismul care face posibilă o excepție îngustă este urmărirea conexiunilor. Când setați ct mark pe un pachet, valoarea este stocată pe intrarea conntrack și nu doar pe pachet, așa că fiecare pachet din acea conexiune o poartă după aceea, inclusiv răspunsul de la gazdă înapoi la oaspete. Acesta este tot trucul: marcați cererea o dată, iar calea de întoarcere este deja marcată.
Marcați interogarea înainte ca tabela VPN să o vadă
Puneți excepția în propria tabelă, ca un cititor ulterior să o găsească fără a analiza regulile VPN:
table inet allowedLocal {
chain guest_dns {
type filter hook input priority mangle; policy accept;
ip saddr 192.168.122.0/24 meta l4proto { tcp, udp } \
th dport 53 ct mark set 0x00000f41
}
}
priority mangle este negativă, ceea ce așază acest lanț înaintea lanțurilor de filtrare obișnuite pe care pachetul VPN le instalează la prioritatea zero. Ordinea hook-urilor este cea care face regula eficientă; aceeași regulă într-un lanț sortat după lanțul VPN este doar decor.
Numărul marcajului în sine nu este portabil. Luați valoarea pe care regulile VPN instalate o acceptă pentru propriul trafic, citiți-o din setul de reguli activ și folosiți-o pe aceea. Un marcaj greșit produce o regulă care se încarcă curat, se potrivește cu fiecare interogare și nu admite nimic.
Țineți gaura la lățimea portului 53
Așa cum este scris, aceasta permite DNS din subrețeaua libvirt către gazdă pe TCP sau UDP port 53 și nimic altceva. Nu le permite oaspeților să ajungă la internet în afara tunelului și nu permite gazdei să deschidă conexiuni către oaspeți. Dacă un oaspete are nevoie mai târziu de alt serviciu al gazdei, adăugați o regulă separată care numește acel port de destinație în loc să o relaxați pe aceasta.
Fiți sincer despre ce schimbați. Un oaspete care poate ajunge la un resolver poate și să tuneleze date arbitrare prin interogări DNS, iar această excepție este o fisură deliberată în granița VPN și nu o declarație că rețeaua locală este de încredere. Restrângerea sursei la 192.168.122.0/24 ține fisura departe de orice altă subrețea locală, iar numărarea interogărilor de la acea sursă este ieftină dacă amenințarea contează pentru dumneavoastră.
Faceți-o să supraviețuiască repornirii și dovediți ambele jumătăți
O regulă tastată într-un prompt de shell dispare la următoarea pornire, iar o regulă încărcată după ce interfața VPN deja trece trafic pierde cursa la prima conexiune. Puneți tabela în configurația nftables persistentă a gazdei, sau într-o unitate ordonată înaintea serviciului VPN, și verificați ordinea în loc să o presupuneți.
Verificarea are nevoie de trei răspunsuri separate. Confirmați că lanțul este încărcat și ordonat primul, confirmați că intrarea conntrack arată marcajul în ambele direcții și confirmați că o căutare din oaspete returnează o adresă. Apoi confirmați cealaltă jumătate: traficul web obișnuit al oaspetelui către o gazdă publică tot eșuează cât timp tunelul este oprit sau blochează. Dacă DNS funcționează și tot restul se scurge, regula dumneavoastră este mai largă decât cea de mai sus.
Dacă căutările tot eșuează după ce marcajul este pus, împotriviți-vă tentației de a lărgi sursa. Verificați încotro redirecționează dnsmasq, dacă resolverul oaspetelui indică spre 192.168.122.1 sau spre o adresă publică pe care cineva a tastat-o, și dacă interogarea ajunge măcar la gazdă. Marcarea admite pachetul și nimic altceva, așa că un upstream prost sau o rețea virtuală stricată rămân stricate oricâte reguli ați adăuga.