కంటైనర్ ప్యాకెట్ ఎప్పటికీ tun0 కు చేరుకోదు, మరియు కంటైనర్పై అదనపు సామర్థ్యాలు దాన్ని మార్చవు. అతిథి మరియు టన్నెల్ మధ్య రెండు రూట్ శోధనలు ఉన్నాయి: ఒకటి అతిథి నెట్వర్క్ నామస్థలంలో, ఒకటి ఫ్రేమ్ వంతెనపై దిగిన తర్వాత హోస్ట్లో, రెండవది వేరే సరిపోలిక నియమాలున్న వేరే పట్టికను అడుగుతుంది. నా సూచన లేఅవుట్ OpenVPN క్లయింట్తో నడిచే Linux హోస్ట్, అది 10.8.0.10 ను tun0 పై ఉంచుతుంది, 172.18.0.0/16 పై Docker వంతెన, మరియు టన్నెల్ వైపు మాత్రమే చేరుకోగల ప్రైవేట్ చిరునామా. లక్ష్యం ఇరుకుగానే ఉంటుంది: ఆ అతిథి సబ్నెట్ టన్నెల్ ద్వారా బయటకు వెళ్తుంది, హోస్ట్ తన సాధారణ అప్లింక్ను ఉంచుకుంటుంది.

VPN క్లయింట్ను కంటైనర్ లోపల నడపడం మరో రూపకల్పన, సులభ మార్గం కాదు. అప్పుడు కంటైనర్ తన టన్నెల్ మరియు తన ఆధారాలను కలిగి ఉంటుంది, పని iptables లో ఉండకుండా Dockerfile కు మారుతుంది.

ఫార్వర్డింగ్ గమ్యం ప్రకారం మార్గాన్ని ఎంచుకుంటుంది, తర్వాత NAT మూలాన్ని తిరిగి రాస్తుంది

సెట్ చేసినప్పుడు net.ipv4.ip_forward=1 , ఫార్వర్డ్ చేసిన ప్యాకెట్ ప్రధాన పట్టికలో గమ్యం ప్రకారం మాత్రమే రూట్ అవుతుంది. ఆ నిర్ణయంలో మూలానికి ఎలాంటి పాత్రా లేదు. మార్గం ఎంచుకున్న తర్వాతే కర్నెల్ POSTROUTING ను నడుపుతుంది, అక్కడే Docker సొంత నియమం ఉంది: -s 172.18.0.0/16 ! -o br-appnet -j MASQUERADE . వంతెనను విడిచి మరో ఇంటర్ఫేస్ వైపు వెళ్లే ప్రతిదీ అనువదించబడుతుంది, అది ఏ చిరునామా అవుతుందో మార్గం దాన్ని ఏ ఇంటర్ఫేస్కు పంపిందనే దానిపై ఆధారపడి ఉంటుంది.

ఈ నియమం నన్ను అడిగే చాలా లక్షణాలను వివరిస్తుంది. ప్రధాన పట్టికలో ప్రైవేట్ గమ్యానికి మార్గం లేకపోతే, ప్యాకెట్ హోస్ట్ భౌతిక చిరునామాతో అప్లింక్ ద్వారా బయటకు వెళ్తుంది. మీ ప్రదాత గమ్యాన్ని పడేస్తాడు, లేదా దూర సైట్ ఎప్పుడూ ఊహించని RFC 1918 మూలాన్ని పడేస్తుంది, టన్నెల్ పైన మరియు ఆరోగ్యంగా ఉన్నప్పుడే కంటైనర్ సమయం ముగుస్తుంది. tun0 పై క్యాప్చర్ ఏమీ చూపదు, అదే సూచన. మార్గం నిజంగా tun0 వైపు చూపిస్తే, MASQUERADE మూలాన్ని 10.8.0.10 కు తిరిగి రాస్తుంది, అదే కంటైనర్ మీరు ఏమీ తాకకుండా పనిచేస్తుంది.

అతిథి మూలాన్ని పేర్కొనే శోధనను అడగండి. from మరియు iif లేకుండా హోస్ట్ తన సొంత సాకెట్ కోసం సమాధానం ఇస్తుంది మరియు ఫార్వర్డ్ చేసిన ప్యాకెట్ ఎప్పటికీ తీసుకోని మార్గాన్ని నివేదిస్తుంది:

ip route get 192.168.11.222 from 172.18.0.5 iif br-appnet

ఆ సమాధానం అప్లింక్ను పేర్కొంటే, టన్నెల్ చిత్రంలో లేదు మరియు టన్నెల్ వైపు ఏ సెట్టింగ్ సహాయపడదు.

అతిథిని టన్నెల్ సొంత చిరునామాకు తరలించండి

అతి చిన్న పనిచేసే మార్పు బయటకు వెళ్లేటప్పుడు స్పష్టమైన మూల పునర్లేఖనం. దాన్ని చేర్చకుండా చొప్పించండి: Docker ఇప్పటికే POSTROUTING తలపై కూర్చుంది, కాబట్టి -A తో చేర్చిన నియమం Docker నియమం తర్వాత మూల్యాంకనం అవుతుంది మరియు ఎప్పటికీ నడవదు.

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

ఇది నిలిచి ఉంటుందో లేదో రెండు షరతులు నిర్ణయిస్తాయి. చిరునామా క్లయింట్ నిజంగా కలిగి ఉన్నదే ఉండాలి, కాబట్టి ప్రతి క్లయింట్ కోసం ifconfig-push 10.8.0.10 255.255.255.0 ఉన్న నమోదుతో దాన్ని పిన్ చేయండి; ఎప్పుడూ కేటాయించని చిరునామాను పేర్కొనే నియమం లోపం కాదు, నిశ్శబ్ద డ్రాప్లను కలిగిస్తుంది. మరియు దూర వైపు ఆ మూలాన్ని అంగీకరించి సమాధానాలను తిరిగి రూట్ చేయాలి, అందుకే అక్కడి అనుమతి జాబితా అతిథి సబ్నెట్ను కాదు, టన్నెల్ చిరునామాను పేర్కొంటుంది. క్లయింట్ చిరునామా చలనశీలమైనప్పుడు, -j MASQUERADE తో -o tun0 ఇంటర్ఫేస్ కలిగి ఉన్నదాన్ని అనుసరిస్తుంది, స్థిర విలువకు వ్యతిరేకంగా రాయలేని దూర విధానం ఖర్చుతో.

ఫిల్టరింగ్ మరో సగం. Docker FORWARD విధానాన్ని drop కు పెట్టి ప్రతి డీమన్ పునఃప్రారంభంలో తన సొంత గొలుసులను ఖాళీ చేస్తుంది, కాబట్టి స్థానిక విధానాన్ని DOCKER-USER లో పెట్టండి, అది నిలిచి ఉంటుంది:

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

తిరిగి వచ్చే నియమం ముఖ్యం: tun0 కు వచ్చే సమాధానం వంతెన ద్వారా తెరిచిన కనెక్షన్ కోసం బయటకు వెళ్లే దిశ అంగీకరించబడినందుకే అంగీకరించబడదు.

మూల నియమంతో హోస్ట్ను నేరుగా ఉంచండి

మొత్తం వంతెన టన్నెల్ను ఉపయోగించాలి కానీ హోస్ట్పై మరేదీ ఉపయోగించకూడదు అన్నప్పుడు, NAT ను దాటవేసి ఆ మూలానికి దాని సొంత పట్టికను ఇవ్వండి. అతిథి చిరునామాలు అప్పుడు మొదటి నుండి చివరి వరకు కనిపిస్తాయి.

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

నియమాలు ప్రధాన పట్టికకు ముందు పరిశీలించబడతాయి, మరియు from మూలంతో సరిపోతుంది. టన్నెల్ సొంత బయటి ప్యాకెట్లు హోస్ట్ భౌతిక మూలాన్ని మోసుకెళ్తాయి, కాబట్టి అవి ఎప్పటికీ from 172.18.0.0/16 తో సరిపోలవు, టన్నెల్ తనను తాను తిరిగి లోపలికి రూట్ చేయలేదు. ఈ స్వయం-మినహాయింపే లేఅవుట్ను స్థిరంగా చేస్తుంది.

తిరిగి వచ్చే మార్గానికి ఇప్పుడు సహాయం కావాలి. దూర వైపు అనువాదం చేయని 172.18.0.x ను చూస్తుంది, అది ఎక్కడ ఉంటుందో తెలుసుకోవడానికి కారణం లేదు. సర్వర్లో ప్రతి క్లయింట్ కోసం ఫైల్కు iroute 172.18.0.0 255.255.0.0 కావాలి, సర్వర్ అంతర్గత పట్టిక ఆ ప్రిఫిక్స్ను ఈ క్లయింట్కు ఇవ్వడానికి, మరియు నెట్టిన route 172.18.0.0 255.255.0.0 కావాలి, మిగతా క్లయింట్లు అది ఉన్నట్టు తెలుసుకోవడానికి.

నమ్మే ముందు రెండు తనిఖీలు. నడపండి ip route show default : redirect-gateway def1 తో పట్టికలో 0.0.0.0/1 మరియు 128.0.0.0/1 ఉన్నాయి tun0 ద్వారా, మరియు హోస్ట్ అసలే నేరుగా కాదు, ఎందుకంటే ఆ సగం-డీఫాల్ట్లు default ను భర్తీ చేయకుండా గెలుస్తాయి. ip rule add తో చేర్చిన నియమాలు కూడా రీబూట్లో మాయమవుతాయి, కాబట్టి వాటిని up స్క్రిప్ట్లో ఉంచండి.

ప్యాకెట్ పరిమాణం మీరు ఎదుర్కొనే రెండవ వైఫల్యం

1500 బైట్ల వంతెన ఇంటర్ఫేస్ బయటి UDP మరియు IP హెడర్లు చేరిన తర్వాత టన్నెల్కు దాని సామర్థ్యం కంటే ఎక్కువ ఇస్తుంది. చిన్న మార్పిడులు దాటుతాయి, కాబట్టి DNS పరిష్కారమవుతుంది మరియు TLS హ్యాండ్షేక్ పూర్తవుతుంది, తర్వాత పెద్ద అప్లోడ్ ఎక్కడా లోపం లేకుండా వేలాడుతుంది. పంపేవాడు అదే సెగ్మెంట్ పరిమాణాన్ని పునరావృతం చేస్తాడు, ఎందుకంటే చిన్నగా ఉండమని చెప్పే ICMP ఫ్రాగ్మెంటేషన్ అవసర సందేశం ఎప్పటికీ చేరుకోదు.

దాన్ని ఇంటర్ఫేస్పై, MSS పై, లేదా రెండింటిపై సరిచేయండి. క్ల్యాంపింగ్కు అతిథి సహకారం అవసరం లేదు:

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

క్ల్యాంప్ TCP ను మాత్రమే తిరిగి రాస్తుంది. UDP, QUIC సహా, బదులుగా అతిథి ఇంటర్ఫేస్ తగ్గించాలి, --opt com.docker.network.driver.mtu=1400 తో నెట్వర్క్ సృష్టించేటప్పుడు లేదా సరిపోలే compose కీతో.

DNS మరియు పునరావృతం చేయదగిన తనిఖీలు

పేరు పరిష్కారం అదే మార్గాన్ని అనుసరిస్తుంది. Docker అంతర్నిర్మిత రిజాల్వర్ 127.0.0.11 వద్ద హోస్ట్ కాన్ఫిగర్ చేసిన సర్వర్లకు ఫార్వర్డ్ చేస్తుంది, కాబట్టి కంటైనర్ హోస్ట్ ఉపయోగించేదాన్ని వారసత్వంగా పొందుతుంది. ప్రైవేట్ జోన్కు టన్నెల్ ద్వారా మాత్రమే చేరగల రిజాల్వర్ సమాధానం ఇస్తే, అతిథిని ఆ చిరునామా వైపు మళ్లించండి, మరియు getent hosts తో కంటైనర్ లోపల పరీక్షించండి, హోస్ట్పై కాదు.

  • విఫలమయ్యే అభ్యర్థనను అతిథి లోపల నడపండి; హోస్ట్ వైపు పరీక్ష మరో మూల చిరునామాను ఉపయోగించి సమస్యను దాచుతుంది.
  • మీరు చేర్చిన NAT మరియు ఫిల్టర్ నియమాల కౌంటర్లను చదవండి. సున్నా సరిపోలిక ఉన్న నియమం రూటింగ్ తప్పు, విధాన తప్పు కాదు.
  • మీ SNAT నియమంలోని టన్నెల్ చిరునామా క్లయింట్ నిజంగా కలిగి ఉన్నదేనని నిర్ధారించండి.
  • ఆగిపోవడానికి సర్వర్ను నిందించే ముందు అతిథి MTU ను తగ్గించండి లేదా MSS క్ల్యాంప్ చేయండి.

జాబితాను దిగి మొదటి వైఫల్యం వద్ద ఆగండి. ఆ పొరనే సరిచేయాలి; కింద చేర్చిన ఏదైనా విరిగిపోతున్న సరిహద్దును దాచుతుంది మాత్రమే.

సంబంధిత వ్యాసాలు