Docker контејнер недоступан преко VPN-а? Упоредите подмреже
Docker додељује подмрежу на коју полаже право и VPN. Упоредите два плана адреса, па изаберите поправку која преживљава поновно повезивање.
Контејнери одговарају на канцеларијској LAN мрежи, а затим престају да одговарају у тренутку када се повеже корпоративни VPN. У контејнеру се ништа није променило: ни поновно покретање, ни ажурирање слике, ни измена конфигурације. Променила се табела рутирања домаћина, у којој рута коју је тунел додао сада покрива адресу коју је доделио Docker. Пре него што измените подмрежу или затражите изузетак од VPN-а, ставите оба плана адреса један поред другог, јер поправке захтевају веома различито време.
Прочитајте руту пре него што промените конфигурацију
Почните од мреже коју је Docker заиста изградио. IPAM блок је план адреса, а подмрежа је она линија која је важна:
docker network inspect project_default --format '{{json .IPAM.Config}}'
# [{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]Compose подразумевано додељује /16 сваком новом пројекту, па два сервиса могу да стану у опсег од 65,536 адреса. Управо та ширина чини преклапања честим: случајно изабран /16 довољно је велик да прогута сајт до којег стижете кроз тунел, и нико то не примети док се тунел не подигне.
Затим упоредите избор руте за једну адресу контејнера, једном са искљученим тунелом и једном са укљученим:
ip route get 172.18.0.7
# 172.18.0.7 dev br-3f2a9c src 172.18.0.1Два облика одговора воде на различита места. Ако излаз наводи tun0, wg0 или други уређај тунела, VPN префикс је барем толико специфичан колико и рута моста и пакет никада не стиже до контејнера. Ако и даље наводи мост, домаћин може да стигне до контејнера, а ваша грешка је филтрирање, DNS или повратна путања која отказује само у једном смеру.
Зашто је судар /16 лако изазвати
Docker узима мостовне мреже из приватних базена, а подразумевани базен долази из блока 172.16.0.0/12 у деловима од /16. Корпоративне мреже често користе исти приватни простор, а VPN за даљински приступ гура те префиксе сваком клијенту који се повеже. Када обе стране верују да поседују 172.18.0.0/16, једна табела рутирања садржи две противречне тврдње.
Победника одлучује дужина префикса, а не редослед рута. Тунел који гура 10.0.0.0/8 не побеђује руту моста 172.18.0.0/16, јер је /8 мање специфичан. Тунел који гура 172.18.0.0/16, или 172.18.5.0/24 унутар ње, побеђује. Зато један лаптоп ради на канцеларијској мрежи, а отказује на хотелском Wi-Fi-ју са истим VPN-ом: клијент добија различите префиксе.
Иста табела управља и супротним смером. Контејнер коме је потребан интерни домаћин на 10.8.4.20 шаље пакет на свој мостовни гејтвеј, а домаћин га затим рутира у тунел. Та путања обично ради јер домаћин обавља NAT, али отказује када корпоративна страна прихвата само VPN адресу лаптопа, или када филтрирање повратне путање одбаци асиметрични одговор.
Упоредите три поправке
Постоје само три излаза, и они се разликују по томе ко их мора одобрити и шта се квари док једну примењујете.
| Repair | Who owns it | What it costs |
|---|---|---|
| Renumber the container network | You | Recreates the network, restarts services, invalidates literal addresses in configs and scripts |
| Exclude your range from the tunnel | Network team | Changes what every laptop sees, needs a change request and a client profile update |
| Reach the service through a published port | You and the client | One port only, no direct container-to-container routing across the tunnel |
Пренумерација је једина поправка коју можете завршити без тикета, зато се већина текстова ту и зауставља. Јефтина је на младом пројекту, а скупа када алат за миграцију или сачувани низ за повезивање покаже на буквалну адресу. Избројте те референце пре измене YAML-а, а не после.
Изузетак од тунела је најчистији одговор када преклапање лежи у опсегу који ваша компанија заиста поседује. Он је и најспорији, и бескористан је извођачу који не може да промени профил клијента. Објављени порт или мали обрнути прокси избегавају расправу: клијент разговара са адресом коју тунел већ исправно рутира, и само тај порт мора бити доступан.
Закачите опсег намерно
За један пројекат, декларишите подмрежу у compose датотеци да би пројекат престао да узима из заједничког базена:
networks:
default:
ipam:
config:
- subnet: 10.201.7.0/24Узмите тај опсег из регистра који води ваш тим, а не из примера који сте нашли приликом претраге. Проверите га према префиксима које гура VPN, кућним мрежама са којих људи раде и осталим контејнерским мрежама на истом домаћину. Затим испланирајте поновно стварање, јер постојећа мрежа задржава своју стару подмрежу: docker compose down, затим up -d. docker network rm одбија док су крајње тачке повезане, а сваки ipv4_address унос у датотеци мора да падне у нови опсег.
За мреже које Docker ствара сам, подесите базен демона у /etc/docker/daemon.json:
{
"default-address-pools": [
{ "base": "10.201.0.0/16", "size": 24 },
{ "base": "10.202.0.0/16", "size": 24 }
]
}Базен се примењује на мреже створене након поновног покретања демона, а мостови који већ постоје задржавају своје адресе. То је згодно и лако се заборавља, зато третирајте стари пројекат као да се још преклапа док неко не поново створи његову мрежу. документација за умрежавање мотора Dockera описује правила доделе ако треба да одбраните базен на прегледу.
Linux мост и Docker Desktop отказују различито
На Linux домаћину, контејнери стоје на мостовима у простору имена домаћина. Једна табела одлучује о свему, па је горње поређење цела прича: прочитајте руту моста, прочитајте руту тунела и погледајте која побеђује за стварну адресу контејнера.
Docker Desktop ставља контејнере иза виртуелне машине са сопственим NAT-ом. Домаћин уопште нема руту до адресе контејнера; до сервиса стиже преко објављеног порта, обично везаног за 127.0.0.1. Зато VPN клијент може да поквари сервис без икаквог преклапања подмрежа: или инсталирањем руте за интерни опсег виртуелне машине, или блокирањем loopback саобраћаја док је тунел повезан. Ако ip route get на домаћину пријави да нема руте за адресу контејнера, то је очекивано, а не грешка.
Практична последица је где прво гледате. На Linux-у, почните од табеле рутирања. На Desktop-у, почните од објављеног порта и правила заштитног зида VPN клијента, па проверите да ли се интерна подмрежа виртуелне машине судара са нечим што тунел гура.
Проверите са укљученим тунелом
Поново повежите VPN двапут пре него што кажете да је решено, јер профил који додаје руте при повезивању и повлачи их при искључивању може да изгледа исправно после првог покушаја. Затим извршите провере које клијент заиста извршава:
ip route getса домаћина, користећи стварну адресу контејнера.- Захтев из другог контејнера, да се докаже да је сам сервис здрав.
curl -sv http://127.0.0.1:8080/са клијента са укљученим тунелом, затимtraceroute -nдо адресе контејнера са машине у LAN-у.sysctl net.ipv4.conf.all.rp_filterако захтев стигне до домаћина, али одговор нестане.
На крају, упишите изабрани опсег у исти регистар из којег сте га изабрали, са датумом и пројектом који га поседује. Следеће преклапање доћи ће из пројекта који нико није документовао, а једина одбрана је да је опсег резервисан намерно, а не изабран случајно.