Problema e objetivo
Os pacotes que fazem parte do envelope WireGuard (os pacotes UDP que transportam a carga criptografada) não estão sujeitos ao próprio encapsulamento do encapsulamento, usando o mesmo IP dentro do túnel como fora do túnel.
Método
Como a pilha de roteamento (ip route, ip rule ...) está trabalhando na camada 3 (IP) e não na camada 4 (UDP, usada pelo envelope), isso não pode ser resolvido apenas com a pilha de roteamento sem ajuda extra para distinguir os pacotes de envelope dos pacotes de "dados".
Felizmente é possível marcar um pacote com uma marca (puramente internamente, no skbuff do pacote, claro que não no fio). A tag pode ser reutilizada como fwmark para a pilha de roteamento. As facilidades (que eu conheço) capazes de marcar pacotes são iptables, nftables ... e o próprio WireGuard.
Como o Wireguard, no entanto, pode marcar pacotes após o encapsulamento, não há necessidade de usar o iptables / nftables como ajuda extra para o roteamento.
Atualmente, há uma limitação irritante no wireguard (que certamente existe por boas razões, provavelmente relacionadas à sua manipulação de roteamento): não consegui encontrar uma maneira de definir dois peers com os mesmos valores permitidos ips. Portanto, não é possível definir simplesmente:
AllowedIps = 172.29.244.0/25,172.29.248.128/25
em todos os endpoints. Tentar isso excluirá os ips permitidos nos pontos de extremidade anteriores com o mesmo valor. Definir qualquer outro intervalo de sobreposição (por exemplo, alterar a máscara) será aceito, mas impedirá que alguns dos pares de sobreposição funcionem. Claro que permitir apenas o IP do terminal remoto único funciona. Essa é a única maneira de a malha inteira funcionar corretamente.
Solução
Distinguir entre pacotes de envelope e pacotes encapsulados com uma marca. Não é necessário informar qual porta UDP deve ser, o WireGuard trata essa parte. Use esta marca para fazer uma "exceção à exceção" para a escolha da rota.
Escolhas feitas
De acordo com o comentário do OP, não é necessário encaminhamento de pacotes, portanto, nenhum encaminhamento foi testado.
A escolha feita aqui é marcar os pacotes que não entrarão no túnel com a ajuda do WireGuard (uma outra solução de trabalho, usando iptables em vez de WireGuard para marcar pacotes, poderia fazer o oposto e marcar os pacotes que entram no túnel).
Instruções
Exemplo de configuração:
# ip -4 -br addr show dev ens160
ens160@if7 UP 172.29.248.132/25
# ip route
default via 10.0.3.1 dev eth0
10.0.3.0/24 dev eth0 proto kernel scope link src 10.0.3.147
172.29.244.0/25 via 172.29.248.129 dev ens160
172.29.248.128/25 dev ens160 proto kernel scope link src 172.29.248.132
# wg show wg0
interface: wg0
public key: 7FsVTBuIDNQsWj9flHWwMt+kCaE8urEE9bCwcvz6CBM=
private key: (hidden)
listening port: 51820
peer: +NJdQr+piwid1iuC58rbnXFgGo/vZ9d8Gs3xvl3/TxI=
endpoint: 172.29.248.134:51820
allowed ips: (none)
transfer: 14.74 KiB received, 34.35 KiB sent
peer: KrZWEupjHGoHTywwWhg4XXQSyFl/disav7/pyhOK/1Q=
endpoint: 172.29.244.20:51820
allowed ips: (none)
transfer: 11.06 KiB received, 15.65 KiB sent
Como no final tudo pode passar pelo túnel reutilizando os mesmos IPs, a rede 192.168.2.0/24 não é mais usada. Como nenhuma regra de roteamento fará referência a esses IPs, eles podem até ser removidos: o wg0 terá um IP zero (ainda é aceitável mantê-los se desejado):
# ip addr flush dev wg0
Configure o wg0 para marcar os pacotes de envelope com algum valor arbitrariamente escolhido (aqui 9):
# wg set wg0 fwmark 9
Configure cada host do WireGuard para aceitar o IP do terminal no túnel, esse é o objetivo:
# wg show wg0|awk 'BEGIN { RS="\n\n" } /^peer/ { printf "wg set wg0 peer %s allowed-ips %s\n",$2,$4 }'|cut -d: -f1 | sh
O que agora dá:
# wg show wg0
interface: wg0
public key: 7FsVTBuIDNQsWj9flHWwMt+kCaE8urEE9bCwcvz6CBM=
private key: (hidden)
listening port: 51820
fwmark: 0x9
peer: +NJdQr+piwid1iuC58rbnXFgGo/vZ9d8Gs3xvl3/TxI=
endpoint: 172.29.248.134:51820
allowed ips: 172.29.248.134/32
transfer: 14.74 KiB received, 34.35 KiB sent
peer: KrZWEupjHGoHTywwWhg4XXQSyFl/disav7/pyhOK/1Q=
endpoint: 172.29.244.20:51820
allowed ips: 172.29.244.20/32
transfer: 11.06 KiB received, 15.65 KiB sent
Adicione rotas na tabela de roteamento (escolhida arbitrariamente) 200, especificando o IP do host como fonte (para evitar que um IP de uma interface não relacionada seja infelizmente escolhido) ...
... apenas uma vez, rotas para ambas as LANs, mas isso exigirá o uso do WireGuard para qualquer tráfego IP com qualquer par nas LANs:
# localip=$(ip -4 -br addr show dev ens160|awk '{ print $3 }'|cut -d/ -f1)
# ip route add 172.29.244.0/25 dev wg0 table 200 src $localip
# ip route add 172.29.248.128/25 dev wg0 table 200 src $localip
O que dá:
# ip route show table 200
172.29.244.0/25 dev wg0 scope link src 172.29.248.132
172.29.248.128/25 dev wg0 scope link src 172.29.248.132
... adicione rotas por pares:
# localip=$(ip -4 -br addr show dev ens160|awk '{ print $3 }'|cut -d/ -f1)
# wg show wg0|awk 'BEGIN { RS="\n\n" } /^peer/ { printf "ip route add %s dev wg0 table 200 src %s\n",gensub(":.*$","",1,$4),localip }' localip=$localip | sh
O que dá em vez disso aqui:
# ip route show table 200
172.29.244.20 dev wg0 scope link src 172.29.248.132
172.29.248.134 dev wg0 scope link src 172.29.248.132
Corrija antecipadamente os problemas de galinha e ovo que seriam introduzidos pela regra após este, usando diretamente a tabela de roteamento principal para os pacotes marcados por WireGuard (aqueles pacotes 51820 / UDP):
# ip rule add priority 32000 fwmark 9 lookup main
"Inserir" após uma consulta à tabela 200. Na verdade, somente os pacotes com as rotas definidas acima para o WireGuard corresponderão e usarão o túnel por meio do wg0, outros pacotes continuarão para a tabela principal (normal):
# ip rule add priority 32100 lookup 200
Essa é a regra 32100 e a tabela 200 que substituem o roteamento usual feito dentro do wg0 quando os IPs são definidos nele.
O que agora dá:
# ip rule
0: from all lookup local
32000: from all fwmark 0x9 lookup main
32100: from all lookup 200
32766: from all lookup main
32767: from all lookup default
Infelizmente, o filtro de caminho inverso agora é acionado para o tráfego de entrada não-WireGuard proveniente da interface normal (aqui ens160) quando wg0 agora seria esperado. Isso inclui pacotes de resposta ARP necessários para encontrar pares na mesma LAN, bem como o gateway para a outra LAN (não tenho uma boa explicação sobre isso). Então rp_filter deve ser configurado para o modo solto para a interface normal (aqui ens160):
echo 2 > /proc/sys/net/ipv4/conf/ens160/rp_filter
Com essas configurações repetidas nos outros peers, todos os peers podem se comunicar entre si usando seu próprio IP, como se não houvesse túnel (em uma malha potencialmente usando até n * (n-1) / 2 túneis).
Exemplo: o host recebe um único ping e responde:
# tcpdump -n -s0 -i wg0 -p
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wg0, link-type RAW (Raw IP), capture size 262144 bytes
05:22:51.553463 IP 172.29.244.20 > 172.29.248.132: ICMP echo request, id 2083, seq 1, length 64
05:22:51.553525 IP 172.29.248.132 > 172.29.244.20: ICMP echo reply, id 2083, seq 1, length 64
Enquanto no roteador, o tráfego criptografado visto é (com alguma sobrecarga, provavelmente porque não houve atividade recente):
# tcpdump -n -s0 -i br248 -p
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br248, link-type EN10MB (Ethernet), capture size 262144 bytes
05:22:51.553317 ARP, Request who-has 172.29.248.132 tell 172.29.248.129, length 28
05:22:51.553358 ARP, Reply 172.29.248.132 is-at 2e:02:6e:cf:6d:4f, length 28
05:22:51.553383 IP 172.29.244.20.51820 > 172.29.248.132.51820: UDP, length 128
05:22:51.553583 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 128
05:22:51.554112 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 148
05:22:51.555198 IP 172.29.244.20.51820 > 172.29.248.132.51820: UDP, length 92
05:22:51.555748 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 32