Կոնտեյների փաթեթը երբեք չի հասնում tun0 և կոնտեյների վրա լրացուցիչ հնարավորությունները դա չեն փոխի։ Հյուրի և թունելի միջև կան երկու երթուղու որոնում՝ մեկը հյուրի ցանցի անվանատարածքի ներսում, մեկը հոսթի վրա այն բանից հետո, երբ կադրը վայրէջք է կատարում կամրջի վրա, և երկրորդը դիմում է այլ աղյուսակի՝ այլ համապատասխանության կանոններով։ Իմ հղումային դասավորությունը Linux հոսթ է, որտեղ աշխատում է OpenVPN հաճախորդ, որը պահում է 10.8.0.10 -ը tun0 -ի վրա, Docker կամուրջ 172.18.0.0/16 -ում, և մասնավոր հասցե, որին հասնում է միայն թունելի կողմը։ Նպատակը մնում է նեղ՝ այդ հյուր ենթացանցը դուրս է գալիս թունելով, մինչ հոսթը պահում է իր սովորական uplink-ը։

VPN հաճախորդը կոնտեյների ներսում աշխատեցնելը այլ ձևավորում է, ոչ թե կարճ ճանապարհ։ Այն ժամանակ կոնտեյներինն են թունելն ու հավատարմագրերը, և աշխատանքը տեղափոխվում է Dockerfile՝ iptables-ում մնալու փոխարեն։

Փոխանցումը երթուղի է ընտրում ըստ նպատակակետի, ապա NAT-ը վերագրում է աղբյուրը

Երբ սահմանված է net.ipv4.ip_forward=1 -ը, փոխանցված փաթեթը երթուղորդվում է միայն ըստ նպատակակետի՝ հիմնական աղյուսակում։ Աղբյուրը այդ որոշման մեջ դեր չի խաղում։ Միայն երթուղու ընտրությունից հետո միջուկը կատարում է POSTROUTING -ը, և հենց այնտեղ է Docker-ի սեփական կանոնը՝ -s 172.18.0.0/16 ! -o br-appnet -j MASQUERADE։ Կամուրջը մեկ այլ ինտերֆեյսի ուղղությամբ լքող ամեն ինչ թարգմանվում է, և այն հասցեն, որի վերածվում է, կախված է այն ինտերֆեյսից, ուր երթուղին ուղարկել է այն։

Այդ կանոնը բացատրում է ինձ հարցնող ախտանիշների մեծ մասը։ Եթե հիմնական աղյուսակում մասնավոր նպատակակետի երթուղի չկա, փաթեթը դուրս է գալիս uplink-ով՝ կրելով հոսթի ֆիզիկական հասցեն։ Ձեր մատակարարը գցում է նպատակակետը, կամ հեռավոր կայքը գցում է 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

Եթե այդ պատասխանը նշում է uplink-ը, թունելը նկարում չէ, և թունելի կողմի ոչ մի կարգավորում չի օգնի։

Տեղափոխեք հյուրին թունելի սեփական հասցեին

Ամենափոքր աշխատող փոփոխությունը ելքի վրա աղբյուրի բացահայտ վերագրումն է։ Տեղադրեք այն, ոչ թե ավելացրեք վերջում՝ 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-ը նախքան սերվերին կանգառի համար մեղադրելը։

Անցեք ցանկով և կանգ առեք առաջին ձախողման վրա։ Հենց այդ շերտն է, որ պետք է ուղղել՝ այն ամենը, ինչ ավելացվում է ավելի ներքև, միայն թաքցնում է կոտրվող սահմանը։

Առնչվող հոդվածներ