Почему маршрут полного туннеля обрывает сервер, который его несёт
Маршрут по умолчанию через туннель захватывает и внешние пакеты, которые его несут. Закрепите конечную точку маршрутом к хосту и держите ответы сервера вне его.
Включите полный туннель, и теперь каждый адрес назначения принадлежит интерфейсу VPN, включая машину, которая его завершает. Внешние пакеты, несущие туннель, адресованы этой машине, поэтому маршрут в итоге съедает тот транспорт, от которого зависит. Один дополнительный конкретный маршрут решает это, и причину стоит понять. Без этой причины следующая пересборка снова внесёт ту же ошибку.
Маршрут, который ест собственный транспорт
Инкапсуляция заворачивает каждый пакет во второй заголовок. Внешний адресован от локального физического адреса к публичному адресу сервера, и он должен пройти через физический канал, прежде чем появится хоть какой-то туннель.
Теперь пусть поиск по этому публичному адресу выберет туннель. Чтобы отправить пакет, машина должна его инкапсулировать, а для этого нужен маршрут к тому же адресу, и он возвращает туннель. Клиенты справляются с этим одним из двух способов. Осторожный отказывается устанавливать маршрут по умолчанию и сообщает об ошибке, а менее осторожный сообщает об успехе и затем ничего не сдвигает. Тихий отказ — тот, что стоит половины дня.
Совпадение самого длинного префикса решает поиск до обращения к любой метрике, поэтому маршрут к одному адресу превосходит любой маршрут по умолчанию на машине. В этом весь механизм исправления.
Установите исключение до маршрута по умолчанию
Создайте маршрут к одному адресу для сервера, с физическим шлюзом в качестве следующего перехода, до того как сдвинется маршрут по умолчанию. Порядок важен: установка после означает жизнь со сломанным туннелем, пока вы печатаете.
Большинство клиентов делают это без запроса. OpenVPN ищет удалённый адрес и закрепляет его перед перезаписью шлюза по умолчанию, а его параметр route-delay существует для платформ, где эта последовательность соревнуется. wg-quick выбирает совсем другой путь, помечая пакеты и обращаясь к правилу политики вместо добавления исключения. Разные механизмы, одно требование: внешний пакет должен вырваться из туннеля, который сам создаёт.
ip route add 203.0.113.10/32 via 192.168.1.1 dev eth0
ip route get 203.0.113.10
Вывод поиска — это приёмочный тест. Он должен назвать физическое устройство и физический следующий переход. Устройство туннеля в этом ответе означает, что исключения нет или оно поставлено после чего-то, что его перекрывает.
Зеркальное отражение на сервере
Та же ловушка ждёт на другой стороне, только в обратную сторону. Дайте серверу маршрут по умолчанию через другой туннель или протолкните ему маршрут, покрывающий публичные адреса клиентов, и его ответы приобретут привычку идти не туда.
Представьте клиента, который подключается и отправляет запрос. Ответ адресован публичному адресу этого клиента, который теперь совпадает с маршрутом туннеля, поэтому уходит с другого интерфейса, неся источник, который клиент никогда не набирал. Клиент может получить этот пакет и всё равно его отбросить, потому что ничто не связывает его с отправленным запросом. Идите от решения маршрутизации сервера, а не от тайм-аута клиента, поскольку только одно из них показывает действительный выбор.
ip route get 198.51.100.44 from 10.90.0.1
ip rule show
sudo tcpdump -ni any host 198.51.100.44
Есть три исправления, и они не равны. Привязка службы к физическому адресу или трансляция источника — обе скрывают решение маршрутизации вместо того, чтобы его исправить. Отправка ответного трафика пула туннеля через отдельную таблицу исправляет причину, а остальные два приемлемы только пока проект маршрутизации заморожен.
Исключения, которые туннель продолжает красть
Нескольким задачам нужен открытый интернет даже тогда, когда туннель владеет маршрутом по умолчанию, и каждой нужно своё исключение. Обновлятель динамического DNS обычно ломается первым.
Он разрешает имя провайдера, открывает соединение и обнаруживает, что его собственные пакеты идут через туннель, адрес которого изменился секунды назад, поэтому обновление срывается или публикует неверный адрес. Три выхода: закрепить провайдера маршрутом к хосту через физический шлюз, запустить обновление до поднятия туннеля или дать обновлятелю таблицу политики, к которой туннель не прикасается. Синхронизация времени подвержена тому же на устройстве, которое загружается без резолвера, а конечные точки проверки сертификатов по той же причине входят в список.
Исключение, которое никто не записал, — это исключение, которое следующая пересборка тихо выбросит.
Докажите это после переподключения, а не до него
Проверьте три адресата, а не один: конечную точку, частный адрес за туннелем и публичный адрес за ним. Один успешный поиск почти ничего не говорит о двух других.
ip route get 203.0.113.10
traceroute -n 203.0.113.10
ip route get 10.90.0.5
ip route get 1.1.1.1
Затем перезапустите соединение, потому что клиент, который при переподключении заново строит свою таблицу, выбросит маршрут, набранный вручную. Если включён kill switch, проверьте, что конечная точка разрешена, иначе туннель не сможет вернуться после смены сети, и симптом будет похож на аварию. Храните исключение в профиле или в unit-файле, а не в истории shell, чтобы переподключение воссоздавало его, а не стирало.