Почему проброс портов VPN в Docker никогда не доходит до OpenVPN
Порт хоста, порт контейнера и транспорт — три отдельных решения. Проследите одну попытку UDP через каждую границу, прежде чем трогать сертификаты.
Ваш контейнер может слушать UDP 1195, пока хост публикует 1194, и это правильно, пока так говорит сопоставление. Числа образуют таблицу перевода: клиент набирает порт хоста, Docker переписывает назначение на порт контейнера, а OpenVPN отвечает на порту, который называет его собственная конфигурация. Несовпадение в любом из этих звеньев даёт тихий отказ, похожий на работу межсетевого экрана. Сертификаты и шифры находятся ниже по цепочке и не могут это исправить.
Проследите один пакет от клиента до процесса, прежде чем что-либо менять в аутентификации.
Три числа, одно соединение
Эти три числа — удалённый адрес назначения, который использует клиент, опубликованное сопоставление на хосте и слушатель внутри контейнера. Они не обязаны совпадать, но должны образовать цепочку. Совпадающие числа — частный случай, который случайно оказался самым распространённым, поэтому несовпадение легко записать один раз и трудно заметить потом.
Запишите цепочку одной строкой перед отладкой: адрес и порт клиента, сопоставление хоста, слушатель контейнера, транспорт. Дефект в цепочке проявляется как число, которое встречается дважды с разными значениями.
| Location | Example |
|---|---|
| Remote client destination | Host address, UDP 1194 |
| Published mapping | Host UDP 1194 to container UDP 1195 |
| Container listener | OpenVPN on UDP 1195 |
Что на самом деле говорит короткий синтаксис
В короткой форме левая часть — это порт хоста, правая — порт контейнера, а суффикс с косой чертой выбирает транспорт. Если суффикс опущен, Docker считает сопоставление TCP, поэтому слушатель UDP за сопоставлением без протокола — это слушатель, до которого никто не дойдёт. Это поведение по умолчанию задокументировано и всё ещё удивляет тех, кто сравнил числа и счёл дело сделанным.
Длинная форма явно фиксирует адрес привязки и протокол, что стоит дополнительных строк для всего, что обращено в сеть. Перечитайте опубликованное сопоставление, вместо того чтобы доверять файлу, который его создал.
ports:
- 1194:1195/udpГде пакет может остановиться
Запрос может быть отброшен до Docker, в Docker или у слушателя. Перед Docker может стоять облачный межсетевой экран или маршрутизатор с собственной пересылкой, и этому устройству нужен порт, обращённый к хосту, и правильный транспорт. Внутри Docker сопоставление на неверный порт контейнера пересылает в закрытый сокет.
Затем слушатель: конфигурация OpenVPN называет порт и протокол, а клиент, пришедший на другой порт внутри контейнера, не достигает ничего. Проверка службы UDP через TCP ничего не доказывает ни на одном из этих этапов, поэтому используйте тот транспорт, который будет использовать клиент.
Адреса привязки определяют доступность
Опубликованное сопоставление, привязанное к loopback, доступно только с хоста, а привязанное ко всем интерфейсам доступно везде, где позволяет межсетевой экран. В файле Compose без адреса оба выглядят одинаково, а значение по умолчанию в Docker — широкое.
Решите, какую экспозицию подразумевает развёртывание, и запишите её явно. Внутренняя проверка, подключающаяся через loopback, и удалённый клиент, который не может подключиться, могут оба точно описывать один и тот же контейнер.
Читайте текущее состояние
Проверьте фактическое сопоставление работающего контейнера и слушатель в его сетевом пространстве имён. Файл Compose мог быть изменён после запуска контейнера, метаданные образа могут объявлять порт, не публикуя его, а второй контейнер может уже занимать порт хоста. Объявить порт в образе — не то же самое, что опубликовать его, и ни то ни другое не равно прослушиванию.
Три разных состояния, три разные команды, и только последняя связана с OpenVPN.
Когда сопоставление верно
Как только пакет доходит до OpenVPN, его журнал — это место, где читают о TLS и аутентификации. Перегенерация сертификатов, чтобы исправить пакет, который так и не пришёл, — это пустая работа, добавляющая вторую переменную. Держите заметку о сопоставлении рядом с профилем клиента, чтобы следующий человек прочитал одну строку, а не заново открывал все три числа. Один перехват пакетов на стороне хоста решает, какое из трёх звеньев неверно, и стоит меньше, чем перегенерация сертификата.
Описанный здесь случай — публикация через мост. Сеть хоста и маршрутизируемые адреса контейнеров обходят перевод, поэтому в таких схемах те же числа означают другое.