Corrigir o DNS do convidado libvirt bloqueado por um firewall VPN baseado em marca
Um firewall VPN baseado em marca descarta o DNS dos convidados antes de uma cadeia de filtro vê-lo. Uma regra de prioridade mangle marca a consulta e a resposta, sem abrir sua LAN.
Os convidados na rede libvirt padrão resolvem nomes perfeitamente até a interface WireGuard subir, e então toda consulta trava no mesmo ponto. dnsmasq ainda está escutando em 192.168.122.1:53, o convidado ainda tem esse endereço como resolvedor, e a consulta ainda chega. O que mudou é que a própria consulta upstream do host, ou a resposta a ela, agora é descartada por uma regra avaliada antes de qualquer cadeia de filtro que você pensaria em editar. A saída é uma marca aplicada cedo o bastante, numa conexão que a resposta herda.
Os convidados perdem DNS no momento em que o túnel sobe
Confirme o formato antes de mudar qualquer coisa. Derrube o túnel, execute dig @192.168.122.1 example.com de um convidado e veja-o responder. Suba o túnel, repita e veja-o estourar o tempo. Esse par de resultados elimina uma rede libvirt quebrada, um endereço de resolvedor errado e um dnsmasq morto num único passo.
Depois olhe o lado do host. Se o dnsmasq registra a consulta e o encaminhamento upstream dela, o pacote chegou e a falha está na saída. Se o dnsmasq nunca registra nada, a consulta do convidado está sendo descartada na entrada e a exceção pertence a um gancho diferente do que este artigo marca.
Por que uma regra accept numa cadeia posterior nunca dispara
Um firewall VPN baseado em marca decide olhando a marca do pacote ou a marca da conexão, não o seu endereço de origem. Qualquer coisa que chegue na interface física sem a marca esperada é recusada, e essa recusa acontece no conjunto de regras que detém o teste de marca. ip saddr 192.168.122.0/24 accept linha adicionada a alguma cadeia posterior simplesmente nunca é consultada para esse pacote, e é por isso que a regra óbvia parece correta e não muda nada.
Alargá-la até algo funcionar é a segunda armadilha. Aceitar toda a sub-rede libvirt no caminho de entrada do host abre todos os serviços do host para os convidados, quando a necessidade real é uma única porta.
O mecanismo que torna possível uma exceção estreita é o rastreamento de conexões. Quando você define ct mark num pacote, o valor é guardado na entrada de conntrack e não apenas no pacote, então todo pacote daquela conexão o carrega depois, incluindo a resposta do host de volta ao convidado. É esse o truque inteiro: marque o pedido uma vez, e o caminho de retorno já está marcado.
Marque a consulta antes de a tabela VPN vê-la
Coloque a exceção na própria tabela, para que um leitor posterior a encontre sem analisar as regras da 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 é negativa, o que coloca esta cadeia à frente das cadeias de filtro comuns que o pacote da VPN instala na prioridade zero. É a ordem dos ganchos que torna a regra eficaz; a mesma regra numa cadeia que vem depois da cadeia da VPN é só decoração.
O número da marca em si não é portátil. Pegue o valor que as regras da VPN instaladas aceitam para o próprio tráfego delas, leia-o do conjunto de regras em execução e use esse. Uma marca errada produz uma regra que carrega limpa, casa com toda consulta e não admite nada.
Mantenha o buraco da largura da porta 53
Como está escrito, isto permite DNS da sub-rede libvirt para o host sobre TCP ou UDP na porta 53 e nada mais. Não deixa os convidados alcançarem a internet fora do túnel, e não deixa o host abrir conexões na direção dos convidados. Se um convidado precisar de outro serviço do host depois, acrescente uma regra separada nomeando essa porta de destino em vez de relaxar esta.
Seja honesto sobre o que está trocando. Um convidado que alcança um resolvedor também pode tunelar dados arbitrários por consultas DNS, e esta exceção é uma fenda deliberada na fronteira da VPN, não uma declaração de que a rede local é confiável. Restringir a origem a 192.168.122.0/24 mantém a fenda longe de toda outra sub-rede local, e contar consultas contra essa origem é barato se a ameaça importa para você.
Faça com que sobreviva ao reboot e comprove as duas metades
Uma regra digitada num prompt de shell desaparece no próximo boot, e uma regra carregada depois que a interface VPN já está passando tráfego perde a corrida na primeira conexão. Ponha a tabela na configuração persistente de nftables do host, ou numa unidade ordenada antes do serviço da VPN, e verifique a ordem em vez de supor.
A verificação precisa de três respostas separadas. Confirme que a cadeia está carregada e ordenada primeiro, confirme que a entrada de conntrack mostra a marca nos dois sentidos, e confirme que uma consulta do convidado devolve um endereço. Depois confirme a outra metade: o tráfego web comum do convidado para um host público ainda falha enquanto o túnel está caído ou bloqueando. Se o DNS funciona e todo o resto vaza, sua regra é mais ampla que a de cima.
Se as consultas ainda falham depois que a marca está no lugar, resista à vontade de alargar a origem. Verifique para onde o dnsmasq encaminha, se o resolvedor do convidado aponta para 192.168.122.1 ou para um endereço público que alguém digitou, e se a consulta chega ao host. Marcar admite o pacote e nada mais, então um upstream ruim ou uma rede virtual quebrada continua quebrado por mais regras que você acrescente.