Ambos sitios usan el mismo rango de LAN, y la superposición no es lo que realmente rompe el diseño. El concentrador debe elegir un sitio usando solo la dirección de destino, y dos destinos idénticos no le dan nada con qué elegir. Renumerar una oficina que funciona para satisfacer un túnel suele ser un peor trato que dar a cada servicio publicado una dirección distinta que el túnel pueda transportar. El diseño de abajo publica un servicio HTTPS por sitio y nada más.

Por qué la superposición no es el problema real

WireGuard reenvía por destino: las AllowedIPs de un peer deciden qué peer recibe un paquete. Dos peers no pueden anunciar ambos 10.10.7.0/24 sin que uno de ellos gane todas las búsquedas. Eso es una propiedad de la tabla de peers y no del túnel, por eso la solución aquí es un plan de direcciones y no un truco de enrutamiento.

El plan es dejar de anunciar la LAN por completo. Anuncie en su lugar un alias por servicio, una dirección por sitio, y deje que la puerta de enlace de cada sitio traduzca ese alias a su aplicación real.

El usuario enruta dos direcciones únicas, nunca ve el prefijo ambiguo, y nada cambia en ninguna de las dos oficinas. Eso también dice la frontera con honestidad: está publicando un servicio HTTPS desde cada sitio, no fusionando dos redes. Las reglas que siguen se mantienen pequeñas porque la afirmación es estrecha. Una afirmación más amplia necesitaría reglas más amplias, y así es como estos diseños se complican.

Dé a cada sitio un alias que el usuario pueda enrutar

Elija direcciones de un rango que no entre en conflicto con nada en la máquina del usuario, el concentrador ni ninguna de las dos LAN. Aquí el concentrador es 10.66.0.1, el usuario es 10.66.0.10, las puertas de enlace son 10.66.0.21 y 10.66.0.22, y los dos alias son 10.77.1.20 y 10.77.2.20. El concentrador publica cada alias a través del peer que lo posee, así que un paquete saliente dirigido a un alias solo puede salir por el sitio correspondiente:

[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

El lado del usuario solo necesita los dos alias, lo que mantiene la configuración del cliente libre de ambos prefijos de LAN. Nada en esa configuración menciona ninguna de las LAN reales:

[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 puerta de enlace anuncia el concentrador y el origen del usuario, nada más, así que un sitio nunca aprende la LAN del otro. El keepalive mantiene una asignación NAT en el enlace ascendente del sitio; no autoriza tráfico, y el cortafuegos sigue decidiendo qué se admite. Copiar la configuración de una puerta de enlace a la otra está bien siempre que la clave privada, la dirección de interfaz y el alias cambien todos.

Qué debe permitir el concentrador entre dos de sus peers

El concentrador reenvía paquetes entre dos de sus propios peers, lo que es una decisión de la cadena forward y no una decisión de entrada. Habilite el reenvío IPv4 mediante el mecanismo habitual de la plataforma y luego permita exactamente los pares que el diseño necesita.

La regla de abajo permite al usuario un alias y un puerto, y permite el tráfico de vuelta mediante el seguimiento de conexiones. Descarta todo lo demás en la ruta forward, y ese es el punto:

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

Merece la pena señalar dos detalles porque causan fallos silenciosos. Un accept en una cadena base no anula un drop en otra, así que fusione esto con la política existente en lugar de cargarlo al lado. Y la dirección de origen identifica el dispositivo, no a la persona; mantenga la autenticación de la aplicación separada de la admisión en la red.

Dónde un alias se convierte en una dirección real

El sitio A recibe una petición para 10.77.1.20, reescribe el destino a la aplicación real y reescribe el origen a su propia dirección de LAN para que la respuesta pueda volver sin una ruta hacia el túnel. Hacer las dos traducciones en un solo lugar mantiene al resto de la red ignorante del alias. Las reglas de abajo son todo el 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

La política forward del sitio A debe entonces admitir el flujo traducido desde la interfaz del túnel a la interfaz de LAN, más la dirección de vuelta. El hook forward ve el destino después de la traducción de destino y antes de la reescritura de origen, por eso la regla nombra la dirección de la aplicación real. Lea esos dos hooks en ese orden siempre que una regla parezca no coincidir con nada. Una regla forward escrita contra el alias nunca puede coincidir, porque el alias ya no existe en ese hook.

El sitio B repite esto con su propio alias y su propia clave. No debe reutilizar la clave privada del sitio A, porque dos peers que comparten una identidad son un error de configuración difícil de ver y fácil de crear copiando un archivo. Mantenga ambos documentos de puerta de enlace idénticos salvo los valores que deben diferir, para que la diferencia destaque en la revisión. Un archivo copiado es el origen habitual de esa falla.

La reescritura de origen tiene un coste. La aplicación ve la puerta de enlace como su cliente, así que sus registros ya no muestran qué usuario se conectó. Conserve el rastro de auditoría de la puerta de enlace, y no debilite el inicio de sesión de la aplicación para compensar una identidad de red que la traducción eliminó.

Cómo demostrar que ambos nombres publicados responden

Dé a cada alias un nombre DNS y configure la aplicación y el certificado para ese nombre, porque la traducción no reescribe redirecciones ni URL absolutas incrustadas. Use un nombre por sitio para que una discrepancia de certificado nunca se confunda con una falla de enrutamiento.

Pruebe desde el cliente real, confirme qué sitio respondió y pruebe también un puerto no autorizado. Use conexiones nuevas después de cualquier cambio de NAT, ya que el estado establecido conserva la asignación antigua:

wg show wg0 allowed-ips
sudo nft list ruleset
curl -sS -o /dev/null -w "%{http_code}\n" https://site-a.example.net/

Un alias vacío o inesperado en el primer comando significa que la selección de peer es incorrecta antes de que importe cualquier regla de cortafuegos. Si el alias es correcto y el nombre sigue fallando, el problema se ha trasladado a DNS y certificados. Una vez que ambos nombres responden y el tercer puerto permanece cerrado, el diseño hace lo que afirma: dos servicios publicados de forma estrecha, no dos LAN fusionadas.

Artículos relacionados