Stream-релей у Nginx для OpenVPN UDP: що він змінює
UDP не місце в HTTP location. Перенесіть його на рівень stream, підберіть тайм-аут сесії для VPN і розраховуйте, що джерелом буде проксі.
Клієнт налаштований на 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 відповідає; він нічого не сказав про те, що підтримує зовнішній інтерфейс. Обидва можуть бути правдою, і лише один із них — конфігурація для цього розгортання.