Приложение привязывается к адресу VPN, а соединение всё равно уходит через обычный маршрут по умолчанию. В bind ничего не сломалось: он сделал ровно то, что делает bind. Привязка сокета к локальному адресу выбирает адрес источника, который ядро записывает в заголовок. Она не устанавливает маршрут и не создаёт правило политики, отправляющее пакеты с этим источником в определённый туннель.

Остальная часть этого руководства — порядок проверки, которым я пользуюсь, вместе с командой, дающей каждое наблюдение.

Что на самом деле решает привязка

Привязка назначает сокету локальный адрес. Затем ядро выполняет тот же поиск маршрута, который выполнило бы иначе, если только правило политики не изменит, какую таблицу читает этот поиск.

Поэтому пакет может уйти с адресом источника VPN через физический интерфейс. На той стороне он приходит из приватного диапазона, которого сеть никогда не ждала на этом пути, у обратного трафика нет маршрута назад, и соединение зависает или сбрасывается.

Справочник по сокетам IP в Linux описывает семантику привязки. Половина про маршрутизацию живёт в ip-rule и ip-route, и это отдельные руководства не случайно.

Убедитесь, что адрес принадлежит этому пространству имён

Адрес, к которому можно привязаться, должен существовать на интерфейсе внутри сетевого пространства имён, в котором работает приложение. Адрес партнёра, адрес шлюза или адрес, существующий только в другом пространстве имён, привязать нельзя, и вызов завершается ошибкой EADDRNOTAVAIL.

ip -br addr show
ip netns identify <pid>
ss -tanp | grep <port>

Выполните эти три команды в том же контексте, что и приложение: то же пространство имён и, если получится, тот же пользователь. Старая схема net30 не доказывает, какой адрес текущая топология назначила клиенту. Читайте интерфейс, который действительно поднят.

Прочитайте поиск для этого источника и назначения

Одна команда отвечает на вопрос, на который привязка не ответила:

ip route get 203.0.113.10 from 10.8.0.2
ip rule show

Первая строка показывает маршрут, по которому пойдёт пакет от этого источника к этому назначению, включая исходящий интерфейс и предпочитаемый источник. Если там указан физический интерфейс, привязка и маршрут расходятся, и пакет уйдёт с источником, к которому путь не может вернуться.

Затем ip rule show подскажет, выбрало ли какое-нибудь правило другую таблицу. Приоритеты здесь важны, потому что побеждает первое совпавшее правило, а правило, перехватывающее всё выше вашего, делает ваше правило невидимым.

Устанавливайте правило политики, только если так задумано

Маршрутизация по источнику — осознанное решение, а не починка для одного приложения. Если владелец политики хочет, чтобы трафик из подсети туннеля использовал туннель, правило принадлежит его конфигурации, а не разовой команде на вашем ноутбуке.

Рабочая форма — отдельная таблица с маршрутом по умолчанию через туннель плюс правило, отправляющее диапазон источников VPN в эту таблицу. Добавьте исключения, которые нужны замыслу, потому что таблица только с туннельным маршрутом по умолчанию перехватит назначения, которые должны оставаться локальными или достигаться по физическому пути.

ip route add default dev tun0 table 100
ip rule add from 10.8.0.2 table 100 priority 100
ip route get 203.0.113.10 from 10.8.0.2

Откатите через ip rule del и ip route flush table 100. Всё добавленное так исчезает при перезагрузке, если его не запишет менеджер; это одновременно свойство безопасности и причина не хранить единственную копию в истории своей оболочки.

Проверьте тремя наблюдениями

Запишите источник, который запросило приложение, маршрут, который выбрал поиск, и источник, который сервер действительно увидел.

Эти три могут расходиться, и каждое расхождение указывает в другое место. Захват на интерфейсе туннеля доказывает, что пакет ушёл с правильным источником. Захват на физическом интерфейсе доказывает, что он ушёл не тем путём. Только вид со стороны сервера доказывает путь от начала до конца.

Если приложение предлагает привязку к устройству или режим маршрутизации для каждого приложения, рассматривайте это как другой механизм с другими ограничениями. Похожие на вид настройки не все приводят к одному и тому же решению ядра.

Похожие статьи