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

Пункт назначения — это адрес сети, маска описывает префикс

networksetup -setadditionalroutes принимает тройки из пункта назначения, маски подсети и шлюза. Вызов, который отправляет одну внутреннюю подсеть через туннель, выглядит так:

sudo networksetup -setadditionalroutes "VPN (L2TP)" 192.168.1.0 255.255.255.0 10.2.0.0

Обратите внимание, что такое пункт назначения: адрес сети, а не адрес сервера, к которому вы пытаетесь попасть. В случае, породившем эту статью, идентичная команда с 192.168.1.20 на этом месте не сделала ничего полезного, а замена его на 192.168.1.0 сработала сразу. Та же маска, тот же шлюз, одно отличающееся число. Это и есть вся ошибка в миниатюре.

Причина — арифметика, а не политика. Адрес хоста в паре с маской /24 не описывает 192.168.1.0/24; он описывает нечто, что таблица маршрутизации не может полезно удержать, поэтому запись отклоняется или игнорируется, и туннель в итоге несёт меньше, чем вы планировали.

Когда вам нужен ровно один хост, используйте адрес хоста с маской 255.255.255.255. Ошибка именно в смешанных парах, а не в использовании адреса хоста как такового. /32, построенный из одного адреса, — законный маршрут; /24, построенный из одного адреса, — ошибка.

Вызов заменяет список, а имя — буквальное

Два поведения удивляют людей при первой попытке. Команда задаёт полный список дополнительных маршрутов, а не добавляет к нему, поэтому вызов, добавляющий один префикс, молча удаляет остальные, которые были там раньше. Соберите весь набор одним вызовом.

Имя службы тоже не та метка, которую вы придумали. Прочитайте его из инструмента и скопируйте точно, включая суффикс типа:

networksetup -listallnetworkservices

Имя, отличающееся на один символ, не даёт ни ошибки, которую стоит читать, ни маршрута. Копирование и вставка — правильная техника здесь, а не перенабор по памяти.

Когда профиль претендует на маршрут по умолчанию

Разделённые маршруты проигрывают маршруту по умолчанию для любого пункта назначения, который они явно не покрывают, а профиль L2TP, настроенный на полный туннель, устанавливает именно это. Если профиль говорит, что всё идёт через туннель, список дополнительных маршрутов меняется очень мало. Ваша запись не ошибочна; она просто не имеет отношения к пунктам назначения, которые он никогда не называет. Управление этим обычно находится в настройке профиля об отправке всего трафика, а не в какой-либо команде маршрута.

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

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

Туннелям PPP нужен хук вместо ключа

Для туннелей на основе PPP defaultroute — это ключ профиля, создающий маршрут по умолчанию; уберите его, и клиент перестанет претендовать на каждый пункт назначения. Затем маршруты добавляются после появления интерфейса, обычно из /etc/ppp/ip-up:

#!/bin/sh
/sbin/route add -net 192.168.1.0 -interface ppp0

Держите скрипт во владении root и исполняемым, и добавьте защиту на имя интерфейса, когда на машине существует больше одного профиля туннеля. Хук, который запускается для каждого соединения PPP и предполагает одно имя устройства, — маленькая ошибка с долгой жизнью.

Проверьте разделение тремя запросами

Снимите таблицу, пока вы подключены, и отметьте, какой интерфейс обслуживает туннель. Затем проверьте конкретный пункт назначения, вместо того чтобы доверять коду возврата команды, которая его создала. Код возврата сообщает, принял ли инструмент аргументы, а не то, идёт ли трафик по нужному вам пути.

Закончите тремя запросами, которые доказывают разделение: один внутренний хост по адресу, одно внутреннее имя через внутренний резолвер и один публичный сайт, который по-прежнему должен использовать локальное соединение. Если публичный сайт теперь тоже идёт через туннель, разделения не было, что бы ни говорил список маршрутов.

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

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