Маршрутизатор LAN и клиент VPN: два устройства, две таблицы маршрутов
Следующий переход маршрутизатора доставляет пакеты только клиенту. Добавьте туннельный маршрут клиента, пересылку и обратный путь, а затем проверьте с хоста в LAN.
Два устройства пересылают пакет, и каждое ведёт свою таблицу. Маршрутизатор LAN знает, что удалённый префикс принадлежит клиенту VPN, а клиент VPN знает, как добраться до этого префикса через свой туннель. Настройте только первую таблицу, и пакет прибудет на машину без подходящего маршрута, поэтому снова уйдёт по маршруту по умолчанию. Это вся неисправность, и со стороны LAN она выглядит как петля маршрутизации, потому что почти ею и является.
Нарисуйте два перехода, прежде чем трогать маршрут
Возьмите иллюстративную схему: хосты LAN на 192.168.50.0/24, обычный маршрутизатор на 192.168.50.1, выделенный клиент на 192.168.50.15 и удалённая сеть LAN на 10.60.0.0/24, доступная только через туннель, который держит этот клиент. Ни один из двух частных диапазонов не перекрывается с другим, а у туннеля своя схема адресации.
Оба частных диапазона важны, потому что они определяют, какое устройство может ответить. Удалённая сторона увидит пакет, приходящий с туннельного адреса клиента, и её ответ должен найти путь назад к 192.168.50.0/24. Если настроено только исходящее направление, запрос может работать, пока ответ исчезает.
Шаг 1: направьте маршрутизатор на клиента, а не на туннель
На маршрутизаторе LAN добавьте маршрут к месту назначения, следующим переходом которого будет адрес LAN клиента:
ip route add 10.60.0.0/24 via 192.168.50.15
ip route get 10.60.0.55
Эта запись говорит «доставь его машине, которая умеет строить туннель». Она ничего не говорит о том, как строится туннель, и не заменяет собственный маршрут клиента. На управляемом маршрутизаторе эквивалент живёт на странице статических маршрутов устройства; на маршрутизаторе Linux он относится к конфигурации интерфейса, которому принадлежит LAN, а не к оболочке, которую вы закроете.
Проверьте ответ второй команды. Если она сообщает клиента как gateway, а интерфейс LAN как device, первый переход верен, а оставшаяся работа — на другой машине.
Шаг 2: дайте клиенту собственный маршрут со стороны туннеля
Теперь клиент получает пакет для 10.60.0.0/24 и смотрит в свою таблицу. Если его конфигурация туннеля установила маршрут для этого префикса, пакет продолжает идти зашифрованным. Если нет, пакет соответствует обычному маршруту по умолчанию и возвращается к 192.168.50.1, который снова отправляет его клиенту.
Посмотрите, прежде чем что-то добавлять:
ip route show table all | grep -E "10\.60\.0\.0/24|default"
sysctl net.ipv4.ip_forward
Отсутствие маршрута префикса во всех таблицах — это находка, которую вы ищете. Добавьте его через собственную конфигурацию туннеля, чтобы следующее переподключение установило его снова; ручная команда ip route add исчезает вместе с сеансом и возвращает неисправность в самый неудобный момент. Следующий переход — это интерфейс туннеля или адрес, который VPN назначает как своего партнёра, в зависимости от клиента, и адрес партнёра должен браться из текущего профиля, а не из старой заметки.
Петля, когда она возникает, на практике не бесконечна: TTL уменьшается при каждом проходе, и пакет погибает с сообщением о превышении времени. Поэтому повторный traceroute может указывать на цикл, тогда как клиент, который просто не пересылает, молча отбрасывает тот же пакет.
Шаг 3: разрешите пересылку и выберите обратный путь
Получение и пересылка — разные разрешения. net.ipv4.ip_forward=1 на клиенте разрешает транзит на уровне ядра, но правило брандмауэра всё равно должно разрешить его между интерфейсом LAN и туннелем. Правило, разрешающее доступ к собственной странице управления клиента, не разрешит транзит в удалённую LAN, и эту разницу легко упустить, когда тот же хост локально отвечает на ping.
У удалённой стороны зеркальная проблема. Она должна знать, что 192.168.50.0/24 доступен через этого аутентифицированного клиента. С OpenVPN это обычно означает маршрут для каждого клиента, который проталкивает конфигурация сервера, или файл, специфичный для клиента на сервере, объявляющий LAN за клиентом. Без этого удалённая LAN либо отбрасывает ответ, либо отправляет его на собственный шлюз по умолчанию, то есть в интернет.
Трансляция источника — это альтернатива, когда префикс LAN нельзя анонсировать. Ограниченное правило masquerade на клиенте переписывает источник на адрес туннеля, и ответы тогда возвращаются естественно. Оно также скрывает, какой хост LAN сделал запрос, и само по себе не позволяет удалённой стороне инициировать соединения внутрь. Выберите этот компромисс осознанно, вместо того чтобы добавить всеобъемлющее masquerade и обнаружить побочный эффект позже.
Шаг 4: сделайте оба решения постоянными, затем проверьте реальный путь
У каждого маршрута есть владелец, и владелец — это конфигурация, которая воссоздаётся при загрузке или при переподключении. На маршрутизаторе это может быть запись статического маршрута; на клиенте это может быть профиль VPN, NetworkManager или systemd-networkd. Проверьте, переподключив туннель и перезагрузив клиента, затем прочитайте таблицу снова, а не полагайтесь на правку.
Оставьте нетронутым маршрут по умолчанию, который несёт внешнее соединение туннеля. Его замена ради «упрощения» настройки ломает зашифрованный путь раньше, чем какой-либо внутренний трафик успеет им воспользоваться, а симптом — туннель, который после изменения больше никогда не устанавливается.
Проверяйте с обычного хоста LAN, а не с клиента, потому что запрос, возникший на клиенте, никогда не задействует первый переход маршрутизатора. Получите сервис, который существует только в удалённой LAN, и подтвердите тело ответа, затем посмотрите счётчики или журналы клиента, чтобы увидеть транзит. Внутренний traceroute с частными переходами доказывает пересылку, а не шифрование: внешний путь — отдельное наблюдение, и только собственные счётчики интерфейса туннеля показывают, что через него вышло.