Paket vsebnika nikoli ne doseže tun0 , in dodatne zmogljivosti na vsebniku tega ne bodo spremenile. Med gostom in tunelom sta dve iskanji poti: eno znotraj imenskega prostora omrežja gosta, eno na gostitelju po tem, ko okvir pristane na mostu, drugo pa vpraša drugo tabelo z drugačnimi pravili ujemanja. Moja referenčna postavitev je gostitelj Linux s OpenVPN odjemalcem, ki drži 10.8.0.10 na tun0 , mostom Docker na 172.18.0.0/16 , in zasebnim naslovom, do katerega seže le stran tunela. Cilj ostaja ozek: ta gostujoča podmreža odide skozi tunel, medtem ko gostitelj obdrži običajen uplink.

Izvajanje odjemalca VPN znotraj vsebnika je drugačna zasnova , ne bližnjica. Vsebnik takrat ima svoj tunel in svoje poverilnice, delo pa se preseli v Dockerfile, namesto da bi ostalo v iptables.

Posredovanje izbere pot glede na cilj, nato NAT prepiše vir

Ko je nastavljen net.ipv4.ip_forward=1 , se posredovani paket usmerja le glede na cilj, v glavni tabeli. Vir pri tej odločitvi ne igra nobene vloge. Šele po izbiri poti jedro zažene POSTROUTING , in prav tam stoji lastno pravilo Dockerja: -s 172.18.0.0/16 ! -o br-appnet -j MASQUERADE . Vse, kar zapusti most proti drugemu vmesniku, se prevede, naslov, v katerega se spremeni, pa je odvisen od vmesnika, kamor ga je poslala pot.

To pravilo pojasni večino simptomov, o katerih me sprašujejo. Če glavna tabela nima poti do zasebnega cilja, paket zapusti uplink s fizičnim naslovom gostitelja. Vaš ponudnik zavrže cilj, ali oddaljeno mesto zavrže vir RFC 1918, ki ga ni pričakovalo, in vsebniku poteče čas, medtem ko tunel ostaja pokonci in zdrav. Zajem na tun0 ne pokaže ničesar, in to je znak. Če pot res kaže na tun0 , MASQUERADE prepiše vir na 10.8.0.10 , in isti vsebnik deluje, ne da bi se česar koli dotaknili.

Zahtevajte iskanje, ki poimenuje vir gosta. Brez from in iif gostitelj odgovarja za svojo lastno vtičnico in poroča pot, ki se je posredovani paket ne bo nikoli lotil:

ip route get 192.168.11.222 from 172.18.0.5 iif br-appnet

Če ta odgovor poimenuje uplink, tunel ni v igri in nobena nastavitev na strani tunela ne bo pomagala.

Premaknite gosta na lasten naslov tunela

Najmanjša delujoča sprememba je izrecno prepisovanje vira na izhodu. Vstavite ga, namesto da bi ga dodali: Docker že sedi na čelu POSTROUTING , zato se pravilo, dodano z -A , ovrednoti za Dockerjevim in se nikoli ne sproži.

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

Dva pogoja odločata, ali bo to zdržalo. Naslov mora biti tak, kot ga odjemalec res ima, zato ga pripnite z vnosom na odjemalca, ki vsebuje ifconfig-push 10.8.0.10 255.255.255.0 ; pravilo, ki poimenuje naslov, ki ni bil nikoli dodeljen, povzroči tiho zavračanje, ne napake. In oddaljena stran mora ta vir sprejeti ter usmeriti odgovore nazaj, zato seznam dovoljenih tam poimenuje naslov tunela, ne gostujoče podmreže. Ko je naslov odjemalca dinamičen, -j MASQUERADE z -o tun0 sledi temu, kar ima vmesnik, za ceno oddaljene politike, proti kateri ne morete zapisati fiksne vrednosti.

Filtriranje je druga polovica. Docker nastavi politiko FORWARD na drop in ob vsakem ponovnem zagonu demona izprazni verige, ki jih ima v lasti, zato lokalno politiko postavite v DOCKER-USER , ki preživi:

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 vrnitve je pomembno: odgovor, ki prispe na tun0 za povezavo, ki jo je odprl most, ni sprejet samo zato, ker je bila smer ven.

Držite gostitelja neposrednega s pravilom vira

Ko mora cel most uporabljati tunel, nič drugega na gostitelju pa ne, preskočite NAT in dajte temu viru lastno tabelo. Gostujoči naslovi potem ostanejo vidni od začetka do konca.

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 pregledajo pred glavno tabelo, in from se ujema z virom. Lastni zunanji paketi tunela nosijo fizični naslov gostitelja, zato se nikoli ne ujemajo z from 172.18.0.0/16 , in tunel se ne more usmeriti nazaj vase. Prav ta samoizključitev naredi postavitev stabilno.

Povratna pot zdaj potrebuje pomoč. Oddaljena stran vidi nepreveden 172.18.0.x in nima razloga vedeti, kje živi. Na strežniku datoteka na odjemalca potrebuje iroute 172.18.0.0 255.255.0.0 , da notranja tabela strežnika preda to predpono temu odjemalcu, in potisnjen route 172.18.0.0 255.255.0.0 , da drugi odjemalci vedo, da obstaja.

Dve preveritvi, preden mu zaupate. Zaženite ip route show default : z redirect-gateway def1 ima tabela 0.0.0.0/1 in 128.0.0.0/1 prek tun0 , gostitelj pa sploh ni neposreden, ker te polovične privzete poti zmagajo, ne da bi nadomestile default . Pravila, dodana z ip rule add , prav tako izginejo ob ponovnem zagonu, zato jih nosite v skriptu up.

Velikost paketa je druga okvara, na katero naletite

Vmesnik mostu pri 1500 bajtih da tunelu več, kot lahko prenese, ko se dodajo zunanje glave UDP in IP. Majhne izmenjave gredo skozi, zato se DNS razreši in rokovanje TLS konča, nato pa se večje pošiljanje ustavi brez kakršne koli napake. Pošiljatelj ponavlja isto velikost segmenta, ker sporočilo ICMP o potrebi po fragmentaciji, ki bi mu reklo, naj zmanjša, nikoli ne prispe.

Popravite na vmesniku, na MSS ali obojem. Stiskanje ne potrebuje sodelovanja 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

Stiskanje prepiše samo TCP. UDP, vključno s QUIC, potrebuje namesto tega znižan gostujoči vmesnik, z --opt com.docker.network.driver.mtu=1400 pri ustvarjanju omrežja ali ustreznim ključem compose.

DNS in preveritve, ki jih je vredno ponavljati

Razreševanje imen sledi isti poti. Vgrajeni resolver Dockerja na 127.0.0.11 posreduje na konfigurirane strežnike gostitelja, zato vsebnik podeduje, kar uporablja gostitelj. Ko na zasebno območje odgovarja le resolver, dosegljiv skozi tunel, usmerite gosta na ta naslov, in preizkusite z getent hosts znotraj vsebnika, ne na gostitelju.

  • Zaženite neuspešno zahtevo znotraj gosta; preizkus na strani gostitelja uporablja drug naslov vira in težavo skrije.
  • Berite števce na pravilih NAT in filtriranja, ki ste jih dodali. Pravilo brez enega samega ujemanja je napaka usmerjanja, ne politike.
  • Potrdite, da je naslov tunela v vašem pravilu SNAT tisti, ki ga odjemalec res ima.
  • Znižajte MTU gosta ali stisnite MSS, preden okrivite strežnik za zastoj.

Pojdite po seznamu in se ustavite pri prvi okvari. Ta plast je tista, ki jo je treba popraviti; karkoli dodano nižje, samo skrije mejo, ki se lomi.

Sorodni članki