Клиент настроен на UDP, на сервере Nginx есть блок location, указывающий на порт VPN, а ничего не приходит. Это ожидаемо: location HTTP не может передать UDP-датаграмму, как бы ни назывался внешний интерфейс. Для этого Nginx нужен слушатель stream, и после переноса конфигурации туда о том, выживет ли сессия, решает второй набор деталей.

Уровень прокси идёт перед адресом

Модуль stream в Nginx проксирует TCP и UDP, не разбирая HTTP. Модуль HTTP ожидает строку запроса, заголовки и ответ, и ничего из этого нет в нативной OpenVPN датаграмме. Поэтому выбор уровня — первое решение, и оно не зависит от того, слушатель IPv4 или IPv6.

Конфигурация, которая выглядит работающей с TCP OpenVPN, ничего не говорит о случае UDP. Транспорт здесь часть протокола, а не деталь развёртывания.

Слушатель и backend

nginx -V 2>&1 | tr ' ' '\n' | grep stream

stream {
    server {
        listen [::]:1194 udp reuseport;
        proxy_pass [2001:db8::20]:1194;
    }
}

Прежде чем что-либо редактировать, убедитесь, что сборка включает модуль stream; дистрибутивный пакет может выделить его в отдельный модуль, а отсутствующий модуль даёт ошибку конфигурации, а не туннель. Поместите блок в основной контекст конфигурации, а не внутрь http, и замените документационный адрес реальным backend.

И оба маршрута, и оба брандмауэра должны пропускать датаграммы: путь до слушателя и путь от прокси до backend. Слушатель IPv6 также не создаёт путь IPv4, поэтому если часть клиентов всё ещё использует IPv4, такой слушатель — отдельная запись со своим тестированием. Проверяйте собственный брандмауэр backend с адреса прокси, а не со своего ноутбука.

Тайм-ауты сессии — не тайм-ауты запроса

Прокси stream хранит состояние сессии UDP и отбрасывает его согласно своему тайм-ауту и настройкам ответа. Короткий тайм-аут, скопированный с релея DNS, плохо подходит для VPN, который рассчитывает обмениваться датаграммами часами, и отказ проявляется как соединение, которое тихо умирает, а не как то, которое отказывается запускаться.

Прочитайте фактический proxy_timeout развёртывания и любую настройку количества ответов, затем сравните их с поведением keepalive, которое VPN реально использует. Два числа, записанные разными людьми в разных файлах, — нормальное состояние работающей системы. Два числа, которые никогда не сравнивали, — нормальное состояние системы с перебоями. Запишите оба в паспорт сервиса, чтобы сравнение произошло один раз, при дневном свете.

Что релей меняет, а что нет

Прокси stream не завершает канал управления TLS OpenVPN и не превращает его в HTTPS. Backend остаётся службой VPN, а отношения сертификата остаются между клиентом и этой службой. Сохранение нужной идентичности backend по-прежнему задача клиента и сервера.

Обычное проксирование меняет и адрес источника, который видит backend. В журналах будет прокси, и любое правило доступа по IP на сервере VPN будет оценивать этот адрес, а не клиентский. Прозрачное сохранение источника — отдельный проект маршрутизации и привилегий, а не то, что следует из добавления udp к слушателю. Спланируйте это до того, как будет написана политика, зависящая от адреса клиента.

Проверяйте с клиента, а не с порта

Локальная проверка того, что порт UDP открыт, доказывает существование слушателя. Она не доказывает, что клиент может аутентифицироваться через него или продолжать обмен трафиком. Выполните реальное соединение с одобренного клиента, затем убедитесь, что сессия держится достаточно долго, чтобы это имело значение.

Когда кто-то сообщает, что Nginx не умеет UDP, потому что вместо него сработал простой инструмент релея, эти два факта не связаны. Инструмент доказал, что backend отвечает; он ничего не сказал о том, что поддерживает внешний интерфейс. Оба могут быть правдой, и только один из них — конфигурация для этого развёртывания.

Похожие статьи