Paket kontejnera nikada ne stiže do tun0 , a dodatne sposobnosti na kontejneru to neće promeniti. Između gosta i tunela stoje dve pretrage rute: jedna unutar mrežnog imenskog prostora gosta, jedna na hostu nakon što okvir sleti na most, a druga pita drugu tabelu sa drugačijim pravilima podudaranja. Moja referentna postavka je Linux host sa OpenVPN klijentom koji drži 10.8.0.10 na tun0 , Docker mostom na 172.18.0.0/16 , i privatnom adresom do koje samo strana tunela može doći. Cilj ostaje uzak: ta gostujuća podmreža izlazi kroz tunel dok host zadržava svoj uobičajeni uplink.

Pokretanje VPN klijenta unutar kontejnera je drugačiji dizajn , a ne prečica. Kontejner tada poseduje svoj tunel i svoje akreditacije, a posao se seli u Dockerfile umesto da ostane u iptablesu.

Prosledjivanje bira rutu po odredištu, zatim NAT prepisuje izvor

Kada je postavljeno net.ipv4.ip_forward=1 , prosledjeni paket se rutira samo po odredištu, u glavnoj tabeli. Izvor ne igra nikakvu ulogu u toj odluci. Tek nakon što se ruta odabere, kernel pokreće POSTROUTING , i tu stoji Dockerovo sopstveno pravilo: -s 172.18.0.0/16 ! -o br-appnet -j MASQUERADE . Sve što napusti most prema drugom interfejsu biva prevedeno, a adresa koju dobije zavisi od interfejsa na koji ga je ruta poslala.

To pravilo objašnjava većinu simptoma o kojima me pitaju. Ako glavna tabela nema rutu za privatno odredište, paket izlazi kroz uplink noseći fizičku adresu hosta. Vaš provajder odbacuje odredište, ili udaljena stranica odbacuje izvor RFC 1918 koji nikada nije očekivala, i kontejneru istekne vreme dok tunel ostaje podignut i zdrav. Snimak na tun0 ne pokazuje ništa i to je znak. Ako ruta ipak pokazuje na tun0 , MASQUERADE prepisuje izvor na 10.8.0.10 , i isti kontejner radi bez toga da bilo šta dirate.

Tražite pretragu koja imenuje izvor gosta. Bez from i iif host odgovara za sopstveni socket i prijavljuje putanju koju prosledjeni paket nikada neće uzeti:

ip route get 192.168.11.222 from 172.18.0.5 iif br-appnet

Ako taj odgovor imenuje uplink, tunel nije u slici i nikakva postavka na strani tunela neće pomoći.

Prevedite gosta na sopstvenu adresu tunela

Najmanja promena koja radi je izričito prepisivanje izvora na izlazu. Umetnite ga, umesto da ga dodajete: Docker već sedi na čelu POSTROUTING , pa se pravilo dodato sa -A procenjuje iza Dockerovog i nikada se ne pokreće.

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

Dva uslova odlučuju da li će se to održati. Adresa mora biti ona koju klijent zaista drži, zato je prikujte zapisom po klijentu koji sadrži ifconfig-push 10.8.0.10 255.255.255.0 ; pravilo koje imenuje adresu koja nikada nije dodeljena proizvodi nemo odbacivanje, ne grešku. I dalja strana mora prihvatiti taj izvor i usmeriti odgovore natrag, zato lista dozvola tamo imenuje adresu tunela, a ne gostujuću podmrežu. Kada je adresa klijenta dinamička, -j MASQUERADE sa -o tun0 sledi ono što interfejs drži, po ceni udaljene politike protiv koje ne možete pisati fiksnu vrednost.

Filtriranje je druga polovina. Docker postavlja politiku FORWARD na drop i briše lance koje poseduje pri svakom restartu daemona, zato stavite lokalnu politiku u DOCKER-USER , koja preživljava:

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

Pravilo povratka je važno: odgovor koji stigne na tun0 za vezu otvorenu kroz most nije prihvaćen samo zato što je odlazni smer bio.

Držite host direktnim pravilom izvora

Kada ceo most treba da koristi tunel, a ništa drugo na hostu ne treba, preskočite NAT i dajte tom izvoru sopstvenu tabelu. Adrese gostiju tada ostaju vidljive od početka do kraja.

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

Pravila se konsultuju pre glavne tabele, i from se podudara sa izvorom. Sopstveni spoljni paketi tunela nose fizički izvor hosta, pa se nikada ne podudaraju sa from 172.18.0.0/16 , i tunel ne može usmeriti sebe natrag u sebe. To samoizuzimanje čini postavku stabilnom.

Putanja odgovora sada treba pomoć. Dalja strana vidi neprevedenu 172.18.0.x i nema razloga znati gde živi. Na serveru, datoteka po klijentu treba iroute 172.18.0.0 255.255.0.0 da bi serverova unutrašnja tabela predala taj prefiks ovom klijentu, i gurnutu route 172.18.0.0 255.255.0.0 da bi drugi klijenti znali da postoji.

Dve provere pre nego mu poverujete. Pokrenite ip route show default : sa redirect-gateway def1 tabela drži 0.0.0.0/1 i 128.0.0.0/1 preko tun0 , a host uopšte nije direktan, jer te polovine podrazumevanog pobeđuju bez zamene default . Pravila dodata sa ip rule add takođe nestaju pri restartu, zato ih nosite u up skripti.

Veličina paketa je drugi kvar na koji naletite

Most na 1500 bajtova daje tunelu više nego što može da nosi kada se dodaju spoljni UDP i IP zaglavlja. Male razmene prolaze, pa se DNS razreši i TLS rukovanje završi, a zatim veći upload visi bez ikakve greške. Pošiljalac stalno ponavlja istu veličinu segmenta jer ICMP poruka o potrebi fragmentacije, koja bi mu rekla da se smanji, nikada ne stiže.

Popravite to na interfejsu, na MSS-u ili oboje. Stezanje ne traži saradnju gosta:

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

Stezanje prepisuje samo TCP. UDP, uključujući QUIC, treba umesto toga spušten interfejs gosta, sa --opt com.docker.network.driver.mtu=1400 pri kreiranju mreže ili odgovarajućim compose ključem.

DNS i provere koje vredi ponavljati

Razrešavanje imena sledi istu putanju. Dockerov ugrađeni rezolver na 127.0.0.11 prosledjuje na konfigurisane servere hosta, pa kontejner nasleđuje ono što host koristi. Kada privatnu zonu odgovara samo rezolver dostupan kroz tunel, usmerite gosta na tu adresu i testirajte sa getent hosts unutar kontejnera, a ne na hostu.

  • Pokrenite neuspešni zahtev unutar gosta; test na strani hosta koristi drugu izvornu adresu i skriva problem.
  • Čitajte brojače na NAT i filter pravilima koja ste dodali. Pravilo sa nula podudaranja je greška rutiranja, ne politike.
  • Potvrdite da je adresa tunela u vašem SNAT pravilu ona koju klijent zaista drži.
  • Snizite MTU gosta ili stegnite MSS pre nego što okrivite server za zastoj.

Prodjite kroz taj spisak i zaustavite se na prvom kvaru. Taj sloj treba popraviti; sve što se doda dalje samo skriva granicu koja se lomi.

Povezani članci