આ વસંતમાં મેં એક સવારનો મોટો ભાગ એક કન્ટેનરની પાછળ દોડવામાં વિતાવ્યો જે એક પણ આંતરિક નામ રિઝોલ્વ કરી શકતું ન હતું, જ્યારે બાજુનો બ્રાઉઝર કોઈ ફરિયાદ વિના વિકિ ખોલી રહ્યો હતો. ટનલ ચાલુ હતી, બ્રાઉઝર તેને સાબિત કરતું હતું, અને કન્ટેનર અલગ રૂટ ટેબલ અને અલગ રિઝોલ્વરવાળા બીજા નેટવર્ક નેમસ્પેસમાં રહેતું હતું. આગળ જે આવે છે તે હવે હું જે ક્રમમાં તપાસું છું તે છે: પહેલા રૂટ ટેબલ, બીજું રિઝોલ્યુશન, ત્રીજું ફોરવર્ડિંગ અને અંતે હોસ્ટ પ્લેટફોર્મ. પહેલેથી નિષ્ફળ જતા પગલા પર જ અટકો, કારણ કે સ્ટેકમાં નીચે નિયમો ઉમેરવાથી સીમા ખસેડવાને બદલે છુપાય છે.

નિયમ બદલતા પહેલા ત્રણેય રૂટ ટેબલની તુલના કરો

Docker ના ડિફોલ્ટ બ્રિજ પરનું કન્ટેનર docker0 ગેટવે તરફ જતું એક ડિફોલ્ટ રૂટ ધરાવે છે અને tun0 અસ્તિત્વમાં છે તેની તેને કોઈ ખબર નથી. હોસ્ટ પાસે tun0 છે, VPN એ ધકેલેલા રૂટ છે, અને કદાચ એવો પોલિસી નિયમ છે જે પ્રોબ ટ્રાફિકને તમે અપેક્ષા રાખો તેના કરતાં અલગ ઇન્ટરફેસ દ્વારા મોકલે છે. WSL પોતાના વર્ચ્યુઅલ એડેપ્ટર પાછળ ત્રીજું ટેબલ ઉમેરે છે. તેમાંથી કોઈપણને સંપાદિત કરતા પહેલા ત્રણેય છાપો.

ContextCommandWhat a wrong answer looks like
Hostip route get 10.8.0.20Leaves a physical interface instead of tun0
Containerip routeOnly 172.17.0.0/16 via 172.17.0.1
Container DNScat /etc/resolv.confA public resolver, or an upstream the tunnel never pushed
WSLip addr; ip routeOnly the WSL subnet, no Windows VPN adapter

જો કન્ટેનરનો એકમાત્ર રૂટ બ્રિજ હોય અને tun0 તેના નેમસ્પેસમાં કદી ન દેખાય, તો નીચેનું કંઈ મદદ કરશે નહીં: કોઈ નેમસર્વર ફેરફાર રૂટ બનાવતું નથી, અને કોઈ રૂટ એવી ટનલ ઓળખ બનાવતું નથી જે પીઅર સ્વીકારશે. ક્રમ મહત્વનો છે કારણ કે DNS નિષ્ફળતા અને રૂટ નિષ્ફળતા શેલની અંદરથી એકસમાન દેખાય છે.

રિઝોલ્વરને જાહેર રિઝોલ્વરને બદલે ટનલ તરફ નિર્દેશ કરો

હોસ્ટ પર, resolvectl status દરેક લિંક માટે DNS સર્વરોની સૂચિ આપે છે, અને readlink -f /etc/resolv.conf જણાવે છે કે ફાઇલ systemd સ્ટબ છે, NetworkManager ફાઇલ છે, કે વેન્ડર ક્લાયન્ટે ફરીથી લખેલું કંઈક છે. વપરાશકર્તા-વ્યાખ્યાયિત નેટવર્ક પરના કન્ટેનરની અંદર, /etc/resolv.conf નામ આપે છે 127.0.0.11, Docker ના એમ્બેડેડ રિઝોલ્વરને, જે ડેમન જે અપસ્ટ્રીમ સાથે ગોઠવાયેલો હતો તેના તરફ ફોરવર્ડ કરે છે. ડિફોલ્ટ બ્રિજ પરના કન્ટેનરને તેના બદલે બન્યા ત્યારે હોસ્ટ ફાઇલની નકલ મળી હતી, અને તે તેને રાખે છે.

તે નકલ એ કારણ છે કે કન્ટેનર શરૂ થયા પછી ઉપર આવતી ટનલ કન્ટેનરને જૂના અપસ્ટ્રીમને પૂછવા દે છે. કાં તો VPN રિઝોલ્વર સ્પષ્ટ રીતે પાસ કરો docker run --dns 10.8.0.53, અથવા "dns": ["10.8.0.53"] માં /etc/docker/daemon.json સેટ કરો અને ડેમન ફરી શરૂ કરો, અથવા ટનલ ઉપર આવે પછી કન્ટેનર ફરી બનાવો. ફરી બનાવવું સામાન્ય રીતે એક કલાક પહેલા સાચું હતું તેવા રિઝોલ્વરને ડિબગ કરવા કરતાં સસ્તું છે.

જાહેર રિઝોલ્વર મૂકવો એ એવી સમારકામ છે જે લક્ષણ રાખે છે. તે ઇન્ટરનેટ રિઝોલ્વ કરે છે અને દરેક ખાનગી ઝોનમાં નિષ્ફળ જાય છે, અને ટનલ જે ફિલ્ટરિંગ લાગુ કરવા માટે અસ્તિત્વમાં છે તેને તે ચૂપચાપ ટાળી શકે છે. જો તમે ચાલતા કન્ટેનરના /etc/resolv.conf ની અંદર લખવાનો પ્રયાસ કરો, તો અપેક્ષા રાખો Device or resource busy: Docker તે ફાઇલને bind-mount કરે છે, તેથી સંપાદનને પહેલા અનમાઉન્ટની જરૂર છે. --dns બનાવતી વખતે સેટ કરવું એ ક્રમ છે જે રીસ્ટાર્ટમાં ટકી રહે છે.

કન્ટેનર ટનલ ઉધાર લે ત્યારે ફોરવર્ડ કરો અને અનુવાદ કરો

ડિફોલ્ટ બ્રિજ સાથે, હોસ્ટ docker0 અને tun0 વચ્ચેનું રાઉટર છે, અને ડિફોલ્ટ રીતે તે બેમાંથી કોઈ કામ કરતું નથી. ફોરવર્ડિંગ ચાલુ કરો અને સ્રોત સરનામાનું અનુવાદ કરો જેથી પીઅર હોસ્ટ ટનલ સરનામું જુએ, એવું સરનામું નહીં જેના તરફ તેનો પાછળનો રૂટ નથી (tun0 ને તમારા ક્લાયન્ટ ઇન્ટરફેસને જે નામ આપે છે તેનાથી બદલો):

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -A FORWARD -i docker0 -o tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o docker0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

FORWARD નિયમો એવા હોસ્ટ પર મહત્વપૂર્ણ છે જેમની ફોરવર્ડ પોલિસી DROP છે. Docker પોતાની ચેઇન દાખલ કરે છે, તેથી વાંચવાને બદલે પેકેટ સાથે પરીક્ષણ કરો iptables -S: કન્ટેનરથી, ip route get 10.8.0.20 બ્રિજ ગેટવેનું નામ આપવું જોઈએ, અને nc -vz 10.8.0.20 443 રિઝોલ્વર પર નહીં પણ ટનલ પર જોડાવું જોઈએ અથવા ટાઇમ આઉટ થવું જોઈએ.

MASQUERADE વિના પીઅરને 172.17.0.0/16 તરફ પાછળનો રૂટ જોઈએ છે, જે મોટાભાગના રિમોટ-એક્સેસ VPN ધકેલશે નહીં. અહીં જ પોલિસી-આધારિત ક્લાયન્ટ યોજના તોડે છે: જો તે ફક્ત ચોક્કસ UID અથવા cgroups નો ટ્રાફિક પકડે છે, તો તમારા ફોરવર્ડ નિયમો ટનલની અંદર પેકેટ કદી જોતા નથી, અને સુધારો iptables માં નહીં પણ ક્લાયન્ટની રાઉટિંગ પોલિસીમાં આવે છે. હાથથી ઉમેરાયેલા નિયમો રીબૂટ પર અદૃશ્ય થાય છે, તેથી તેમને systemd યુનિટ અથવા netfilter-persistent ટેબલમાં મૂકો અને રીબૂટ પછી ફરી પરીક્ષણ કરો, કારણ કે મોડી ઉપર આવતી ટનલ તેમને વહી જવા દે છે.

જ્યારે અલગીકરણ ધ્યેય હોય ત્યારે ટનલને કન્ટેનરની અંદર મૂકો

જો એક કન્ટેનરને ચોક્કસ નોડ દ્વારા બહાર જવું હોય, તે કન્ટેનરમાં ક્લાયન્ટ ચલાવો. તેને --cap-add NET_ADMIN અને --device /dev/net/tun ની જરૂર છે, અને પછી તે પોતાનું tun0, રૂટ અને ફાયરવોલ ધરાવે છે. જો અન્ય કન્ટેનર તેમાંથી પસાર થાય, તો તેને કન્ટેનરની અંદર ફોરવર્ડિંગ અને MASQUERADE નિયમની પણ જરૂર છે, અને તે પીઅરને તેના તરફ નિર્દેશ કરતો સ્પષ્ટ રૂટ અથવા પ્રોક્સી જોઈએ છે; Docker નું ડિફોલ્ટ બ્રિજ તમારા માટે તે રૂટ ઉમેરતું નથી.

હોસ્ટ નેટવર્કિંગ, docker run --network host, સસ્તું સંસ્કરણ છે: કન્ટેનર હોસ્ટના નેમસ્પેસમાં જોડાય છે અને ટનલ રૂટ સીધા જુએ છે. તે નેટવર્ક અલગીકરણ પણ છોડી દે છે, પોર્ટ અથડામણને આમંત્રે છે, અને વ્યવહારમાં તે Linux વિકલ્પ છે. પ્રકાશિત પોર્ટ તેનો વિકલ્પ નથી. -p 8080:80 સેવાને હોસ્ટથી પહોંચવાલાયક બનાવે છે; તે આંતરિક 10.x સરનામાંને કન્ટેનરની અંદરથી પહોંચવાલાયક બનાવતું નથી, અને બંનેને ભેગા કરવા એ જ રીતે રાઉટિંગ સમસ્યા ખુલ્લા ડેટાબેઝ પોર્ટમાં ફેરવાય છે.

નામ નિષ્ફળતાને ઓવરલેપિંગ સબનેટથી અલગ કરો

Docker નું ડિફોલ્ટ બ્રિજ 172.17.0.0/16 છે, અને ઘણા કોર્પોરેટ VPN પૂલ 172.16.0.0/12 ની અંદર આવેલા છે. એકવાર ટનલ તે શ્રેણીની માલિક બને, તો કન્ટેનર માટેના ટ્રાફિકને તેના બદલે ટનલમાં રૂટ કરી શકાય છે. નામ નિષ્ફળ જાય છે, ભૂલ DNS જેવી લાગે છે, અને સમસ્યા સરનામાંઓમાં છે. ગંતવ્ય તપાસો, રિઝોલ્વર નહીં: ip route get 172.17.0.5 હોસ્ટ પર, પછી બ્રિજ પ્રીફિક્સની VPN પૂલ અને docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' સાથે તુલના કરો.

સમારકામ એ શ્રેણીમાંની એકને ખસેડવાનું છે: કાં તો daemon.json માં Docker માટે અલગ ડિફોલ્ટ સરનામા પૂલ, અથવા કોન્સન્ટ્રેટર પર અલગ પૂલ. અહીં બીજું નેમસર્વર ઉમેરવાથી કંઈ થતું નથી, અને ssh -b થી પણ નહીં: ક્લાયન્ટને ઇન્ટરફેસ સાથે બાંધવાથી સ્રોત સરનામું બદલાય છે, ટનલમાં જતો ગંતવ્ય રૂટ નહીં. ઝડપી કામવિભાજન: હોસ્ટ પર રિઝોલ્વ થતું પણ કન્ટેનરમાં ન થતું નામ રિઝોલ્વર સમસ્યા છે, જ્યારે કન્ટેનરમાં અટકતું પણ હોસ્ટ પર કામ કરતું સીધું IP કનેક્શન રૂટ અથવા ફોરવર્ડ-ચેઇન સમસ્યા છે.

WSL અને Docker Desktop Linux ના નિયમોનું પાલન કરતા નથી

તેના ડિફોલ્ટ NAT મોડમાં, WSL પોતાના વર્ચ્યુઅલ એડેપ્ટર પાછળ બેસે છે અને Windows VPN ના આંતરિક રૂટ કે DNS સફિક્સ મેળવતું નથી, તેથી બ્રાઉઝર કામ કરે છે અને ping ડિસ્ટ્રિબ્યુશનની અંદર કામ કરતું નથી. તાજેતરના Windows 11 બિલ્ડમાં ઉપલબ્ધ મિરર્ડ નેટવર્કિંગ તેના બદલે હોસ્ટ ઇન્ટરફેસ શેર કરે છે, પણ તે .wslconfig માં સક્ષમ કરવું પડે છે અને ડિસ્ટ્રિબ્યુશન wsl --shutdown થી ફરી શરૂ કરવું પડે છે. સક્રિય મોડની પુષ્ટિ કરો wslinfo --networking-mode થી, સુધારો લાગુ કરતા પહેલા, કારણ કે NAT નો જવાબ મિરર્ડ મોડ માટે ખોટો છે અને ઊલટું પણ.

Docker Desktop બીજું સ્તર ઉમેરે છે. Windows પરના Linux કન્ટેનર ઐતિહાસિક રીતે vpnkit કહેવાતા NAT અમલીકરણ પાછળ બેસે છે, અને તેમનો માર્ગ મૂળ Linux હોસ્ટથી અલગ છે. Windows કન્ટેનર Hyper-V વર્ચ્યુઅલ સ્વિચ દ્વારા જોડાય છે, અને કોર્પોરેટ ક્લાયન્ટ તે સ્વિચનો ટ્રાફિક અવરોધી શકે છે, તેથી એક જ મશીન પરના Linux કન્ટેનર નેટવર્ક સુધી પહોંચી શકે છે જ્યારે Windows કન્ટેનર પાસે કંઈ નથી. ભૌતિક એડેપ્ટર સાથે બંધાયેલ બાહ્ય સ્વિચ સામાન્ય ઉપાય છે, અને તે કન્ટેનરની નેટવર્ક ઓળખ એવી રીતે બદલે છે જે પોલિસી મંજૂર કરે નહીં.

બીજો નિયમ લખતા પહેલા, ચાર સ્તરો ક્રમમાં ચાલો અને જ્યાં તેમાંથી એક ખોટું હોય ત્યાં અટકો:

  • કન્ટેનરની અંદર: ip route ખાનગી પ્રીફિક્સ સુધી પહોંચે છે, અને /etc/resolv.conf એવા અપસ્ટ્રીમનું નામ આપે છે જે તેને રિઝોલ્વ કરે?
  • હોસ્ટ પર: ફોરવર્ડિંગ ચાલુ છે, NAT ટનલ ઇન્ટરફેસ સાથે બંધાયેલું છે, અને ફોરવર્ડ ચેઇન બ્રિજથી ટનલ સ્વીકારે છે?
  • પીઅર પર: તે પાછળનો માર્ગ જાણે છે, અથવા તમે કન્ટેનર સબનેટ છુપાવવા NAT પર આધાર રાખો છો?
  • પ્લેટફોર્મ પર: WSL NAT કે મિરર્ડ મોડમાં છે, અને કન્ટેનર Linux કે Windows છે?

દરેક પરીક્ષણ નવા કન્ટેનર અથવા શેલમાં ફરી ચલાવો. કેશ કરેલા જવાબ અથવા સ્થાપિત કનેક્શનવાળી લાંબા સમયની પ્રક્રિયા ગોઠવણી સાચી થયા પછી પણ નિષ્ફળ થતી રહેશે, અને તે નિષ્ફળતા બરાબર એવા સુધારા જેવી લાગે છે જે કામ કર્યું ન હતું.

સંબંધિત લેખો