കണ്ടെയ്നറിന്റെ പാക്കറ്റ് ഒരിക്കലും tun0 ലേക്ക് എത്തുന്നില്ല, കൂടാതെ കണ്ടെയ്നറിലെ അധിക കഴിവുകൾ അത് മാറ്റില്ല. അതിഥിയും ടണലും തമ്മിൽ രണ്ട് റൂട്ട് തിരച്ചിലുകളുണ്ട്: ഒന്ന് അതിഥിയുടെ നെറ്റ്വർക്ക് നാമസ്ഥലത്തിനുള്ളിൽ, ഒന്ന് ഫ്രെയിം ബ്രിഡ്ജിൽ എത്തിയശേഷം ഹോസ്റ്റിൽ, രണ്ടാമത്തേത് വ്യത്യസ്ത പൊരുത്ത നിയമങ്ങളുള്ള മറ്റൊരു പട്ടികയോട് ചോദിക്കുന്നു। എന്റെ റഫറൻസ് ലേയൗട്ട് ഒരു Linux ഹോസ്റ്റാണ്, അതിൽ OpenVPN ക്ലയന്റ് പ്രവർത്തിക്കുന്നു, അത് 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 ക്ലാംപ് ചെയ്യുകയോ ചെയ്യുക।

പട്ടികയിലൂടെ താഴേക്ക് പോയി ആദ്യ പരാജയത്തിൽ നിർത്തുക। ആ പാളിയാണ് ശരിയാക്കേണ്ടത്; താഴെ ചേർക്കുന്നതെല്ലാം പൊട്ടുന്ന അതിർത്തി മറയ്ക്കുന്നു മാത്രം।

അനുബന്ധ ലേഖനങ്ങൾ