En klient ringer opp OpenVPN-serveren på en Compute Engine-VM, statusvinduet sier tilkoblet, og en ping til en vert i VPC-en ender fortsatt ingen steder. Instinktet er å legge til enda en push-linje, og det løser det aldri. Compute Engine bestemmer hvor pakker tar veien ut fra sin egen rutetabell og ut fra adressene et VM-grensesnitt faktisk har, så en tunnelpool som VM-en ikke eier, er en pool som ingen leverer til.

Følg den feilende pakken i stedet for konfigurasjonsfilen, så dukker de manglende delene opp i rekkefølge.

Start ved pakken som dør

SYN-pakken forlater klienten, lander i tunnelen og når VM-en som en innkapslet pakke for en destinasjon i VPC-en. OpenVPN avkapsler den og prøver å videresende den ut av eth0, der fabricen stiller ett spørsmål før alt annet: eier denne instansen destinasjonsadressen. En tunnelpool som er skåret ut av en annens subnet, feiler på det spørsmålet, og pakken forkastes før noen rute eller brannmurregel blir konsultert.

Retningen fra klient til VPC har altså to atskilte krav, og ingen av dem er et push-direktiv. VM-en trenger et aliasområde som dekker tunnelpoolen, og det er nettopp det som gjør den til rettmessig eier av disse adressene. VPC-en trenger en rute som peker ut VM-en som next hop for hvert beskyttede prefiks. Mangler ett av dem, dør pakken et annet sted, mens klienten ser den samme stillheten.

Les feilen i den rekkefølgen, for fra klientsiden ser de to betingelsene identiske ut. En tunnel som rapporterer tilkoblet mens ingenting svarer, er signaturen på et topologiproblem og ikke på en dårlig cipher.

Eier instansen tunnelpoolen

Gi VM-en et sekundært område inne i sitt eget subnet, og la deretter OpenVPN dele ut adresser fra nøyaktig det området. På en instans med primæradresse 10.156.0.10/20 holder et /28-alias poolen atskilt fra adressene andre instanser allerede har:

gcloud compute instances network-interfaces update openvpn-vm \
  --zone=europe-west1-b \
  --aliases=eth0:10.156.1.0/28

Serverdirektivet må da beskrive den samme blokken. Den første adressen blir tunnelens gateway, og de gjenværende adressene deles ut til klienter. To tall beskriver én blokk her, et nettverk og en nettmaske, og det er den pool-syntaksen OpenVPN fortsatt forventer.

server 10.156.1.0 255.255.255.240

Bekreft at adressen virkelig landet på grensesnittet og ikke bare inne i OpenVPN-konfigurasjonen. Fabricen videresender det NIC-en rapporterer, ikke det daemonen tror. Én kommando avgjør det:

ip -4 addr show dev eth0

En sekundær adresse som aldri når eth0, eller en pool som overlapper et annet subnet, viser seg senere som periodisk tap i stedet for som en oppstartsfeil. Daemonen starter, klienter kobler til, og bare noen destinasjoner oppfører seg feil. Hold aliasområdet lite slik at poolen er lett å kjenne igjen i en rutetabell. Skjær det aldri ut av et subnet som en annen instans allerede bruker.

Gi returtrafikken en next hop

Et svar fra en vert i VPC-en er adressert til en klientadresse i tunnelpoolen, som ikke tilhører noe subnet VPC-en kjenner. Uten en rute for den poolen stopper svaret ved det første hoppet uten treff, og forespørselen kan godt ha lykkes i den andre enden.

gcloud compute routes create openvpn-return \
  --network=prod-vpc \
  --destination-range=192.168.127.0/24 \
  --next-hop-instance=openvpn-vm \
  --next-hop-instance-zone=europe-west1-b \
  --priority=800

Den samme ruten trengs for hvert prefiks som ligger bak en klient i stedet for inne i VPC-en. Disse prefiksene trenger også en iroute-oppføring i den klientens ccd-fil. Den oppføringen er bokføring på serversiden: den forteller serveren hvilken klient som eier prefikset, og den installerer ingenting på klienten selv.

Behold push-listen for klientsiden av samtalen, for den legger bare til ruter på maskinen som kobler til. En push-linje for et VPC-subnet og en VPC-rute tilbake til poolen er to halvdeler av samme vei, og hver halvdel alene gir en tunnel som bærer forespørsler men ingen svar.

Brannmurer, videresending og hoppene imellom

VPC-brannmuren vurderer den avkapslede pakken, så en ingress-regel må tillate tunnelpoolen og ethvert site-prefiks som når VM-en den veien. En default-deny-holdning feiler stille her: pakken forkastes etter avkapslingen, og OpenVPN-loggen viser en sunn økt.

Kontroller på enhver Linux-vert som videresender i stedet for å terminere at net.ipv4.ip_forward er aktivert. Eierregelen gjelder der også: en boks som videresender for et subnet den ikke har, forkaster pakken akkurat som VM-en ville gjort. Les verdien før du gir tunnelen skylden.

Når nøyaktig ett prefiks feiler

Delvis feil er det letteste tilfellet å lese, fordi alt annet i veien allerede er bevist. Start med rutelisten og les destinasjonsområdet og next hop for oppføringen som skulle dekke prefikset, les deretter instansbeskrivelsen og sammenlign aliasområdet med poolen serveren deler ut.

gcloud compute routes list --filter=destination-range~10.164.0.0
 gcloud compute instances describe openvpn-vm --format=get(networkInterfaces[0].aliasIpRanges)

En manglende rute viser seg som ingen next hop for prefikset, mens et manglende alias viser seg som en pakke som forkastes ved grensesnittet; fra klienten ser de to like ut og i de to utskriftene er de helt forskjellige. Hvis begge finnes, er den gjenstående mistenkte ccd-irouten for klienten som gjør krav på prefikset.

Skriv ned de fire verdiene ved siden av tunnelen: aliasområde, serverpool, pushade prefikser, VPC-ruter. Et utdatert alias ødelegger hver pooladresse, en utdatert rute ødelegger én retning, en manglende push skjuler prefikset for klienten, og en feil iroute sender prefikset til feil peer. Den neste som legger til et subnet trenger alle fire på ett sted, og notatet er billigere enn kvelden.

Relaterte artikler