Одно устройство через VPN на роутере требует трёх правил, а не тумблера
Одно устройство через VPN на роутере — это маршрутизация политики, а не галочка: помеченная таблица, ограниченное правило NAT, а также пути DNS, IPv6 и LAN, которые руководства пропускают.
На VPN роутера нет переключателя для каждого устройства; переключатель, который вы ищете, — это ярлык, который пишет правила маршрутизации политики от вашего имени. В тот момент, когда одному ноутбуку, одному диапазону портов, одному списку адресов или одному сегменту LAN нужно использовать туннель, а всё остальное остаётся в WAN, вы строите маршрут политики, а не включаете функцию. В работе три подвижные части, и каждая отказывает по-своему: помеченная таблица без маршрута выглядит как тишина, метка, поставленная не в той цепочке, выглядит так, будто ничего не произошло, а отсутствующее правило NAT выглядит как туннель, который подключается и ничего не несёт. Ещё две части теряются потому, что никогда не появляются в правиле mangle, и это DNS и IPv6.
Миф: туннель — это настройка клиента
VPN-клиент на стороне роутера хорошо делает одну грубую вещь: он кладёт 0.0.0.0/0 в главную таблицу маршрутизации и направляет её в туннель. WireGuard выводит это из AllowedIPs, OpenVPN а из redirect-gateway, который присылает сервер, и оба меняют путь для каждого хоста за роутером. Сужение AllowedIPs или добавление route-nopull меняет то, что устанавливает клиент. Это не меняет того, на кого распространяется установка, потому что клиент никогда не видит устройства. Он видит только пакеты.
Выбор по источнику или назначению — это решение маршрутизации, поэтому он относится к уровню политики роутера: правило mangle плюс вторая таблица на RouterOS, MARK плюс ip rule на OpenWrt или DD-WRT, либо правило межсетевого экрана, шлюзом которого является туннель, на pfSense. Рецепт клиента WireGuard от Netgate — это то, что стоит прочитать, прежде чем гадать, потому что на этой платформе шлюз правила, назначение интерфейса и запись исходящего NAT должны совпасть, прежде чем хоть один клиент начнёт использовать туннель.
Вторая половина мифа — второй роутер. Покупка ещё одной коробки или перенос устройства в гостевой SSID часто работает, и причина не в железе: устройство попадает в собственную подсеть, что даёт селектор источника, который прошивка уже понимает. Если вы можете определить этот сегмент на своём роутере, лишняя коробка решает проблему, которой у вас не было.
Часть первая: туннель, который не является маршрутом по умолчанию
На RouterOS добавьте клиента без маршрута по умолчанию и дайте туннелю собственную таблицу. Первый маршрут — помеченный по умолчанию; второй — половина отказа.
/ip route add dst-address=0.0.0.0/0 gateway=VPN_GATEWAY_IP routing-mark=vpn distance=1
/ip route add dst-address=0.0.0.0/0 type=unreachable routing-mark=vpn distance=2
Недостижимый маршрут — вот почему помеченная таблица побеждает список исключений в главной таблице. Когда туннель падает, помеченные пакеты сразу получают недостижимость вместо тихого возврата в WAN, поэтому сбой появляется в сообщении об ошибке приложения, а не на странице геолокации, которую вы проверяете через час.
RouterOS 7 разделяет то, что 6.x держал вместе: таблицу объявляют через /routing table add name=vpn fib, а затем ссылаются на неё по имени в маршруте и в правиле mangle. Фрагмент для 6.x, который пишет routing-mark без определения таблицы, загружается чисто и ничему не соответствует. Другая классика — две половины 0.0.0.0/1 или два маршрута по умолчанию на одинаковом расстоянии в одной таблице: ядро выбирает один, и поведение может измениться после перезагрузки.
Часть вторая: пометьте до поиска маршрута
Селектор решает, какие пакеты попадут в эту таблицу. RouterOS обычно начинает со списка адресов для политики назначения или с адреса источника для политики устройства:
/ip firewall mangle add chain=prerouting src-address=192.168.88.50 action=mark-routing new-routing-mark=vpn
/ip firewall mangle add chain=prerouting dst-address-list=via-vpn action=mark-routing new-routing-mark=vpn
/ip firewall address-list add list=via-vpn address=203.0.113.10
Прошивка Linux делает то же самое с меткой netfilter и правилом, которое направляет помеченные пакеты в таблицу, которую вы заполнили:
iptables -t mangle -A PREROUTING -p tcp --dport 27000:27050 -j MARK --set-mark 0x200
ip route add default dev tun0 table 100
ip rule add fwmark 0x200 table 100
Цепочка — не выбор стиля. К моменту, когда пакет достигает FORWARD, поиск маршрута уже произошёл, поэтому MARK или DROP там может только переписать или отбросить. Метка должна попасть в PREROUTING для пересылаемого трафика и в OUTPUT для трафика, который создаёт сам роутер, где живут DNS, NTP и проверки обновлений роутера. Именно этот путь вывода — обычная причина, по которой полностью туннелированная конфигурация в тесте на утечку всё ещё отвечает от резолвера провайдера.
Политике устройства нужно соответствие, которое не дрейфует. Зарезервируйте адрес в DHCP или сопоставьте интерфейс для выделенного сегмента; адрес, который позже переедет на другое устройство, тихо применит туннель к неверному клиенту. Мост на каждый SSID с собственной подсетью — более долговечная версия той же идеи, и он даёт правилам IPv6 место для жизни.
Часть третья: NAT, DNS и исключение для LAN
Трафику, уходящему через туннель, нужен адрес источника, на который ответит другая сторона. Ограничьте трансляцию интерфейсом туннеля: out-interface=VPN_NAME на RouterOS, -o tun0 в Linux, соответствующая запись исходящего NAT на pfSense. Правило masquerade без этого ограничения переписывает трафик, который вы хотели оставить в покое, и симптом в том, что устройство вне туннеля теряет свой публичный адрес.
Исключение для LAN вызывает больше тем поддержки, чем сам туннель. Если помеченная таблица держит только маршрут по умолчанию, адрес принтера или NAS с выбранного устройства совпадёт с этим умолчанием и исчезнет в туннеле. Добавьте маршрут LAN в ту же таблицу или исключите локальную подсеть в селекторе; работают оба варианта, и исключение проще держать корректным, когда вы позже добавляете VLAN.
DNS идёт отдельным путём. Запросы, которые роутер пересылает, порождаются роутером и следуют OUTPUT, а не пересылаемой метке, поэтому полностью туннелированный ноутбук всё ещё может разрешать имена через провайдера. Направьте клиентов на резолвер, доступный через туннель, или пометьте собственный трафик port-53 роутера, а затем проверьте разрешённый адрес, вместо того чтобы считать, что ответ путешествовал вместе с веб-запросом.
Когда правило совпадает, но приложение всё ещё использует WAN
Списки назначений быстро устаревают. Имя разрешается в адрес, которого нет в списке, поэтому запрос уходит в WAN, хотя каждый тест по указанному в списке адресу работал. Обновляйте список из того же резолвера, которым пользуется клиент, и предпочитайте селектор по источнику, когда вам действительно нужен весь трафик с одного устройства.
IPv6 — это тихий обход. У устройства есть второе семейство адресов со своим маршрутом по умолчанию и своим набором правил, и совпадение только по адресу IPv4 — это половина политики. Примените тот же селектор к ip6tables или эквиваленту nftables либо намеренно отключите IPv6 в этом сегменте, а не случайно.
Установленные соединения тоже важны. Запись conntrack, созданная до изменения, продолжает идти старым путём, пока не истечёт, поэтому браузер, оставленный открытым во время правки, выглядит точно как правило, которое так и не применилось. Откройте новое соединение или очистите состояние, прежде чем судить о политике.
Проверьте двумя устройствами и перезагрузкой
Проверьте устройство, которое должно быть в туннеле, и то, которое не должно, и сравните второй хоп, а не число скорости. Traceroute с каждого показывает либо шлюз туннеля, либо шлюз провайдера на втором хопе; если оба выглядят одинаково, метка или таблица делают не то, что говорит правило. Для теста используйте новые соединения.
Затем перезагрузите. Порядок запуска — это место, где работающая политика ломается, потому что клиент должен быть поднят до установки недостижимого маршрута, а сохранённый снимок, восстанавливающий старый набор правил, перезапишет вашу таблицу. Проверьте, что каждое правило есть в сохранённой конфигурации и что помеченный маршрут по умолчанию существует после загрузки, а не только после того, как вы его набрали.
Если что-то не работает, сначала снимите метку и посмотрите, вернётся ли обычный трафик, затем снимите таблицу. Этот порядок скажет вам, гоняетесь ли вы за проблемой маршрутизации или за проблемой межсетевого экрана, и оставляет домашним работающий принтер, пока вы заканчиваете работу.