WireGuard aninhado: o salto intermédio não consegue responder ao próprio porto
Quando o salto intermédio envia tudo para um único túnel, as respostas ao seu serviço de entrada saem pelo caminho errado. Uma regra de porto de origem na interface corrige isso.
Três saltos WireGuard chegam a uma rede sem endereço público, e então a máquina intermédia deixa de responder no porto em que devia escutar. O túnel em frente continua a funcionar, o anfitrião remoto continua a responder, e apenas o servidor intermédio se calou do exterior. Essa combinação é confusa precisamente porque é autoinfligida: o salto intermédio obedece à sua própria tabela de encaminhamento, e a tabela envia as suas respostas na direção errada.
Uma cadeia que funciona até falares com a caixa intermédia
Tomemos uma cadeia ilustrativa: o cliente A chega ao servidor B em UDP 500, e B segue para o servidor C em UDP 500. C só aceita tráfego do endereço do seu único par, o que o torna uma folha e mantém o seu comportamento simples. B não é uma folha, e tudo o que é interessante nesta falha acontece ali.
A distinção importa porque os papéis de folha e de intermédio puxam em direções opostas. Uma folha pode enviar tudo para um único túnel sem consequências, já que nada mais depende dela. Um salto intermédio é ao mesmo tempo um ponto final para clientes e um cliente para o lado remoto, e esses dois trabalhos querem encaminhamento diferente.
Porque é que a resposta sai pelo túnel
Em B, a interface virada para C transporta AllowedIPs = 0.0.0.0/0 juntamente com a rota predefinida correspondente. Por isso, cada pacote que B origina entra nesse túnel, a menos que algo mais específico tenha prioridade.
Um pacote de A endereçado a B chega e é aceite, porque B é o destino e a entrega local acontece primeiro. A resposta é um pacote completamente novo gerado localmente e dirigido ao endereço público de A, e esse destino corresponde à rota predefinida para o túnel. C recebe-o, não possui esse endereço e descarta-o.
O sintoma lê-se como um problema de firewall ou uma incompatibilidade de chave, e nenhum dos dois é verdade aqui. Uma captura no túnel em direção a C mostra as respostas a seguirem na direção errada. Essa única observação poupa mais tempo do que qualquer quantidade de leitura de configuração, por isso anota-a antes de começares a mudar chaves. Quem não viu a captura vai assumir que o túnel em si está avariado.
A reparação estreita: regras de política que correspondem a um porto de origem
As respostas do socket de escuta de B saem com o porto de origem 500. Uma regra de política pode corresponder a isso e devolver esses pacotes à tabela normal:
ip rule add sport 500 table main priority 100
ip rule add sport 8080 table main priority 101
As regras de política são consultadas por ordem de prioridade, e a tabela principal está em 32766, por isso uma regra em 100 é perguntada antes de a rota predefinida do túnel ter algo a dizer. Acrescenta uma entrada por cada porto que tem de permanecer acessível do exterior e nada mais, para que o tráfego reencaminhado continue a usar o túnel para o qual foi construído.
Conhece o limite deste truque. O seletor sport corresponde a pacotes gerados localmente, o que cobre exatamente o caso da resposta e deliberadamente não cobre tráfego que B apenas reencaminha por outra pessoa. Um serviço alojado atrás de B continua a precisar da sua própria resposta, e fingir o contrário produz uma correção que funciona para o primeiro serviço e falha para o segundo.
Dá um dono à regra
Uma regra escrita numa linha de comandos desaparece na próxima vez que a interface for reconstruída. Numa configuração WireGuard, coloca-a onde a interface é criada e removida:
PostUp = ip rule add sport 500 table main priority 100
PostDown = ip rule del sport 500 table main priority 100
Se o NetworkManager, um gancho da distribuição ou um ponto de entrada de contentor for o dono da interface, o par pertence a esse dono e não a um ficheiro editado à mão. Verifica as regras efetivas depois de uma reconexão, não apenas depois do primeiro arranque, porque o primeiro arranque é o caso que funciona sempre.
Compara as alternativas com honestidade
A regra de porto de origem é uma de quatro saídas, e é a mais estreita de todas. Tem a vantagem de não tocar em nada na política do túnel, e é por isso que costuma sobreviver a alterações posteriores. As correções estreitas também falham ruidosamente quando deixam de se aplicar, enquanto uma exceção ampla continua a funcionar em silêncio muito depois de a razão ter desaparecido. Essa diferença importa mais do que a elegância quando outra pessoa é dona da caixa dentro de dois anos.
| Approach | What it costs | Where it breaks |
|---|---|---|
| Source-port policy rule | One rule per exposed port | Anything B forwards rather than originates |
| Destination exception route | A route pinned to specific client addresses | Clients whose address changes |
| Stop full-tunnelling on B | Loses the catch-all path toward C | Designs that depend on it |
| Split into two tunnels | More interfaces and more policy | Nothing, at the cost of complexity |
Verifica a partir de ambas as pontas depois de escolheres. A partir de A, inicia uma ligação ao porto de B e mantém-na ocupada durante um bocado. Em B, faz com que o kernel justifique o caminho da resposta com algo como ip route get <address-of-A> sport 500, e confirma que nomeia a interface WAN e não o túnel. Depois disso, verifica que algo atrás de C ainda responde através da cadeia, o que prova que a exceção se manteve estreita em vez de se tornar um desvio. Por fim, regista os portos nas notas de conceção, ou o próximo operador redescobrirá isto noutro serviço.