Повний тунель чи маршрут до кінцевої точки: як залишити VPN-сервер доступним
Тунель проходить через мережу, яку він замінює. Порівняйте виняток у вигляді маршруту до хоста з позначкою сокета на рівні застосунку та дізнайтеся, коли кожен із них відмовляє.
Додайте маршрут за замовчуванням через тунель, і власні пакети тунелю підуть за ним. Таблиця тоді містить правило, яке саме себе знецінює. Зашифроване з'єднання із сервером намагається пройти всередині з'єднання, яке воно намагається встановити.
Два механізми запобігають цій петлі. Один видно в таблиці маршрутизації, інший живе всередині застосунку.
Внутрішній і зовнішній трафік — різні рішення
Пакет застосунку потрапляє у віртуальний інтерфейс і інкапсулюється. Результат — новий пакет, адресований публічній адресі сервера. Цьому пакету потрібен маршрут у фізичній мережі, бо ніщо в ньому не повинно потрапити в тунель.
Обидва — рішення щодо маршрутизації, і лише перше належить тунелю. Коли клієнт встановлює маршрут за замовчуванням, що охоплює й сервер, зовнішній пакет теж перехоплюється.
Симптоми миттєві й повні. Рукостискання завершується, і після цього нічого не тече, або з'єднання падає тієї ж миті, коли встановлюється маршрут. В обох випадках keepalive більше не може вийти.
Перший варіант: маршрут до хоста для кінцевої точки
Прямий підхід додає маршрут для адреси сервера через початковий шлюз. Це займає один рядок. Його бачить кожен, хто читає таблицю. Його також легко пояснити в записі про зміну.
Його слабкість проявляється, коли змінюється нижній шлях. Збережений маршрут називає шлюз і інтерфейс зі старої мережі. Після зміни Wi-Fi цього шлюзу може не бути, а маршрут залишається, виглядає правильно і нічого не робить.
# before the tunnel: which path reaches the endpoint?
ip route get 198.51.100.7
# pin it through the current gateway
ip route add 198.51.100.7/32 via 192.168.1.1 dev wlan0
# after the tunnel is up, confirm the pin survived
ip route get 198.51.100.7
Ім'я хоста ускладнює це. Якщо кінцева точка — ім'я, що розв'язується в кілька адрес, виняток має охоплювати адресу, яка фактично використовується. Пізніший запит може повернути те, що маршрут ніколи не охоплював.
Другий варіант: захистити сокет
Інший підхід ніколи не торкається таблиці маршрутизації. Клієнт позначає або захищає сокет, що несе тунель, тому операційна система за політикою надсилає трафік цього сокета поза тунелем. Android надає цей механізм VPN-застосункам напряму. Настільні клієнти реалізують еквіваленти за допомогою позначок міжмережевого екрана або викликів прив'язки до пристрою.
Перевага в тому, що виняток іде за з'єднанням, а не за збереженим шлюзом. Зміна мережі переписує нижній шлях, і захищений сокет рухається разом із ним, бо він ніколи не був прикріплений до адреси. Таблиця маршрутів залишається чистою.
Ціна — видимість. Ніщо в таблиці маршрутизації не показує виняток, тому рецензент, який шукає маршрут до хоста, нічого не знаходить і може дійти висновку, що схема небезпечна. Захист живе в коді клієнта та в правилах політики, які цей код встановлює.
Вибір між ними
Обирайте механізм рівня сокета, коли клієнт його підтримує, бо він переживає зміни мережі, які ламають прикріплений маршрут. Обирайте маршрут до хоста, коли виняток має бути видимим для інших інструментів або коли клієнт не пропонує нічого кращого.
Жоден із механізмів не скасовує потреби в тому, щоб адреса сервера взагалі була доступною. Приватний шлюз має публічну адресу прослуховування, і саме ця адреса має залишатися поза тунелем. Внутрішні мережі за ним стають доступними лише після появи тунелю.
Що б ви не обрали, тримайте це поруч із компонентом, якому належить тунель. Заблуканий маршрут до хоста, доданий вручну, працює до наступної мережі, а потім стає загадковим збоєм завтрашнього дня.