Ответ уходит через LAN, а не через туннель: почему и как
Запрос, приходящий через туннель, не означает, что ответ уйдёт тем же путём. Linux ищет адрес назначения, и локальная подсеть обычно побеждает.
Служба, опубликованная через шлюз, работает из большей части интернета и не работает из одного офиса. Кто-то проверяет туннель, видит приход запроса и делает вывод, что ответ должен вернуться тем же путём. Linux так не работает, и никакая проверка туннеля этого не изменит. Ответ маршрутизируется по назначению, а тот единственный сбойный вызывающий находится в подсети, которую хост уже достигает напрямую.
Что на самом деле определяет исходящий пакет
Ядро ищет маршрут для адреса назначения пакета, просматривая правила политики в порядке приоритета, а затем таблицу, которую выбирает подходящее правило. Интерфейс, через который пришёл пакет, не играет роли, если только не написано правило или метка, чтобы это имело значение. Это факт маршрутизации данного хоста, а не неисправность туннеля.
Поэтому запрос, полученный через туннель, может породить ответ, уходящий через физический интерфейс, и поток становится односторонним без того, чтобы какое-либо устройство сообщило об ошибке. Проверяйте оба направления, прежде чем делать вывод о туннеле. Ответ, ушедший не в ту сторону, исчезает из счётчиков туннеля, поэтому две стороны расходятся в том, было ли что-то отправлено. Обратите внимание, какой счётчик изменился, прежде чем трогать правило.
Почему побеждает локальная подсеть
Хост с адресом в локальной сети имеет в главной таблице подключённый маршрут для этого префикса, а подключённый маршрут — это прямое совпадение. Когда вызывающий приходит из той же подсети, поиск находит локальный канал раньше, чем туннель вообще будет рассмотрен.
Именно асимметрия делает диагностику запутанной. Вызывающие из остального интернета работают, потому что не совпадают ни с одним локальным маршрутом, тогда как единственный вызывающий, разделяющий офисный префикс, терпит неудачу, и именно с ним кто-то и тестирует.
Покрытие пиров не то же самое, что установленные маршруты
На стороне туннеля разрешённые диапазоны пира описывают, что можно отправлять в туннель и какие источники из него принимаются. Они ничего не говорят о том, куда локальная таблица маршрутизации отправит пакет.
Если инструмент туннеля устанавливает на хосте маршрут по умолчанию, он может затащить в туннель посторонний трафик как побочный ущерб. Там, где решение должно принадлежать правилу политики, опция установки маршрутов существует именно для того, чтобы этого не произошло, а адреса, ключи и настройки конечной точки остаются точно такими, какими были. Маршрут по умолчанию, добавленный ради удобства, — обычный способ, которым хост теряет собственную локальную сеть.
Выберите таблицу по адресу источника
Правило на основе источника отправляет ответы с адреса службы в частную таблицу, значением по умолчанию которой является туннель, а всё остальное продолжает использовать главную таблицу. Выбирайте номера таблицы и приоритета, которые не используются локально, и читайте существующие правила, прежде чем что-либо вставлять. Читайте действующие правила, а не сохранённый файл, потому что после перезагрузки они могут различаться.
ip -6 route add default dev wg0 table 200
ip -6 rule add priority 32000 from 2001:db8:aa::20/128 lookup 200
ip -6 rule add priority 32001 from 2001:db8:aa::20/128 unreachableПоследняя строка заставляет отсутствующий маршрут явно терпеть неудачу вместо возврата к локальному каналу. Источник должен быть действительно назначен хосту, а обычные локальный и главный поиски должны оставаться на прежних позициях. Правило выбирает таблицу по источнику; оно не сравнивает длины префиксов между таблицами.
Сначала подтвердите путь, затем службу
Спросите ядро, что оно сделает, вместо того чтобы строить выводы по перехвату, используя адрес службы как селектор источника. Правильный ответ здесь экономит целую трассировку пакетов.
ip -6 route get 2001:db8:bb::30 from 2001:db8:aa::20Вывод должен называть туннель. Затем проверьте источник, которого вы не касались, и убедитесь, что он по-прежнему использует локальный канал, так что изменение осталось в пределах одного адреса. Более широкий селектор ничего не доказал бы относительно исходной жалобы.
Чего это не исправляет
Оставьте пересылку, правила межсетевого экрана и поведение ICMPv6 на шлюзе такими, какими они были, потому что маршрут по источнику не заменяет ничего из этого. Отсутствующее сообщение Packet Too Big по-прежнему ломает большие ответы, какая бы таблица ни выиграла поиск. Исправьте это до добавления правил маршрутизации, иначе симптом переживёт изменение.
Подтвердите модель публикации, прежде чем применять что-либо из этого. Обратный прокси, открывающий собственное соединение с бэкендом, представляет собственный источник и не сохраняет вызывающего, поэтому эта неисправность в такой схеме невозможна. Применение правила там добавило бы исключение маршрутизации, которое ничего не решает и скрывает настоящую причину.
Наконец, запишите номера правил и таблицу в управление конфигурацией хоста. Правило политики, добавленное вручную, исчезает при следующей пересборке, и офисный вызывающий возвращается с той же жалобой.