Защо Docker контейнер не достига хостове зад VPN
Мостовите контейнери имат собствено именно пространство, затова тунелът на хоста е невидим за тях. Сравнете мрежата на хоста, tun устройство и macvlan, преди да редактирате DNS.
Контейнер, който не достига нищо зад корпоративния VPN, обикновено живее в различно мрежово именно пространство от тунела. Маршрутите, DNS сървърите и маркировките на защитната стена на клиента на хоста принадлежат на стека на хоста; контейнерът в мостова мрежа има свой. Този единствен факт обяснява повечето сигнали, които стигат до екипа на платформата, и също така е причината „VPN-ът е счупен“ и „Docker заобикаля VPN“ да могат да бъдат грешни едновременно. Две много различни конфигурации се крият зад един симптом, затова установете коя е вашата, преди да променяте настройка.
Разберете чие именно пространство притежава тунела
В Docker Desktop за macOS или Windows контейнерите работят вътре в Linux виртуална машина. VPN клиент, инсталиран на настолния компютър, създава тунел в настолната операционна система и виртуалната машина никога не го вижда. Никаква конфигурация на контейнера не поправя това, защото интерфейсът, който контейнерът би имал нужда, изобщо не съществува в неговото мрежово именно пространство.
На Linux хост тунелът живее в именното пространство на хоста и мостовите контейнери обикновено го достигат чрез маршрутната таблица на хоста с приложен NAT на източника на изхода. Когато този път се провали, причината обикновено е политика за препращане, филтриране на обратния път или припокриваща се подмрежа, а не липсващ маршрут. Потвърдете в кой от двата свята сте, преди да четете нататък:
docker info --format '{{.OperatingSystem}}'
docker run --rm --net=host alpine ip route | head -5
docker run --rm alpine ip route | head -5
Разликата между тези две маршрутни таблици е целият проблем на един екран. Ако изгледът на хоста съдържа тунелния интерфейс, а изгледът на моста не, виждате изолация на именно пространство и всичко останало е избор как да я пресечете.
Мрежата на хоста е тест, а не дизайн
Стартирането на контейнер с мрежа на хоста, което Docker документира като споделяне на мрежовото именно пространство на хоста, го кара директно да наследи тунелния интерфейс и неговите маршрути. Ако същата заявка след това успее, маршрутната теория е потвърдена и отказът е изолация на именно пространство, а не идентификационни данни, DNS или правило за достъп.
docker run --rm --net=host curl -sS -o /dev/null -w '%{http_code}\n' https://api.internal/health
Запазете го като диагностика. Мрежата на хоста се отказва от публикуването на портове и по-голямата част от изолацията, която сте искали от контейнер, а в Docker Desktop „host“ означава виртуалната машина, а не настолния компютър, така че успех или провал там може да ви подведе, ако забравите кой хост адресирате.
tun устройство и привилегиите, които идват с него
VPN клиент вътре в контейнера се нуждае от тунелно устройство и разрешение да го конфигурира. Обичайният пряк път е --privileged, който дава всяко устройство и смекчава политиката за сигурност в целия контейнер. Това е много повече, отколкото изисква тази задача, и трудно се оправдава при преглед.
sudo modprobe tun
docker run --rm -it --device /dev/net/tun --cap-add NET_ADMIN myvpn-client
По-тясната форма картографира единствения възел на устройството и добавя само възможността за администриране на мрежата. Първо заредете модула на хоста, за да съществува възелът. Ако контейнерът стартира и клиентът съобщи, че не може да отвори тунелното устройство, проверете картографирането, преди да подозирате профила, защото тази грешка обикновено е буквална.
Този дизайн също означава, че клиентът работи за всеки контейнер. Това е правилният отговор, когато всяко натоварване се нуждае от собствен тунел, и грешният отговор, когато просто сте искали тунелът на хоста да бъде видим, което екипът на платформата вероятно е предполагал, че правите.
NAT на моста променя източника, който VPN вижда
При стандартния мост изходящият трафик на контейнера се преобразува към адреса на хоста. Зад VPN корпоративната страна следователно вижда тунелния адрес на хоста, а не този на контейнера, правилата за достъп по източник се държат така, сякаш хостът е направил заявката, и два контейнера стават неразличими за VPN сървъра.
macvlan или ipvlan вместо това дава на контейнера LAN адрес, което помага за откриване в LAN и прави контейнера да изглежда като равен в сегмента. Той също така напълно заобикаля тунела на хоста, така че такъв контейнер няма да достигне префикси само за VPN, освен ако VPN не е достъпен и от тази LAN.
И двете форми са законни; те отговарят на различни изисквания. Ако изискването е „този контейнер трябва да достига услуга само за VPN“, избирате между маршрутизиране през хоста и прекратяване на тунела вътре в контейнера. Запишете този избор преди внедряването, а не след първата неуспешна заявка. Кое и да изберете, запишете адреса на източника, който далечната страна ще види, защото точно това ще покажат нейните правила за достъп и нейните журнали. Дизайн, който не може да посочи този адрес, не е завършен.
DNS следва демона, а не тунела
Контейнерът получава конфигурацията си за резолвер при стартиране, копирана от демона или от образа. Адресите, които VPN изпраща след свързване, пристигат твърде късно за това копие и се изпращат към резолвера на хоста, а не в контейнера.
Задайте резолвера изрично за услугата или го насочете към вътрешен резолвер, достъпен през тунела. Контейнер, който разрешава частно име към публичен адрес, обикновено използва публичен резолвер, а не страда от счупен маршрут, и корекцията принадлежи във файла compose или конфигурацията на демона.
Същото разсъждение важи за въпроса за адреса на изхода. Ако всеки контейнер трябва да се появява от различен VPN адрес, един тунел на хоста не може да го достави, защото NAT ги свива в един източник. Работещите форми са клиент в именното пространство на всеки контейнер или sidecar, който притежава тунела и споделя своя стек, и двете променят начина, по който се адресира приложението.
Контролен списък преди затваряне на заявката: установете именното пространство, което притежава тунела, докажете пътя с мрежа на хоста, картографирайте само нужното tun устройство, запомнете адреса на източника след NAT, задайте резолвера изрично и третирайте адресите на изхода за контейнер като архитектурно решение, а не като флаг.