Трафік Docker і VM за OpenVPN: маршрутызацыя ці перанумарацыя?
Кантэйнеры і госці на хасце з кліентам OpenVPN або губляюць зваротны шлях, або сутыкаюцца з прэфіксам тунэля. Тры пытанні выбіраюць рашэнне.
Хаст бразіць праз тунэль, а кантэйнер побач не дасягае нічога. Апублікаваць порт з кантэйнера, які мае ўласны кліент VPN, яшчэ горш: запыт прыходзіць, а адказ ніколі не выходзіць. Абодва — гэта рашэнні аб маршрутызацыі на хасце, а Docker — толькі пасыльны.
Тры пытанні вызначаюць, які з двух выпадкаў перад вамі, і гэта займае каля хвіліны.
Дзве паломкі, якія выглядаюць аднолькава
Першая — праблема зваротнага шляху. Апублікаваны порт транслюецца ў кантэйнер, запыт прыходзіць, а адказ маршрутызуецца праз маршрут па змаўчанні хаста, які кліент OpenVPN накіраваў на tun0. Адказ выходзіць з адраса, якога аддалены партнёр не чакае, і адкідваецца. Другая — сутыкненне прэфіксаў: маст Docker па змаўчанні валодае 172.17.0.0/16, а карпаратыўны тунэль прасоўвае той жа дыяпазон.
Адна выпраўляецца табліцай маршрутызацыі, другая — перанумарацыяй моста. Рэдагаваць, пакуль не ведаеш, што ёсць што, — гэта спосаб зламаць працоўны кантэйнер.
Вырашыце трыма пытаннямі
Пытанне першае: ці знікае памылка, калі вы спыняеце VPN? Калі ўсё працуе пры адключаным тунэлі, падазравайце зваротны шлях. Пытанне другое: ці пералічвае ip route show table all той самы прэфікс двойчы — адзін раз на мосце, адзін раз на tun0? Гэта і ёсць сутыкненне. Пытанне трэцяе: пацярпелы адрас — гэта кантэйнер, госць NAT ці госць, падключаны праз мост?
Трэцяе пытанне важнае, бо ў кожнага сваё правільнае рашэнне, а прымяненне рашэння для кантэйнера да госця libvirt марнуе вечар.
ip route
ip route show table all | grep -E '172\.1[7-9]|10\.8'
docker network inspect bridge --format '{{.IPAM.Config}}'Зваротны шлях: табліца для аднаго адраса крыніцы
Калі трафік кантэйнера павінен выходзіць праз фізічны інтэрфейс, пакуль сам хаст выкарыстоўвае тунэль, маршрутызацыя па крыніцы — гэта найменшае змяненне. Дадайце правіла, якое супадае з адрасам кантэйнера, і накіруйце яго ў асобную табліцу. Больш нішто на хасце не рухаецца.
ip rule add from 172.22.0.3 lookup 10
ip route add default via 172.22.0.1 table 10Кожны пакет, крыніца якога — гэты адрас, спачатку звяртаецца да табліцы 10, і табліца 10 накіроўвае яго на шлюз моста, а не ў тунэль.
Праверце з дапамогай ip route get 1.1.1.1 from 172.22.0.3. Адказ павінен называць інтэрфейс моста, а не tun0. Правілы, дададзеныя такім чынам, знікаюць пры перазагрузцы, таму змясціце іх у unit або сеткавы хук, які валодае кантэйнерам.
Той жа шаблон працуе для кантэйнера WireGuard, дзе зваротны шлях таксама патрабуе яўнага правіла.
Сутыкненне прэфіксаў: перанумаруйце мост
Табліца маршрутаў накіроўвае адзін прэфікс у адно месца. Калі VPN прасоўвае 172.17.0.0/16, а мост Docker ужо там, перамагае меншая метрыка: Docker усталёўвае свой падключаны маршрут з метрыкай 0, а прасунуты маршрут прыходзіць з 50. Тады тунэль выглядае зламаным, пакуль Docker працягвае працаваць, або наадварот — у залежнасці ад парадку ўсталявання. Перанумаруйце мост замест барацьбы з метрыкай.
{
"bip": "10.200.0.1/24",
"default-address-pools": [{"base": "10.201.0.0/16", "size": 24}]
}Перазапусціце Docker пасля змены і перастварыце сеткі, пабудаваныя на старым пуле. Змена метрыкі замест гэтага толькі пераносіць канфлікт на наступную загрузку.
VM патрабуюць яшчэ іншага адказу
Госць libvirt у сетцы NAT па змаўчанні ўспадкоўвае маршрутызацыю хаста і перастае дасягаць знешняга свету, як толькі тунэль хаста авалодвае маршрутам па змаўчанні. Пераключэнне госця на мост або прыладу macvtap дае яму ўласны шлях у фізічнай сетцы. У virt-manager дадайце абсталяванне, выберыце Network, задайце крыніцу як хост-прыладу macvtap, пакіньце virtio у якасці мадэлі, затым адключыце стары інтэрфейс NAT.
Госць macvtap звычайна не можа дасягнуць свайго хаста. Гэта чаканыя паводзіны, а не памылка, і гэта варта запісаць у нататку, якую вы пакідаеце.
Для госця, якому патрэбна толькі LAN хаста, у кліенце пастаўшчыка можа быць адсутны перамыкач: з Mullvad mullvad lan set allow аднаўляе лакальную дасяжнасць, не закранаючы libvirt. А калі кантэйнер павінен быць дасяжным толькі праз тунэль, прывяжыце апублікаваны порт да адраса тунэля, -p 10.8.0.5:8080:8080, замест публікацыі на кожным адрасе.