Dois sites, uma sub-rede, um hub WireGuard: faça-o funcionar
As duas LAN estão em 10.10.7.0/24, pelo que o hub não pode escolher site por destino. Dê a cada serviço um alias e traduza no seu gateway.
Os dois sites usam a mesma faixa de LAN, e a sobreposição não é o que realmente quebra o projeto. O hub precisa de escolher um site usando apenas o endereço de destino, e dois destinos idênticos não lhe dão nada com que escolher. Renumerar um escritório que funciona para satisfazer um túnel costuma ser uma troca pior do que dar a cada serviço publicado um endereço distinto que o túnel consiga transportar. O projeto abaixo publica um serviço HTTPS por site e nada mais.
Por que a sobreposição não é o problema real
O WireGuard encaminha por destino: os AllowedIPs de um peer decidem qual peer recebe um pacote. Dois peers não podem anunciar ambos 10.10.7.0/24 sem que um deles ganhe todas as buscas. Isso é uma propriedade da tabela de peers e não do túnel, por isso a solução aqui é um plano de endereços e não um truque de encaminhamento.
O plano é parar de anunciar a LAN por completo. Anuncie em vez disso um alias por serviço, um endereço por site, e deixe o gateway de cada site traduzir esse alias para a sua aplicação real.
O utilizador encaminha dois endereços únicos, nunca vê o prefixo ambíguo, e nada muda em nenhum dos dois escritórios. Isso também declara a fronteira com honestidade: está a publicar um serviço HTTPS de cada site, não a fundir duas redes. As regras que se seguem mantêm-se pequenas porque a afirmação é estreita. Uma afirmação mais ampla exigiria regras mais amplas, e é assim que estes projetos se tornam complicados.
Dê a cada site um alias que o utilizador consiga encaminhar
Escolha endereços de uma faixa que não entre em conflito com nada na máquina do utilizador, no hub ou em qualquer das duas LAN. Aqui o hub é 10.66.0.1, o utilizador é 10.66.0.10, os gateways são 10.66.0.21 e 10.66.0.22, e os dois alias são 10.77.1.20 e 10.77.2.20. O hub publica cada alias através do peer que o possui, pelo que um pacote de saída dirigido a um alias só pode sair pelo site correspondente:
[Interface]
Address = 10.66.0.1/32
ListenPort = 51820
PrivateKey = HUB_KEY
[Peer]
PublicKey = USER_PUBLIC_KEY
AllowedIPs = 10.66.0.10/32
[Peer]
PublicKey = SITE_A_PUBLIC_KEY
AllowedIPs = 10.66.0.21/32, 10.77.1.20/32
[Peer]
PublicKey = SITE_B_PUBLIC_KEY
AllowedIPs = 10.66.0.22/32, 10.77.2.20/32
O lado do utilizador só precisa dos dois alias, o que mantém a configuração do cliente livre de ambos os prefixos de LAN. Nada nessa configuração menciona qualquer das LAN reais:
[Interface]
Address = 10.66.0.10/32
PrivateKey = USER_KEY
[Peer]
PublicKey = HUB_PUBLIC_KEY
Endpoint = hub.example.net:51820
AllowedIPs = 10.77.1.20/32, 10.77.2.20/32
PersistentKeepalive = 25
Cada gateway anuncia o hub e a origem do utilizador, nada mais, pelo que um site nunca aprende a LAN do outro. O keepalive mantém um mapeamento NAT no uplink do site; não autoriza tráfego, e a firewall continua a decidir o que é admitido. Copiar a configuração de um gateway para o outro é aceitável desde que a chave privada, o endereço de interface e o alias mudem todos.
O que o hub tem de permitir entre dois dos seus peers
O hub encaminha pacotes entre dois dos seus próprios peers, o que é uma decisão da cadeia forward e não uma decisão de entrada. Ative o encaminhamento IPv4 através do mecanismo habitual da plataforma e depois permita exatamente os pares de que o projeto precisa.
A regra abaixo permite ao utilizador um alias e uma porta, e permite o tráfego de retorno através do rastreio de ligações. Descarta tudo o resto no caminho forward, e esse é o ponto:
nft add table inet hub_transit
nft add chain inet hub_transit forward '{ type filter hook forward priority 0 ; policy drop ; }'
nft add rule inet hub_transit forward ct state established,related accept
nft add rule inet hub_transit forward iifname wg0 oifname wg0 tcp dport 443 ip saddr 10.66.0.10 ip daddr 10.77.1.20 accept
Dois detalhes merecem ser ditos porque causam falhas silenciosas. Um accept numa cadeia base não anula um drop noutra, por isso funda isto com a política existente em vez de o carregar ao lado. E o endereço de origem identifica o dispositivo, não a pessoa; mantenha a autenticação da aplicação separada da admissão na rede.
Onde um alias se torna um endereço real
O site A recebe um pedido para 10.77.1.20, reescreve o destino para a aplicação real e reescreve a origem para o seu próprio endereço de LAN para que a resposta possa voltar sem uma rota para o túnel. Fazer as duas traduções num só lugar mantém o resto da rede ignorante do alias. As regras abaixo são todo o mecanismo:
nft add table ip site_a_nat
nft add chain ip site_a_nat pre '{ type nat hook prerouting priority -100 ; policy accept ; }'
nft add chain ip site_a_nat post '{ type nat hook postrouting priority 100 ; policy accept ; }'
nft add rule ip site_a_nat pre iifname wg0 tcp dport 443 ip saddr 10.66.0.10 ip daddr 10.77.1.20 dnat to 10.10.7.20:443
nft add rule ip site_a_nat post iifname wg0 oifname lan0 tcp dport 443 ip saddr 10.66.0.10 ip daddr 10.10.7.20 snat to 10.10.7.2
A política forward do site A tem então de admitir o fluxo traduzido da interface do túnel para a interface de LAN, mais a direção de retorno. O hook forward vê o destino depois da tradução de destino e antes da reescrita de origem, por isso a regra nomeia o endereço da aplicação real. Leia esses dois hooks nessa ordem sempre que uma regra pareça não corresponder a nada. Uma regra forward escrita contra o alias nunca pode corresponder, porque o alias já não existe nesse hook.
O site B repete isto com o seu próprio alias e a sua própria chave. Não deve reutilizar a chave privada do site A, porque dois peers que partilham uma identidade são um erro de configuração difícil de ver e fácil de criar copiando um ficheiro. Mantenha os dois documentos do gateway idênticos exceto nos valores que têm de diferir, para que a diferença se destaque na revisão. Um ficheiro copiado é a origem habitual dessa falha.
A reescrita de origem tem um custo. A aplicação vê o gateway como seu cliente, pelo que os seus registos já não mostram que utilizador se ligou. Mantenha o rasto de auditoria do gateway, e não enfraqueça o início de sessão da aplicação para compensar uma identidade de rede que a tradução removeu.
Como provar que ambos os nomes publicados respondem
Dê a cada alias um nome DNS e configure a aplicação e o certificado para esse nome, porque a tradução não reescreve redirecionamentos nem URL absolutos incorporados. Use um nome por site para que uma discrepância de certificado nunca seja confundida com uma falha de encaminhamento.
Teste a partir do cliente real, confirme qual site respondeu, e teste também uma porta não autorizada. Use ligações novas após qualquer alteração de NAT, uma vez que o estado estabelecido mantém o mapeamento antigo:
wg show wg0 allowed-ips
sudo nft list ruleset
curl -sS -o /dev/null -w "%{http_code}\n" https://site-a.example.net/
Um alias vazio ou inesperado no primeiro comando significa que a seleção de peer está errada antes de qualquer regra de firewall importar. Se o alias estiver correto e o nome continuar a falhar, o problema passou para DNS e certificados. Assim que ambos os nomes respondem e a terceira porta permanece fechada, o projeto faz o que afirma: dois serviços publicados de forma estreita, não duas LAN fundidas.