Gli ospiti sulla rete libvirt predefinita risolvono i nomi perfettamente finché non sale l'interfaccia WireGuard, e allora ogni ricerca si blocca nello stesso punto. dnsmasq è ancora in ascolto su 192.168.122.1:53, l'ospite ha ancora quell'indirizzo come resolver, e la query arriva ancora. Quello che è cambiato è che la query upstream dell'host stesso, o la risposta ad essa, ora viene scartata da una regola valutata prima di qualsiasi catena di filtro che penseresti di modificare. La via d'uscita è un mark applicato abbastanza presto, su una connessione che la risposta eredita.

Gli ospiti perdono il DNS nel momento in cui sale il tunnel

Conferma la forma prima di cambiare qualsiasi cosa. Abbassa il tunnel, esegui dig @192.168.122.1 example.com da un ospite e guardalo rispondere. Alza il tunnel, ripeti e guardalo andare in timeout. Questa coppia di risultati esclude una rete libvirt rotta, un indirizzo di resolver sbagliato e un dnsmasq morto in un solo passo.

Poi guarda il lato host. Se dnsmasq registra la query e il suo inoltro upstream, il pacchetto è arrivato e il guasto è in uscita. Se dnsmasq non registra nulla, la query dell'ospite viene scartata in ingresso e l'eccezione appartiene a un hook diverso da quello che questo articolo marca.

Perché una regola accept in una catena successiva non scatta mai

Un firewall VPN basato su mark decide guardando il mark del pacchetto o il mark della connessione, non il tuo indirizzo di origine. Tutto ciò che arriva sull'interfaccia fisica senza il mark atteso viene rifiutato, e quel rifiuto avviene nel set di regole che possiede il test del mark. Una riga ip saddr 192.168.122.0/24 accept aggiunta a una catena successiva semplicemente non viene mai consultata per quel pacchetto, ed è per questo che la regola ovvia sembra corretta e non cambia nulla.

Allargarla finché qualcosa funziona è la seconda trappola. Accettare l'intera sottorete libvirt nel percorso di input dell'host apre ogni servizio dell'host agli ospiti, quando il bisogno reale è una sola porta.

Il meccanismo che rende possibile un'eccezione stretta è il tracciamento delle connessioni. Quando imposti ct mark su un pacchetto, il valore viene memorizzato nella voce conntrack e non solo nel pacchetto, così ogni pacchetto di quella connessione lo porta dopo, compresa la risposta dall'host verso l'ospite. È tutto il trucco: marca la richiesta una volta e il percorso di ritorno è già marcato.

Marca la query prima che la tabella VPN la veda

Metti l'eccezione in una tabella propria, così un lettore successivo può trovarla senza analizzare le regole 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 è negativo, il che colloca questa catena davanti alle catene di filtro ordinarie che il pacchetto VPN installa a priorità zero. È l'ordine degli hook che rende efficace la regola; la stessa regola in una catena che si ordina dopo la catena VPN è solo decorazione.

Il numero del mark in sé non è portabile. Prendi il valore che le regole VPN installate accettano per il proprio traffico, leggilo dal set di regole vivo e usalo. Un mark sbagliato produce una regola che si carica pulita, corrisponde a ogni query e non ammette nulla.

Mantieni il buco largo quanto la porta 53

Così com'è scritto, questo consente DNS dalla sottorete libvirt all'host su TCP o UDP porta 53 e nient'altro. Non lascia che gli ospiti raggiungano internet fuori dal tunnel, e non lascia che l'host apra connessioni verso gli ospiti. Se un ospite ha bisogno più avanti di un altro servizio dell'host, aggiungi una regola separata che nomini quella porta di destinazione invece di allentare questa.

Sii onesto su ciò che stai scambiando. Un ospite che può raggiungere un resolver può anche incanalare dati arbitrari attraverso query DNS, e questa eccezione è un varco deliberato nel confine VPN, non un'affermazione che la rete locale sia affidabile. Limitare l'origine a 192.168.122.0/24 tiene il varco lontano da ogni altra sottorete locale, e contare le query contro quell'origine è economico se la minaccia ti interessa.

Falla sopravvivere a un riavvio e dimostra entrambe le metà

Una regola digitata in un prompt della shell scompare al prossimo avvio, e una regola caricata dopo che l'interfaccia VPN sta già passando traffico perde la corsa alla prima connessione. Metti la tabella nella configurazione nftables persistente dell'host, o in un'unità ordinata prima del servizio VPN, e controlla l'ordine invece di presumerlo.

La verifica richiede tre risposte separate. Conferma che la catena sia caricata e ordinata per prima, conferma che la voce conntrack mostri il mark in entrambe le direzioni e conferma che una ricerca dell'ospite restituisca un indirizzo. Poi conferma l'altra metà: il normale traffico web dell'ospite verso un host pubblico fallisce ancora mentre il tunnel è giù o bloccante. Se il DNS funziona e tutto il resto perde, la tua regola è più ampia di quella sopra.

Se le ricerche falliscono ancora dopo che il mark è a posto, resisti all'impulso di allargare l'origine. Controlla verso cosa inoltra dnsmasq, se il resolver dell'ospite punta a 192.168.122.1 o a un indirizzo pubblico che qualcuno ha digitato, e se la query raggiunge anche solo l'host. Marcare ammette il pacchetto e nient'altro, quindi un upstream cattivo o una rete virtuale rotta restano rotti per quante regole aggiungi.

Articoli correlati