Tre Linux-verter, ett design: en offentlig tilgjengelig OpenVPN-hub, en forbrukerbærbar og en utgangsmaskin bak en vanlig hjemmeruter som ikke videresender noe innover. Utgangen ringer selv til huben. Deretter går forbrukerens internettrafikk inn i tunnelen på den bærbare og ut gjennom utgangens egen uplink. Alt overraskende ved dette følger av én detalj: utgangen startet forbindelsen, så veien innover finnes allerede, og det trengs ingen portvideresending for å lage den.

Det følgende følger pakkens vei framfor konfigurasjonsrekkefølgen, fordi konfigurasjonen først gir mening når man vet hvilken komponent som eier hvilken beslutning. Hvert lag eier nøyaktig én beslutning, og feilene samler seg der to lag antas å være ett.

To transportøkter, én indre vei

Hver vert holder sin egen ytre forbindelse til huben, og ingen av dem kjenner den andre. Forbrukerens trafikk til internett er en separat indre strøm som tilfeldigvis bæres inne i forbrukerens tunnel og deretter sendes ut igjen fra utgangens tunnel. Det er denne indre strømmen huben må rute, og den utgangen må videresende.

outer: consumer --TLS--> hub
outer: exit     --TLS--> hub
inner: consumer --tun--> hub --internal--> exit --tun--> uplink

Fordi begge de ytre forbindelsene går utover fra klientsiden, ser utgangens ruter aldri en innkommende SYN og trenger aldri en destinasjons-NAT-regel. Den må bare holde den etablerte transporten i live, noe den allerede gjør for enhver langvarig forbindelse. Ingenting på det offentlige internettet må først nå utgangen, og derfor er en dynamisk adresse på den uplinken ikke noe problem. Ruteren må fortsatt tillate den utgående økten, men det er den samme tillatelsen en nettleser allerede bruker.

Hva iroute faktisk installerer inne i serveren

Huben er den eneste enheten som avgjør hvilken peer som eier hvilken destinasjon, og den tar den beslutningen i sin egen brukertilstands-rutetabell, ikke i kjernens. En client-config-dir-oppføring for utgangen med navnet exit-node kan kreve standardprefikset der:

# /etc/openvpn/server/ccd/exit-node
iroute 0.0.0.0 0.0.0.0

Den linjen forteller serverprosessen "indre pakker med enhver destinasjon tilhører denne klienten". Den legger ikke til en standardrute i hubens operativsystem og gjør ikke huben til en internett-gateway. OpenVPN 2.6-referanse holder klientspesifikk intern ruting og kjerneruting som separate mekanismer, og den separasjonen er grunnen til at designet virker uten å røre hubens standardrute.

Forbrukeren trenger den speilvendte instruksjonen, levert som push, slik at dens egen trafikk går inn i tunnelen i stedet for ut gjennom dens lokale gateway. Med subnettopologi er poolen en tilkoblet rute på utgangens tun-enhet, så returretningen trenger ingen ekstra push; det utgangen ikke må motta, er omdirigeringen nedenfor, som ville sende dens egen uplinktrafikk tilbake i tunnelen den prøver å bruke. Send den bare til forbrukeren, og les de anvendte rutene på klienten i stedet for å stole på at CCD-filen ble valgt.

# /etc/openvpn/server/ccd/consumer-01
push "redirect-gateway def1"

Utgangens kjerne gjør videresendingen

Inne i utgangen ankommer en pakke fra forbrukeren på tun-grensesnittet, adressert til en eller annen internettvert. Kjernen slår opp i rutetabellen, finner den virkelige uplinken som beste treff og bruker deretter to uavhengige policyer: kan denne pakken videresendes i det hele tatt, og kan den forlate det grensesnittet med den kildeadressen. Videresending er en sysctl, og den er av som standard på mange distribusjoner.

Så utgangen trenger vedvarende aktivert IPv4-videresending, en regel som slipper forbrukerens tunnelkilder til mot uplinken, og returveien tilbake gjennom tun. Å aktivere videresending for hele verten endrer også oppførselen til alt annet som rutes gjennom den, og derfor bør regelen navngi kildene og grensesnittene i stedet for å akseptere alt.

Returveien kjøpes av kildeoversettelse

En internettvert har ingen rute til en 10.90.0.x-adresse, så svar ville bli forkastet før de nådde utgangen. Å skrive om kilden mens pakken forlater uplinken løser det, og tilkoblingssporing reverserer omskrivingen på veien tilbake.

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 10.90.0.0/24 -o enp1s0 -j MASQUERADE
ip -4 route get 10.90.0.9   # run on the exit: must point at the tun

Regelen ovenfor er et utgangspunkt for ett uplink-grensesnitt, ikke en brannmurpolicy. Begrens kilden til tildelingene du faktisk har autorisert, og hold utgangens egen inngangspolicy atskilt, slik at maskering av tunneltrafikk ikke stille eksponerer lokale tjenester. På en vert med dynamisk uplinkadresse sparer maskeringen deg også for å spore adressen manuelt.

Hvor huben kan håndheve og hvor den ikke kan

Med client-to-client og den tradisjonelle brukerroms-datastien overleverer huben indre pakker mellom peers inne i serverprosessen. De passerer aldri hubens kjerne-FORWARD-kjede, så en kjerneregel der kan ikke begrense peer-til-peer-transitt, uansett hvor nøye den er skrevet. Håndhevelse må ligge i serverens egen policy: hvem som får koble til, hvilken CCD-fil de får, og om utgangens standardeierskap i det hele tatt gis.

Derfor er en standard-iroute en bred tillitsbeslutning. Utgangen må legitimt akseptere returtrafikk fra vilkårlige internettadresser, og den må være en maskin du kontrollerer, patcher og overvåker. Å gi samme eierskap til en peer du ikke ville gitt en ruter er feilen dette designet inviterer til.

Medlemskap er den egentlige kontrollen. Enhver klient som kan konfigurere sine egne ruter, kan prøve å bruke utgangen, så å begrense hvem som får koble til, eller hvilke peers utgangen skal betjene, er en del av designet og ikke en ettertanke.

Feile trygt når utgangen forsvinner

Ta utgangen offline, og det interne standardeierskapet forsvinner med økten. Det som ikke må skje, er at huben stille blir erstatningsutgangen: ingen standardrute fra VPN-poolen til hubens uplink, og ingen bred maskeringsregel på huben som gjerne ville videresendt den samme trafikken. Test den feilen med vilje, og test deretter gjenoppretting med en fersk strøm i stedet for en side som allerede var åpen.

# on the consumer, with the exit up and then down
ip -4 route get 1.1.1.1
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com

Hvis forbrukerens trafikk fortsatt når internett etter at utgangen er borte, bærer noe annet den, og grensen du hadde tenkt på finnes ikke. Behandle DNS og IPv6 også som separate beslutninger: en IPv4-rute pluss maskering sier ingenting om AAAA-trafikk, og en resolver som huben skyver på, vil svare fra der forespørselen faktisk forlater.

Relaterte artikler