Два записи A, одна адреса, один демон: яку б назву не ввів користувач, пакет, що надходить, однаковий, і в процесу, прив'язаного до порту 1194, немає чим їх розрізнити. Це не помилкова конфігурація, що чекає на виправлення; це межа того, що може виразити пошук за назвою. Усе, що вибирає між двома примірниками OpenVPN, має бути значенням, яке клієнт кладе у з'єднання і яке зовнішня частина може прочитати назад, а стандартний клієнт OpenVPN такого значення відкрито не кладе. Далі — до чого це призводить і які схеми справді розділяють трафік.

Почніть із того, що повертає розв'язувач

Клієнт запитує vpn-a.example і отримує адресу; ця адреса плюс порт — усе, до чого він підключається. Назва витрачається локально, під час пошуку, і ніколи не стає полем на дроті, тому слухач на тому боці не може побачити, яку мітку використано. Спрямуйте vpn-a.example і vpn-b.example на один хост, і обидва пошуки дадуть одну й ту саму адресу призначення, тому демон поглинає обидва з'єднання в один примірник, не фіксуючи різниці. Профілі на основі адреси поводяться точно так само, як на основі назви, з тієї ж причини.

Це також закриває родину спокусливих обхідних шляхів: додаткові псевдоніми, вибір сертифіката для кожної назви на одному сокеті або правило брандмауера, прив'язане до запитаної назви. Жодне з них не може діяти на інформацію, яку вже було відкинуто до того, як перший пакет залишив клієнт. Якщо два сервери мають залишатися розділеними, розділення має подорожувати разом із самим з'єднанням, тобто адреса, порт або поле корисного навантаження, яке визначає протокол.

Єдиний селектор, що рахується, їде всередині пакета

HTTP вирішує це заголовком Host, а TLS — розширенням імені сервера в ClientHello, і так одна адреса обслуговує багато сайтів за одним слухачем. Обидва працюють, бо протокол на дроті несе запит до конкретної служби. Істотний факт про OpenVPN полягає в тому, що жодного з цих полів немає на рівні, який оглядає проміжна коробка.

У стандартній схемі рукостискання TLS, що захищає канал керування, відбувається після встановлення зовнішнього сеансу і переноситься всередині нього, тому слухач, який не завершив цей сеанс, бачить непрозорий потік. Він усе ще може сказати, що це OpenVPN, бо код операції та кадрування в перших байтах упізнавані, але ім'я сервера, якщо воно є, сидить у зашифрованій частині. Проєкт, який сподівається прочитати віртуальний хост із зовнішнього пакета, читає поле, яке протокол ніколи туди не пише. Це випливає з того, як побудований тунель, а не з прогалини, яку міг би закрити розумніший збіг шаблону.

Де роздільник протоколів зупиняється

Мультиплексор того типу, який документує проєкт sslh, слухає на одному порту, оглядає перші байти і передає з'єднання тому бекенду, який говорить розпізнаним протоколом. Це справжня цінність, коли один порт має обслуговувати SSH, HTTPS і OpenVPN разом.

sslh тримає окремий зонд для кожного протоколу, і його зонд TLS може витягти ім'я сервера або значення ALPN зі справжнього ClientHello. Розпізнавання звичайного OpenVPN — це інша класифікація, ніж читання розширення TLS, і ці дві не складаються, бо клієнт, який ніколи не надсилає ClientHello на слухаючий сокет, залишає зонд без нічого для читання. Тому правило, що збігається з OpenVPN, відповідає «це клієнт OpenVPN» і далі не йде. Два бекенди OpenVPN за цим правилом невиразні, у зовнішньої частини немає підстав для вибору, і кожен сеанс приземляється в одному й тому ж місці. Мультиплексування ділить один порт між різними службами; воно не робить віртуального хостингу всередині однієї служби.

Схеми, які справді розділяють два сервери

Найдешевше чесне розділення — друга публічна адреса, по одній на примірник, і наявні профілі вже несуть потрібне, бо вказують на різні адреси. Наступне — інший порт на тій самій адресі, що не коштує нічого, крім числа в кожному профілі. TCP і UDP тримають окремі таблиці портів, тому 1194/tcp і 1194/udp — незв'язані сокети, і по одному з кожного можуть існувати на одному хості; це розділення транспорту, а не маршрутизація за назвою, і з нею це часто плутають. Обидва варіанти проходять перевірку брандмауера, бо правило збігається з тим, що пакет справді містить.

Якщо потрібна вам межа проходить між групами користувачів, а не між двома реалізаціями, її може закрити один примірник із різними конфігураціями клієнтів, власним опрацюванням сертифікатів і явною політикою доступу. Це купує політику всередині сервера, а не ізоляцію між серверами, і це різні вимоги. Ізоляція, що має витримувати під компрометацією, усе ще потребує адреси або краю брандмауера.

Термінатор TLS, поставлений перед OpenVPN, може показати справжнє ім'я сервера здатній зовнішній частині, але лише коли клієнтський бік теж налаштований на цей додатковий шар. Наявні профілі не набувають такої поведінки просто від указівки на ту саму адресу.

Доведіть селектор, перш ніж будувати

Назвіть поле, яке ідентифікуватиме бекенд, потім підтвердьте, що клієнт справді його надсилає; якщо відповідь — адреса, план тримається, а якщо це ім'я сервера всередині рукостискання, яке ніколи не доходить до слухача, жодна робота з DNS його не врятує. Три команди швидко вирішують питання слухаючого боку.

ss -lntup | grep -E ':443|:1194'
openssl s_client -connect vpn-a.example:443 -servername vpn-a.example </dev/null | head -n 20
journalctl -u openvpn-server@server-a -n 20 --no-pager

Рядок openssl дає сертифікат лише там, де щось на цій адресі завершує TLS; проти звичайного слухача OpenVPN він застрягає або зазнає невдачі, і це саме по собі відповідь на те, що розкриває зовнішній шар. Рядок journal, прочитаний на кожному бекенді, показує, який примірник прийняв сеанс. Журнали зовнішньої частини записують те, що було класифіковано, і ніколи те, що передбачалося, тому бекенд залишається єдиною інстанцією, яка знає, де приземлився користувач.

Завершіть двома профілями, призначеними для різних серверів, підключіть їх по одному і запишіть журнал бекенда для кожного. Якщо обидва сеанси з'являться в одному журналі, селектор відсутній, а не налаштований неправильно, і виправлення — це адреса або порт, на який клієнт може націлитися. Редагування правила маршрутизації не допоможе, бо правилу ніколи не давали нічого, за чим маршрутизувати. Коли розділення стане реальним, запишіть його поруч із профілями, щоб наступна людина не додала другий псевдонім і не чекала, що той зробить роботу.

Схожі статті