Kan klienter på to OpenVPN-servere nå hverandre?
To OpenVPN-servere lager to klientbassenger, ikke ett nettverk. Rut mellom dem med egne subnett, gjensidige ruter og en tydelig tillitsgrense.
Å sette opp en OpenVPN-server gir deg en annen plass klientene kan kople til, og ikke noe mer. Den setter ikke disse klientene på den første serverens nettverk, og alternativet som heter client-to-client endrer bare videresending inne i én serverprosess. De to bassengene blir ett nettverk når du ruter mellom dem, med vilje, med en eier for hver retning. Alt nedenfor forutsetter TUN-modus i brukerrommet med den interne videresendingen avslått, slik at kjernen tar beslutningen.
Myten: én kontoliste, ett nettverk
Autentisering og tilgjengelighet blandes sammen fordi begge bor i serverkonfigurasjonen. En bruker som kan logge på hvilken som helst av de to gatewayene ser, fra utsiden, ut som en bruker på ett system med to dører. Innsiden deler hver server ut adresser fra sitt eget basseng og installerer bare ruter for klientene den avslutter. Så en klient på gateway A som sender en pakke til en klient på gateway B, ber om en destinasjon som dens egen server aldri har hørt om. Pakken går til A sin standardrute, forlater tunnelen og kommer til en brannmur som aldri ble bedt om å tillate den.
Å legge til en andre server gir derfor ikke redundans, oppdagelse eller et delt kringkastingsdomene. Det gir et rutet nettverk som trenger en plan, og planen begynner med adressering.
Gi hver gateway sitt eget basseng og transitadresse
To områder som ikke kan overlappe noe annet, pluss en liten transitlenke mellom vertene, er hele adresseplanen. Hold transienten på et privat segment du kontrollerer, og skriv ned tallene før noen av serverne deler ut en lease.
| Gateway | Client pool | Transit address |
|---|---|---|
| gateway-a | 10.64.10.0/24 | 172.28.44.1/30 |
| gateway-b | 10.64.20.0/24 | 172.28.44.2/30 |
Motstå fristelsen til å gi begge serverne samme basseng slik at profilene forblir identiske. En kjernerute kan ikke si hvilken av to verter som for øyeblikket eier en vilkårlig adresse innenfor et delt område, så rutetabellen ville peke på én gateway og klienten kan være koplet til den andre. Grensesnittnavn er lokale konvensjoner, ikke delt tilstand. Begge vertene her kaller tunellenheten tun0 og transitlenken transit0, noe som er greit fordi ingen pakke bærer disse navnene.
Installer ruten på begge sider
Hver gateway trenger en rute til den andres basseng via transitadressen, og videresending må være på for at noen av dem skal fungere som hopp. Bekreft gjeldende tabell først, og legg deretter til oppføringen og gjør den varig gjennom vertens nettverksbehandler i stedet for en krok for gjenoppkobling.
sysctl net.ipv4.ip_forward
ip route add 10.64.20.0/24 via 172.28.44.2 dev transit0
ip route get 10.64.20.37
Speil dette på den andre verten med bassengene byttet om. Å legge til den samme ruten gjentatte ganger fra et urelatert skript er hvordan en vert ender opp med flere kopier og en mystisk endring neste gang noen leser tabellen. Hvis transitlenken selv er en tunnel, peker ruten på den tunnelens topologi, og hoppet må overleve gjenoppkoblingen. En transitadresse som forsvinner i tretti sekunder tar veien mellom bassengene med seg, noe som er en designegenskap det er verdt å si høyt i stedet for å oppdage.
Skyv klientruten uten å late som eierskap
Klienter trenger en rute til det eksterne bassenget, ellers sender deres eget operativsystem pakken til standardgatewayen og tunnelen ser den aldri. Serverkonfigurasjonen er det naturlige stedet å levere den.
push "route 10.64.20.0 255.255.255.0"
Sett speillinjen i den andre serverens konfigurasjon, kople deretter til en testklient på nytt og les tabellen dens. En klient som ignorerer skyvede ruter trenger sin egen godkjente konfigurasjon, og en rute som aldri kommer er ikke tilgangskontroll. Ikke gi en klient iroute for hele bassenget til den andre gatewayen. Det direktivet finnes for et subnett bak én tilkoplet klient, og å bruke det til å dekke over en manglende rute mellom gatewayene gir en server som tror den eier adresser den ikke kan nå.
Bevis én forespørsel og avvis en annen
Velg en reell operasjon, for eksempel HTTPS fra en klient på 10.64.10.21 til en tjeneste på 10.64.20.37, og tillat nøyaktig det på begge verter. Hver brannmur slipper forespørselen inn på innkommende side og det sporede svaret på retursiden; destinasjonens egen tjenestepolicy må fortsatt godta det.
iptables -A FORWARD -i tun0 -o transit0 -s 10.64.10.21 -d 10.64.20.37 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -i transit0 -o tun0 -d 10.64.10.21 -s 10.64.20.37 -p tcp --sport 443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Med gjensidige ruter er kilde-NAT unødvendig og aktivt skadelig her: å oversette kilden skjuler hvilken klient som sendte forespørselen og undergraver kildebasert policy på destinasjonssiden. Sjekk at en eksisterende masquerade-regel for internett-utgang ikke også fanger denne veien. Test deretter avvisningen. En tjeneste som skal holde seg lokal i basseng B må forbli utilgjengelig fra basseng A, og klientpar på samme gateway må også testes, ettersom videresendingspolicyen du nettopp endret gjelder dem også.
Én korrigering til av den mentale modellen: transitlenken bærer dekrypterte indre pakker, så den er en tillitsgrense og ikke en privat garanti. Hvis den krysser et nettverk du ikke kontrollerer, beskytt det hoppet med en godkjent kryptert tunnel og rut gjennom dens virkelige topologi. Ende-til-ende-TLS autentiserer fortsatt applikasjonen på egen hånd, og derfor bør den indre tjenesten fortsette å bruke det.