Lei net Docker-houers se verkeer deur OpenVPN
Hou die gasheer op sy normale opstrekkanaal en plaas net een houer-subnet in die tonnel: NAT-volgorde, bronreëls, OpenVPN-iroute en MSS-kontroles.
Die houer se pakkie bereik nooit tun0 nie, en ekstra vermoëns op die houer sal dit nie verander nie. Twee roetesorgtogte staan tussen die gas en die tonnel: een binne die gas se netwerk-naamruimte, een op die gasheer nadat die raam op die brug beland, en die tweede raadpleeg 'n ander tabel met ander pasreëls. My verwysingsuitleg is 'n Linux-gasheer met 'n OpenVPN kliënt met 10.8.0.10 op tun0, 'n Docker-brug op 172.18.0.0/16, en 'n private adres wat net die tonnelkant kan bereik. Die doel bly eng: daardie gassubnet verlaat deur die tonnel terwyl die gasheer sy gewone opstrekkanaal hou.
Om die VPN-kliënt binne die houer te laat loop is 'n ander ontwerp, nie 'n kortpad nie. Die houer besit dan sy tonnel en geloofsbriewe, en die werk skuif na 'n Dockerfile in plaas van om in iptables te bly.
Aansturing kies 'n roete volgens bestemming, dan herskryf NAT die bron
Met net.ipv4.ip_forward=1 gestel, word 'n aangestuurde pakkie net volgens bestemming in die hoof tabel gelei. Die bron speel geen rol in daardie besluit nie. Eers nadat die roete gekies is, kom POSTROUTING, en dit is waar Docker se eie reël sit: -s 172.18.0.0/16 ! -o br-appnet -j MASQUERADE. Enigiets wat die brug vir 'n ander koppelvlak verlaat, word vertaal, en die adres wat dit word, hang af van die koppelvlak waarheen die roete dit gestuur het.
Daardie reël verduidelik die meeste simptome waaroor ek gevra word. As die hoof tabel geen roete vir die private bestemming het nie, verlaat die pakkie die opstrekkanaal met die gasheer se fisiese adres. Jou verskaffer laat die bestemming val, of die webtuiste aan die ander kant laat 'n RFC 1918-bron val wat hy nooit verwag het nie, en die houer hou op reageer terwyl die tonnel op en gesond bly. 'n Opname op tun0 wys niks, en dit is die teken. As die roete wel na tun0 wys, herskryf MASQUERADE die bron na 10.8.0.10 en dieselfde houer werk sonder dat jy enigiets aanraak.
Vra vir die opsoek wat die gas se bron noem. Sonder from en iif antwoord die gasheer vir sy eie sok en rapporteer 'n pad wat die aangestuurde pakkie nooit sal neem nie:
ip route get 192.168.11.222 from 172.18.0.5 iif br-appnetAs daardie antwoord die opstrekkanaal noem, is die tonnel nie in die prentjie nie en geen instelling aan die tonnelkant sal help nie.
Vertaal die gas na die tonnel se eie adres
Die kleinste werkende verandering is 'n uitdruklike bronherskrywing op pad uit. Voeg dit in eerder as om dit by te voeg: Docker sit reeds aan die hoof van POSTROUTING, so 'n reël wat met -A bygevoeg word, word agter Docker s'n geëvalueer en werk nooit nie.
iptables -t nat -I POSTROUTING 1 -s 172.18.0.0/16 -o tun0 -j SNAT --to-source 10.8.0.10Twee voorwaardes bepaal of dit hou. Die adres moet een wees wat die kliënt werklik het, so pen dit vas met 'n inskrywing per kliënt wat ifconfig-push 10.8.0.10 255.255.255.0 bevat; 'n reël wat 'n adres noem wat nooit toegewys is nie, lewer stil weglaatings, nie 'n fout nie. En die ander kant moet daardie bron aanvaar en antwoorde terugstuur, daarom noem 'n toelatingslys daar die tonneladres eerder as die gassubnet. Wanneer die kliëntadres dinamies is, -j MASQUERADE met -o tun0 volg wat die koppelvlak ook al het, teen die koste van afgeleide beleid waarteen jy nie 'n vaste waarde kan skryf nie.
Filtering is die ander helfte. Docker stel die FORWARD beleid op drop en maak die kettings wat hy besit by elke daemon-herbegin skoon, so plaas plaaslike beleid in DOCKER-USER, wat oorleef:
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 ACCEPTDie terugreël maak saak: 'n antwoord wat op tun0 aankom vir 'n verbinding wat deur die brug oopgemaak is, word nie aanvaar net omdat die uitgaande rigting dit was nie.
Hou die gasheer direk met 'n bronreël
Wanneer die hele brug die tonnel moet gebruik maar niks anders op die gasheer nie, slaan NAT oor en gee daardie bron sy eie tabel. Gasadresse bly dan van begin tot end sigbaar.
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 vpnboxReëls word voor die hoof tabel geraadpleeg, en from pas die bron. Die tonnel se eie buitenste pakkies dra die gasheer se fisiese bron, so hulle pas nooit op from 172.18.0.0/16 nie en die tonnel kan homself nie terug in homself lei nie. Daardie self-uitsluiting is wat die uitleg stabiel maak.
Die antwoordpad het nou hulp nodig. Die ander kant sien 'n onvertaalde 172.18.0.x en het geen rede om te weet waar dit woon nie. Op die bediener het 'n lêer per kliënt iroute 172.18.0.0 255.255.0.0 nodig sodat die bediener se interne tabel daardie voorvoegsel aan hierdie kliënt gee, en 'n gestuurde route 172.18.0.0 255.255.0.0 sodat ander kliënte weet dit bestaan.
Twee kontroles voordat jy dit vertrou. Voer ip route show default uit: met redirect-gateway def1 hou die tabel 0.0.0.0/1 en 128.0.0.0/1 via tun0, en die gasheer is glad nie direk nie, want daardie half-verstekke wen sonder vervanging van default. Reëls wat met ip rule add bygevoeg word, verdwyn ook met 'n herbegin, so dra hulle in 'n op-skrip in.
Pakgrootte is die fout wat jy tweede teëkom
'n Brugkoppelvlak op 1500 grepe gee die tonnel meer as wat dit kan dra sodra die buitenste UDP- en IP-opskrifte bykom. Klein uitruilings slaag, so DNS los op en die TLS-handdruk voltooi, dan hang 'n groter oplaai sonder enige fout. Die sender bly dieselfde segmentgrootte herhaal omdat die ICMP-boodskap oor nodigheid vir fragmentering, wat hom sou sê om te krimp, nooit aankom nie.
Maak dit reg by die koppelvlak, by die MSS, of albei. Klemming het geen samewerking van die gas nodig nie:
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-pmtuDie klem herskryf net TCP. UDP, QUIC ingesluit, het eerder 'n verlaagde gas-koppelvlak nodig, met --opt com.docker.network.driver.mtu=1400 by netwerkskepping of die ooreenstemmende compose-sleutel.
DNS en die kontroles wat werd is om te herhaal
Naamopossing volg dieselfde pad. Docker se ingeboude oplosser by 127.0.0.11 stuur aan na die gasheer se gekonfigureerde bedieners, so 'n houer erf wat die gasheer ook al gebruik. Wanneer die private sone net deur 'n oplosser wat deur die tonnel bereikbaar is, beantwoord word, wys die gas na daardie adres, en toets met getent hosts binne die houer eerder as op die gasheer.
- Voer die mislukkende versoek binne die gas uit; 'n toets aan die gasheerkant gebruik 'n ander bronadres en verberg die probleem.
- Lees die tellers op die NAT- en filterreëls wat jy bygevoeg het. 'n Reël met nul treffers is 'n roetefout, nie 'n beleidsfout nie.
- Bevestig die tonneladres in jou SNAT-reël is een wat die kliënt werklik het.
- Verlaag die gas se MTU of klem die MSS voordat jy die bediener vir 'n stilstand blameer.
Werk daardie lys af en stop by die eerste fout. Daardie laag is die een om reg te maak; enigiets wat verder af bygevoeg word, verberg net die grens wat breek.