Não pode isentar um programa de um host WireGuard com túnel completo editando rotas. As rotas escolhem um caminho por destino, e o que quer isentar é um processo, portanto o núcleo não tem com o que comparar. A abordagem viável é dar a esse processo o seu próprio contexto de rede: um espaço de nomes com a sua interface, os seus endereços e a sua rota predefinida, ligado ao host por um par veth. Executei isto em Ubuntu 24.04 com wireguard-tools 1.0.20210914, e o espaço de nomes nunca foi o problema — foram a política de encaminhamento do host e as regras de marcação do túnel.

Primeiro escolha o tipo de contexto de que precisa

Na prática surgem duas formas. Se o host corre um túnel completo e um programa tem de sair pelo caminho do ISP, constrói um segundo espaço de nomes, liga-o ao host e deixa o host encaminhar e traduzir o tráfego por ele. Se um espaço de nomes já transporta uma interface VPN e só precisa de um comando iniciado lá dentro, é o caso simples de ip netns exec e a maior parte do trabalho de encaminhamento já está feita.

Nenhuma das formas lhe dá uma regra limitada a um único identificador de processo. O Netfilter compara endereços, portas, marcas e interfaces; não existe tabela de encaminhamento por processo. A marcação pode orientar o tráfego, mas a marca tem de ser aplicada a pacotes que já identificou, e esse é o mesmo problema uma camada mais abaixo. Um espaço de nomes separa toda a pilha para essa árvore de processos, e é por isso que é a resposta habitual.

Se o requisito é mesmo que nada saia do túnel, pare o túnel em vez disso. O espaço de nomes existe para o caso misto: um programa fora, todo o resto dentro, na mesma máquina, ao mesmo tempo.

Construa o segundo contexto e ligue-o ao host

Uma disposição ilustrativa: o host tem uma interface WireGuard que transporta a rota predefinida, e um espaço de nomes de rede chamado clearnet ligado ao host por um par veth. Os endereços abaixo são exemplos.

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

Esse espaço de nomes pode agora alcançar o host e nada mais. O host tem de encaminhar o tráfego e reescrever o endereço de origem, porque 192.168.100.0/24 é privado e o router a montante não tem rota de regresso para dentro dele:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o <wan-interface> -j MASQUERADE

Confirme o lado do espaço de nomes antes de continuar.ip netns exec clearnet ip route deveria mostrar a rota veth e a rota predefinida através de 192.168.100.1, e um ping para esse endereço deveria responder. Se o ping para o endereço do host falhar, os endereços ou o estado da ligação estão errados e nenhuma regra de firewall ajudará.

Quando os nomes se resolvem mas não volta nada, leia FORWARD

A falha clássica parece um bug de encaminhamento: o espaço de nomes resolve um nome, o pacote sai e nunca chega uma resposta. Em hosts com uma política FORWARD de DROP — várias distribuições e a maioria das imagens endurecidas fazem-no — o pacote é descartado a caminho, e o erro que a aplicação imprime não diz nada sobre filtragem.

Leia a cadeia antes de acrescentar seja o que for:

iptables -S FORWARD
nft list chain inet filter forward

Depois admita o tráfego nos dois sentidos, com contadores, para poder ver se a regra alguma vez correspondeu:

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'

Uma regra com um contador de pacotes a zero não está no caminho. Ou os nomes das interfaces diferem do que supôs, ou uma regra anterior na cadeia aceitou, descartou ou devolveu o pacote primeiro. Corrija a ordem, não o texto da regra.

O tráfego de resposta é a metade que as pessoas esquecem. A regra de regresso precisa do mesmo nome veth mais uma correspondência de estado de ligação, ou uma aceitação de interface simples se mantiver a política aberta. Acrescente só a regra de saída e o sintoma original volta, com a sua regra nova ali parada e aparentemente correta.

Mantenha as regras de marcação do túnel fora do caminho novo

Este passo transforma um espaço de nomes que funciona num que tem fugas. As configurações de WireGuard instalam normalmente uma política de marca de firewall com as suas próprias regras de encaminhamento e uma tabela dedicada, pelo que os pacotes sem marca recaem na tabela principal enquanto os marcados usam a tabela do túnel. O tráfego encaminhado a partir do espaço de nomes é avaliado contra o encaminhamento por políticas à saída e, consoante a forma como essas regras foram escritas, pode cair na tabela do túnel.

Dois acrescentos separam os caminhos. Volte cedo na cadeia mangle para a sub-rede do espaço de nomes e acrescente uma regra baseada na origem que coloca essa sub-rede na 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

A prioridade 100 ordena-se antes das regras do túnel no meu host, por isso para essa origem decide a tabela normal. Não copie o número às cegas: as prioridades que wg-quick instala diferem entre versões e entre as configurações IPv4 e IPv6, por isso execute ip rule show e escolha uma prioridade que fique à frente das regras do túnel na sua máquina.

Verifique com uma pesquisa específica da origem em vez de confiar na lista de regras:

ip route get 1.1.1.1 from 192.168.100.2
ip netns exec clearnet ip route get 1.1.1.1

Se o primeiro comando relatar a interface WireGuard, a regra nova ainda não está à frente da política do túnel. Se relatar a interface WAN enquanto o segundo ainda mostra a rota predefinida veth, o host e o espaço de nomes não concordam e deve reler as duas tabelas de encaminhamento.

Inicie o processo que abre a ligação

Iniciar o comando é uma linha, mas inicie o processo que cria mesmo o socket.ip netns exec clearnet curl -s https://ifconfig.me é o teste honesto mais pequeno: mostra o endereço que o espaço de nomes apresenta ao mundo, não o que o host usaria.

Para um serviço, anexe o espaço de nomes por caminho para que o processo permaneça nele toda a vida:

[Service]
NetworkNamespacePath=/run/netns/clearnet

As aplicações gráficas são onde a abordagem de uma linha falha em silêncio. Um navegador iniciado a partir de um menu entrega muitas vezes o pedido a uma instância que já corre fora do espaço de nomes, pelo que a janela nova aparece e o tráfego continua a sair pelo túnel. Dê-lhe um perfil separado para que uma instância nova seja realmente criada e depois verifique o contexto do processo em vez de adivinhar:

readlink /proc/$(pgrep -f clearnet-profile | head -1)/ns/net
readlink /run/netns/clearnet

As duas saídas têm de coincidir. A mesma verificação funciona para qualquer programa de longa duração, e vale a pena fazê-la uma vez por aplicação em vez de assumir que o lançador fez o que queria.

A resolução de nomes precisa da sua própria decisão. Criar um espaço de nomes não lhe dá configuração de resolução; os ficheiros por espaço de nomes são suportados através de /etc/netns/<name>/resolv.conf e sem um herda um comportamento fácil de ler mal. O IPv6 precisa do mesmo tratamento: se o espaço de nomes não tiver rota predefinida v6 enquanto a aplicação prefere v6, os pedidos podem bloquear antes de recuar, o que parece um túnel partido.

Verifique o enquadramento, não só o endereço de saída

Um endereço público que funciona prova a rota, não todo o requisito. Percorra o resto por esta ordem:

  • ip netns exec clearnet ip route get 1.1.1.1 mostra a rota predefinida veth, não a interface WireGuard.
  • Os contadores FORWARD das duas regras aumentam enquanto um pedido decorre.
  • O processo da aplicação relata o inode do espaço de nomes que espera.
  • Após um reinício o espaço de nomes existe antes de o serviço arrancar; uma unidade que corra antes falha ou, pior, corre fora do espaço de nomes.

Depois decida o que deve acontecer quando o túnel cai. O espaço de nomes continua a funcionar, o que é o objetivo do exercício e também o risco: o programa isento permanece ligado enquanto todo o resto para. Registe isso como uma escolha de política e seja claro sobre o que a isenção não cobre — a identidade da conta, o estado guardado do navegador e o seu fornecedor de DNS ficam todos fora do alcance de um espaço de nomes de rede, e tratar a isenção como anonimato é o erro que sobrevive à configuração.

Artigos relacionados