Docker կոնտեյներների թրաֆիկը շրջանցում է հոսթի VPN-ը. ինչպես ստուգել
Հոսթի VPN-ը ծածկում է միայն հոսթի անվանատարածքը։ Այս ստուգումներով պարզեք՝ կամուրջի կոնտեյներների թրաֆիկը մտնում է թունել, թե ուղիղ դուրս գալիս։
Ձեր հոսթի զննարկիչը ցույց է տալիս VPN-ի ելքի հասցեն, կոնտեյները հաղորդում է ձեր տնային կապի մասին, և ինչ-որ մեկը դա անվանում է արտահոսք։ Ոչինչ չի արտահոսել։ Հոսթի թունելը ինտերֆեյսների, երթուղիների և կանոնների փաթեթ է, որոնք պատկանում են հոսթի ցանցային անվանատարածքին, իսկ կամրջի վրա գտնվող կոնտեյները այլ անվանատարածք է՝ իր լռելյայն երթուղով։ Ես նստել եմ Compose-ի կույտի վրա, որտեղ VPN-ի հաճախորդը միացված էր շաբաթներով, և ոչ մի կոնտեյներային փաթեթ երբեք չէր մտել այնտեղ։
Ստուգեք անվանատարածքը սկուտեղի պատկերակից առաջ
Անվանատարածքներն են ամբողջ փաստարկը։ Երբ Docker-ը կոնտեյներ է սկսում կամուրջային ցանցում, այն ստեղծում է ցանցային անվանատարածք, միացնում է veth զույգի մի ծայրը դրա ներսում և տալիս է այդ անվանատարածքին հասցե և լռելյայն երթուղի։ Թունելի ինտերֆեյսը, ինչպես էլ այն կոչվի, ապրում է հոսթի անվանատարածքում։ Կոնտեյների ներսում թրաֆիկը չի կարող տեսնել այն, և ոչ մի հաճախորդի կարգավորում դա չի փոխում դրսից։
Երկու աջակցվող քայլ դուրս են բերում ձեզ մեկուսացումից։ --network host-ը կոնտեյները տեղադրում է հոսթի անվանատարածքի ներսում, ուստի այն ժառանգում է հոսթի երթուղիները և դրանով իսկ թունելը։ --network container:vpn-ը կիսում է մեկ այլ կոնտեյների անվանատարածքը, և հենց այդպես են sidecar-ի նախագծերի մեծ մասը աշխատանքային բեռը ուղարկում VPN կոնտեյների միջով։ Երկուսն էլ բացահայտ ընտրություններ են. սովորաբար դրանցից միայն մեկն է այն, ինչ նկատի ուներ տեղակայողը։
Հոսթի ռեժիմը անվճար արդիականացում չէ։ Կոնտեյնը դադարում է ունենալ իր սեփական հասցեն, պորտերի հրապարակումը դադարում է գործել, և այնտեղ NET_ADMIN պահող պրոցեսը կարող է վերագրել հոսթի երթուղավորումը։ Դա ընդունելը կարող է ճիշտ որոշում լինել։ Ենթադրել, որ այն արդեն միացված է, այն ձևն է, ինչպես մարդիկ երեկոն անցկացնում են կարգաբերելով թունել, որը երբեք ուղու վրա չի եղել։
Հետևեք փաթեթին կամրջից դուրս
Կամրջի կոնտեյնը իր փաթեթն ուղարկում է իր լռելյայն դարպասին, որը հոսթի կամուրջի ինտերֆեյսն է։ Այնուհետև հոսթը փոխանցում է փաթեթը և լռելյայն կարգավորումով թարգմանում է աղբյուրի հասցեն իր հասցեով, մինչև փաթեթը դուրս կգա։ Հենց այդ թարգմանության քայլն է, որ լուռ խափանում է քաղաքականությունը։
Երբ փաթեթը հասնում է թունելի վերջնակետին, այն կրում է հոսթի հասցեն։ Ցանկացած կանոն, քաղաքականության երթուղի կամ բաժանված թունելի որոշում, որը հիմնված է կոնտեյների սկզբնական հասցեի վրա, դադարում է համընկնել, և տարբեր ելքերով դուրս գալու համար նախատեսված երկու կոնտեյներ հնարավոր չէ տարբերել միայն աղբյուրով։ Եթե ձեզ անհրաժեշտ է երթուղավորում յուրաքանչյուր կոնտեյների համար, որոշումը պետք է կայացվի թարգմանությունից առաջ կամ ձեր վերահսկած անվանատարածքի ներսում։
Docker-ը ինքն է պահպանում այս կանոնները՝ այն firewall backend-ով, որով կարգավորվել է daemon-ը։ Փոխանցվող թրաֆիկի աջակցվող կեռիկից դուրս ձեռքով գրված կանոնները, DOCKER-USER, կարող են վերադասավորվել կամ հեռացվել, երբ daemon-ը վերագործարկվի կամ հոսթը արդիականացվի։ Docker-ի փաթեթների զտման փաստաթղթերը ցույց են տալիս շղթաների հերթականությունը. գործնական կետն այն է, որ յուրաքանչյուր կանոնի պետք է տեր և վերաբեռնման ուղի, որը դուք իսկապես ստուգել եք։
Փորձարկեք երկու համակարգերն առանձին
Մեկ անվանատարածքից ապացույցը ոչինչ չի ասում մյուսի մասին։ VPN կոնտեյների ներսում գործարկված հարցումը ապացուցում է, որ թունելը աշխատում է այդ կոնտեյների համար։ Դա ապացույց չէ հոսթի մասին, և նույն հրամանը --network host կոնտեյներից գործարկելը ապացույց չէ կամրջի մասին։
# host namespace
ip route get 1.1.1.1
ip -brief addr show
# a fresh container on the same bridge network
docker run --rm --network appnet alpine sh -c 'ip route; cat /etc/resolv.conf; ip -6 route'
Այնուհետև կրկնեք փորձարկումը իրական հավելվածի կոնտեյների ներսում, այլ ոչ նմանատիպ պատկերի մեջ։ Հավելվածը կարող է կրել լրացուցիչ երթուղի, proxy-ի միջավայրի փոփոխական կամ այլ լուծիչ, և դրանցից յուրաքանչյուրը փոխում է պատասխանը։ Ամեն անգամ ստուգեք անունների լուծումը և հասցեների երկրորդ ընտանիքը. օգտատիրոջ կողմից սահմանված կամուրջների կոնտեյներները լուծվում են Docker-ի ներկառուցված լուծիչով 127.0.0.11 հասցեում, և կամրջի IPv6 լռելյայն երթուղին կարող է թրաֆիկը դուրս տանել, մինչ դուք զբաղված եք միայն IPv4 թունելի փորձարկմամբ։
Կարդացեք օրինաչափությունը, նախքան հավատարմագրերին դիպչելը
Երբ հոսթը աշխատում է, իսկ կոնտեյնը՝ ոչ, պատճառը գրեթե միշտ կառուցվածքային է, և բանալիների պտտումը կամ հաճախորդի վերատեղադրումը կորցնում է կես օր։ Նախ դասավորեք ախտանիշը, և ուղղումը սովորաբար ինքն իրեն անուն է տալիս։
| What you see | Usual cause | First check |
|---|---|---|
| Host exits through the VPN, container shows the ISP address | The container never entered the tunnel | Default route inside the container |
| Container works until the daemon restarts, then stops | Rules outside the supported hook, or a changed backend | Daemon's reported firewall backend and DOCKER-USER |
| Container loses internal hosts after the tunnel comes up | VPN prefix overlaps the Docker bridge subnet | ip route on the host, then docker network inspect |
| Small replies arrive, large ones hang | Tunnel MTU or missing MSS clamping | Link MTU on both ends of the tunnel |
| Container falls back to the ISP address when the tunnel drops | Nothing enforces the kill switch for forwarded traffic | Stop the tunnel with a request in flight |
Համընկնման տողը արժանի է իր սեփական նախադասությանը։ VPN պրոֆիլը, որը երթուղի է մղում 172.17.0.0/16-ի համար, կամ 10.0.0.0/8-ի համար, որը պատահաբար պարունակում է ձեր կամրջի նախածանցը, ստիպում է թունելին հավակնել կոնտեյների ենթացանցին, և թարգմանված հասցեներին ուղղված պատասխանները կգնան սխալ ուղղությամբ կամ կանհետանան։ Docker ցանցի վերահամարակալումը սովորաբար ավելի մաքուր է, քան բացառություններ կուտակելը։
Դարձրեք ծածկույթը բացահայտ, ապա դիտավորյալ կոտրեք այն
Երկու նախագիծ դիմանում են վերանայմանը։ Կիսեք VPN կոնտեյների անվանատարածքը, և յուրաքանչյուր ծածկված աշխատանքային բեռ օգտագործում է մեկ թունել՝ մեկ վերագործարկման սահմանով, ինչը պարզ է այնքան ժամանակ, քանի դեռ մի ծառայության պետք չէ այլ ելք կամ սեփական DNS ուղի։ Կամ ուղղեք կոնտեյներների ցանցը հոսթի VPN դարպասին: փոխանցումը միացված, կամրջի նախածանցը ուղղված թունելին, վերադարձի թրաֆիկը բացահայտ մշակված։ Դա գնում է վերահսկողություն յուրաքանչյուր ցանցի համար և ձեզ արժենում է կանոնների հավաքածու, որը պետք է պահպանեք daemon-ի և հաճախորդի արդիականացումների ընթացքում։
Ինչպես էլ լինի, կարևոր փորձարկումը ձախողման դեպքն է։ Կանգնեցրեք թունելը, երբ կոնտեյների հարցումը թռիչքի մեջ է, և տեսեք, թե ուր է գնում փաթեթը։ Եթե այն վերադառնում է ուղիղ ուղուն, ծածկույթը երբեք չի պարտադրվել, քանի որ հաճախորդի kill switch-ը կառավարում է հաճախորդի սեփական թրաֆիկը, այլ ոչ կամրջից փոխանցվող փաթեթները։ Դրանից հետո վերագործարկեք daemon-ը և հոսթը և երկրորդ անգամ հաստատեք արդյունքը. դա այն պահն է, երբ ձեռքով գրված կանոնները անհետանում են։
Նախքան այն ավարտված անվանելը, հաստատեք չորս բան. թունելի ինտերֆեյսը նույն անվանատարածքում է, ինչ թրաֆիկը, կոնտեյների փորձարկումը անցկացվել է իրական կոնտեյների ներսում, անունների լուծումը և հասցեների երկու ընտանիքները ստուգվել են, և թունելի ձախողման փորձարկումը դեռ փակ է ձախողվում։ Այնուհետև գրեք firewall backend-ը, հաճախորդի տարբերակը և յուրաքանչյուր կանոնի տերը։ Հենց այդ գրառումն է խանգարում, որ հաջորդ արդիականացումը թողնի հին ենթադրությունների չփաստաթղթավորված խառնուրդ։