Ambele site-uri folosesc același interval LAN, iar suprapunerea nu este ceea ce strică de fapt proiectarea. Hub-ul trebuie să aleagă un site doar după adresa de destinație, iar două destinații identice nu îi dau nimic cu ce să aleagă. Renumerotarea unui birou funcțional pentru a satisface un tunel este de obicei un schimb mai prost decât a da fiecărui serviciu publicat o adresă distinctă pe care tunelul o poate transporta. Proiectarea de mai jos publică un serviciu HTTPS pe site și nimic altceva.

De ce suprapunerea nu este problema reală

WireGuard transmite după destinație: AllowedIPs ale unui peer decid ce peer primește un pachet. Doi peers nu pot anunța amândoi 10.10.7.0/24 fără ca unul dintre ei să câștige fiecare căutare. Aceasta este o proprietate a tabelului de peers, nu a tunelului, motiv pentru care soluția aici este un plan de adrese și nu un truc de rutare.

Planul este să nu mai anunțăm deloc LAN-ul. Anunțați în schimb un alias pe serviciu, o adresă pe site, și lăsați gateway-ul fiecărui site să traducă acel alias în aplicația sa reală.

Utilizatorul rutează două adrese unice, nu vede niciodată prefixul ambiguu, și nimic nu se schimbă în niciunul dintre cele două birouri. Asta declară și granița cu onestitate: publicați un serviciu HTTPS din fiecare site, nu fuzionați două rețele. Regulile care urmează rămân mici pentru că afirmația este îngustă. O afirmație mai largă ar cere reguli mai largi, și exact așa devin aceste proiecte complicate.

Dați fiecărui site un alias pe care utilizatorul îl poate ruta

Alegeți adrese dintr-un interval care nu intră în conflict cu nimic de pe mașina utilizatorului, hub sau vreuna dintre cele două LAN-uri. Aici hub-ul este 10.66.0.1, utilizatorul este 10.66.0.10, gateway-urile sunt 10.66.0.21 și 10.66.0.22, iar cele două aliasuri sunt 10.77.1.20 și 10.77.2.20. Hub-ul publică fiecare alias prin peer-ul care îl deține, astfel încât un pachet de ieșire adresat unui alias poate pleca doar prin site-ul corespunzător:

[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

Partea utilizatorului are nevoie doar de cele două aliasuri, ceea ce menține configurația clientului lipsită de ambele prefixe LAN. Nimic din acea configurație nu menționează vreunul dintre LAN-urile reale:

[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

Fiecare gateway anunță hub-ul și sursa utilizatorului, nimic altceva, astfel încât un site nu află niciodată LAN-ul celuilalt. Keepalive menține o mapare NAT pe uplink-ul site-ului; nu autorizează trafic, iar firewall-ul decide în continuare ce se admite. Copierea configurației unui gateway în celălalt este în regulă atâta timp cât cheia privată, adresa de interfață și aliasul se schimbă toate.

Ce trebuie să permită hub-ul între doi dintre peers-ii săi

Hub-ul transmite pachete între doi dintre propriii peers, ceea ce este o decizie din lanțul forward și nu o decizie de intrare. Activați transmiterea IPv4 prin mecanismul obișnuit al platformei, apoi permiteți exact perechile de care are nevoie proiectarea.

Regula de mai jos permite utilizatorului un alias și un port, și permite traficul de retur prin urmărirea conexiunilor. Elimină tot restul pe calea forward, și acesta este ideea:

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

Două detalii merită menționate pentru că provoacă eșecuri silențioase. Un accept într-un lanț de bază nu anulează un drop în altul, așa că fuzionați acest lucru cu politica existentă în loc să îl încărcați alături. Iar adresa sursă identifică dispozitivul, nu persoana; țineți autentificarea aplicației separată de admiterea în rețea.

Unde un alias devine o adresă reală

Site-ul A primește o cerere pentru 10.77.1.20, rescrie destinația către aplicația reală și rescrie sursa către propria adresă LAN, astfel încât răspunsul să poată reveni fără o rută către tunel. Efectuarea ambelor traduceri într-un singur loc ține restul rețelei ignorant cu privire la alias. Regulile de mai jos sunt întregul mecanism:

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

Politica forward a site-ului A trebuie apoi să admită fluxul tradus de la interfața tunelului la interfața LAN, plus direcția de retur. Hook-ul forward vede destinația după traducerea destinației și înainte de rescrierea sursei, de aceea regula numește adresa aplicației reale. Citiți acele două hook-uri în această ordine ori de câte ori o regulă pare să nu se potrivească cu nimic. O regulă forward scrisă împotriva aliasului nu poate niciodată să se potrivească, pentru că aliasul nu mai există în acel hook.

Site-ul B repetă acest lucru cu propriul alias și propria cheie. Nu trebuie să reutilizeze cheia privată a site-ului A, pentru că doi peers care împart o identitate sunt o eroare de configurare greu de văzut și ușor de creat copiind un fișier. Țineți ambele documente de gateway identice, cu excepția valorilor care trebuie să difere, astfel încât diferența să iasă în evidență la revizuire. Un fișier copiat este originea obișnuită a acelei defecțiuni.

Rescrierea sursei are un cost. Aplicația vede gateway-ul ca pe clientul său, așa că logurile nu mai arată ce utilizator s-a conectat. Păstrați urma de audit a gateway-ului și nu slăbiți autentificarea aplicației pentru a compensa o identitate de rețea pe care traducerea a eliminat-o.

Cum să dovediți că ambele nume publicate răspund

Dați fiecărui alias un nume DNS și configurați aplicația și certificatul pentru acel nume, pentru că traducerea nu rescrie redirecționări sau URL-uri absolute încorporate. Folosiți un nume pe site, astfel încât o nepotrivire de certificat să nu fie niciodată confundată cu o defecțiune de rutare.

Testați din clientul real, confirmați ce site a răspuns și testați și un port neautorizat. Folosiți conexiuni noi după orice modificare NAT, deoarece starea stabilită păstrează maparea veche:

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 gol sau neașteptat în prima comandă înseamnă că selecția peer-ului este greșită înainte ca vreo regulă de firewall să conteze. Dacă aliasul este corect și numele tot eșuează, problema s-a mutat la DNS și certificate. Odată ce ambele nume răspund și al treilea port rămâne închis, proiectarea face ceea ce susține: două servicii publicate îngust, nu două LAN-uri fuzionate.

Articole similare