Pakken frå containeren når aldri tun0 , og ekstra eigenskapar på containeren endrar ikkje det. Mellom gjesten og tunnelen ligg to ruteoppslag: eitt inne i nettverksnamnerommet til gjesten, eitt på verten etter at ramma landar på brua, og det andre spør ein annan tabell med andre matchreglar. Oppsettet mitt er ein Linux-vert som køyrer ein OpenVPN klient som held 10.8.0.10 på tun0 , ei Docker-bru på 172.18.0.0/16 , og ei privat adresse som berre tunnelsida kan nå. Målet blir verande smalt: det gjestenettet går ut gjennom tunnelen medan verten held sin vanlege uplink.

Å køyre VPN-klienten inne i containeren er eit anna design , ikkje ein snarvveg. Då eig containeren sin eigen tunnel og sine eigne legitimasjonar, og arbeidet flyttar inn i ein Dockerfile i staden for å bli i iptables.

Vidaresending vel rute etter destinasjon, så skriv NAT om kjelda

Med net.ipv4.ip_forward=1 sett blir ein vidaresend pakke ruta berre etter destinasjon, i hovudtabellen. Kjelda spelar inga rolle i den avgjerda. Først etter at ruta er vald, køyrer kjernen POSTROUTING , og det er der Dockers eigen regel sit: -s 172.18.0.0/16 ! -o br-appnet -j MASQUERADE . Alt som forlèt brua til eit anna grensesnitt, blir omsett, og adressa det blir til avheng av grensesnittet ruta sende det til.

Den regelen forklarer dei fleste symptoma eg blir spurd om. Viss hovudtabellen ikkje har ei rute til den private destinasjonen, forlèt pakken uplinken med den fysiske adressa til verten. Leverandøren din droppar destinasjonen, eller det eksterne nettstaden droppar ei RFC 1918-kjelde det aldri venta, og containeren får tidsavbrot medan tunnelen står oppe og er sunn. Eit opptak på tun0 viser ingenting, og det er teiknet. Viss ruta faktisk peikar på tun0 , skriv MASQUERADE om kjelda til 10.8.0.10 , og same container verkar utan at du rører noko.

Be om oppslaget som namngir kjelda til gjesten. Utan from og iif svarar verten for sin eigen socket og rapporterer ein veg den vidaresende pakken aldri vil ta:

ip route get 192.168.11.222 from 172.18.0.5 iif br-appnet

Viss svaret namngir uplinken, er ikkje tunnelen i bildet, og inga innstilling på tunnelsida hjelper.

Flytt gjesten over på den eigne adressa til tunnelen

Den minste endringa som verkar, er ei eksplisitt kjeldeomskriving på veg ut. Set ho inn i staden for å leggje ho til: Docker sit allereie i spissen av POSTROUTING , så ein regel lagd til med -A blir vurdert bak Dockers og utløysest aldri.

iptables -t nat -I POSTROUTING 1 -s 172.18.0.0/16 -o tun0 -j SNAT --to-source 10.8.0.10

To vilkår avgjer om dette held. Adressa må vere ei klienten faktisk har, så fest ho med ei oppføring per klient som inneheld ifconfig-push 10.8.0.10 255.255.255.0 ; ein regel som namngir ei adresse som aldri vart tildelt, gir stille dropp, ikkje ein feil. Og den eksterne sida må godta den kjelda og rute svar tilbake, derfor namngir ei tillatingsliste der tunneladressa i staden for gjestenettet. Når klientadressa er dynamisk, -j MASQUERADE med -o tun0 følgjer det grensesnittet har, på kostnad av ekstern politikk du ikkje kan skrive mot ein fast verdi.

Filtrering er den andre halvdelen. Docker set FORWARD -policyen til drop og tømmer kjedene det eig ved kvar daemon-restart, så legg lokal politikk i DOCKER-USER , som overlever:

iptables -I DOCKER-USER -i br-appnet -o tun0 -j ACCEPT
iptables -I DOCKER-USER -i tun0 -o br-appnet -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Returregelen er viktig: eit svar som kjem inn på tun0 for ei tilkopling opna av brua, blir ikkje godteke berre fordi retninga ut var det.

Hald verten direkte med ein kilderegel

Når heile brua skal bruke tunnelen, men ingenting anna på verten skal, hopp over NAT og gi den kjelda si eiga tabell. Gjesteadresser blir då synlege heile vegen.

echo "200 vpnbox" >> /etc/iproute2/rt_tables
ip rule add from 172.18.0.0/16 lookup vpnbox pref 1000
ip route add default dev tun0 table vpnbox

Reglar blir konsulterte før hovudtabellen, og from matchar kjelda. Dei eigne ytre pakkane til tunnelen ber den fysiske kjelda til verten, så dei matchar aldri from 172.18.0.0/16 , og tunnelen kan ikkje rute seg sjølv tilbake i seg sjølv. Den sjølvutelukkinga er det som gjer oppsettet stabilt.

Returvegen treng no hjelp. Den eksterne sida ser ein uomsett 172.18.0.x og har ingen grunn til å vite kvar han bur. På serveren treng ei fil per klient iroute 172.18.0.0 255.255.0.0 , slik at den interne tabellen til serveren gir det prefikset til denne klienten, og ein pusht route 172.18.0.0 255.255.0.0 , slik at andre klientar veit at han finst.

To kontrollar før du stolar på det. Køyr ip route show default : med redirect-gateway def1 held tabellen 0.0.0.0/1 og 128.0.0.0/1 via tun0 , og verten er slett ikkje direkte, fordi dei halve standardrutene vinn utan å erstatte default . Reglar lagde til med ip rule add forsvinn også ved omstart, så ber dei i eit up-skript.

Pakkestorleik er den andre feilen du møter

Eit brugrensesnitt på 1500 byte gir tunnelen meir enn han kan bere når dei ytre UDP- og IP-hovuda kjem til. Små utvekslingar går gjennom, så DNS blir løyst og TLS-handtrykket fullført, deretter heng ein større opplasting utan nokon feil nokon stad. Avsendararen held fram med å gjenta same segmentstorleik fordi ICMP-meldinga om fragmenteringsbehov, som ville bede han krympe, aldri kjem.

Fiks det på grensesnittet, på MSS, eller begge. Klemming krev ingen medverknad frå gjesten:

ip link set dev tun0 mtu 1400
iptables -t mangle -A FORWARD -o tun0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Klemminga skriv berre om TCP. UDP, inkludert QUIC, treng i staden eit lågare gjestegrensesnitt, med --opt com.docker.network.driver.mtu=1400 ved nettverksoppretting eller den matchende compose-nokkelen.

DNS og kontrollane som er verd å gjenta

Namneoppslag følgjer same veg. Den innebygde resolvaren til Docker på 127.0.0.11 vidaresender til dei konfigurerte serverane til verten, så ein container arvar det verten brukar. Når den private sona berre blir svara av ein resolvar som er tilgjengeleg gjennom tunnelen, peik gjesten på den adressa, og test med getent hosts inne i containeren i staden for på verten.

  • Køyr den feilande førespurnaden inne i gjesten; ein test på vertssida brukar ei anna kjeldeadresse og skjuler problemet.
  • Les teljarane på NAT- og filterreglane du la til. Ein regel utan treff er ein rutefeil, ikkje ein politikkfeil.
  • Stadfest at tunneladressa i SNAT-regelen din er ei klienten faktisk har.
  • Senk MTU-en til gjesten eller klem MSS før du klandrar serveren for ein stans.

Gå nedover lista og stopp ved første feil. Det laget er det som må rettast; alt som blir lagt til lenger nede, skjuler berre grensa som ryker.

Relaterte artiklar