Выборочный роутинг по доменным именам на маршрутизаторах Keenetic
Эта статья предназначена для тех, кто хочет настроить выборочный роутинг на основе доменных имен на своих маршрутизаторах Keenetic. Основная цель — обойти блокировки по конкретным доменным именам, без необходимости добавлять сотни маршрутов в таблицу маршрутизации вручную. Такой подход значительно упрощает процесс и позволяет гибко управлять трафиком через VPN-туннели.
Эта инструкция собрана из различных источников и протестирована на версии KeeneticOS 4.3 beta — всё работает стабильно. Процесс на других версиях KeeneticOS 4.x будет идентичным.
Предварительные условия
Роутер Keenetic с подключённым внешним сервером WireGuard (WG) или Amnezia. Используются стандартные средства Keenetic для подключения туннеля.
Важно: статья касается перенаправления трафика в зависимости от домена, а не настройки VPN.
На туннеле должен быть установлен чекбокс «использовать для выхода в интернет».
Установленные компоненты операционной системы: Протокол IPv6, Модули ядра подсистемы Netfilter.
Установите Entware по этой инструкции.
Получите доступ к SSH с установленным Entware. После этого выполните следующие команды:
opkg update
opkg install mc dnsmasq-full ipset iptables
Настройка DNS-сервера
Откройте файл
/opt/etc/dnsmasq.conf
и добавьте строку:
conf-file=/opt/etc/unblock.dnsmasq
Весь конфиг для dnsmasq будет храниться в файле /opt/etc/unblock.dnsmasq
Создайте файл
/opt/etc/unblock.dnsmasq
и добавьте в него следующую конфигурацию (где@nwg0
— ваш VPN-интерфейс, узнать его можно через командуip a
):
port=5354
server=1.1.1.1@nwg0
user=root
group=root
ipset=/youtube.com/bypass
ipset=/googlevideo.com/bypass
ipset=/cdninstagram.com/bypass
ipset=/instagram.com/bypass
ipset=/threads.net/bypass
ipset=/threadsapp.net/bypass
ipset=/ig.me/bypass
ipset=/chatgpt.com/bypass
ipset=/openai.com/bypass
ipset=/linkedin.com/bypass
ipset=/medium.com/bypass
ipset=/rutracker.org/bypass
ipset=/youtu.be/bypass
ipset=/nhacmp3youtube.com/bypass
ipset=/youtubei.googleapis.com/bypass
ipset=/yt3.ggpht.com/bypass
ipset=/ytimg.com/bypass
Перезапустите сервер
dnsmasq:
/opt/etc/init.d/S56dnsmasq restart
Отключите автоматическое получение DNS-серверов в настройках интерфейса провайдера.
В настройках DNS роутера укажите сервер с портом 5354 (например,
192.168.2.1:5354
). У меня это 192.168.2.1:5354, у вас адрес может отличаться.Примечание: localhost и 127.0.0.1 Keenetic не позволяет указать.
PS: Я у себя оставил DoH сервера Яндекса и дополнительно прописал только домены из списка выше. Это решение на ваше усмотрение, но в случае падения туннеля я не хочу остаться без интернета. По этой же причине я не хотел делегировать роль DNS-сервера целиком сервису dnsmasq.
Подготовка политик доступа
Далее будем использовать возможности интерфейса Keenetic для настройки политик доступа.
Переходим в раздел «Приоритеты подключений». Нам нужно создать две новые политики доступа:
Политика «TO_VPN» будет использоваться для устройств, которые должны выходить в интернет только через VPN. Оставляем галочку только у VPN соединения.
Политика «Internet» будет использоваться для всех остальных устройств. Вы должны перенести все устройства из »политики по умолчанию». Эти устройства будут подключаться к интернету через основного провайдера, но для доменов, указанных в конфигурации dnsmasq, трафик будет перенаправляться через VPN (политика «TO_VPN»).
Маркирование трафика
Keenetic маркирует трафик в зависимости от группы устройств. Нам нужно выяснить, какие маркеры присваиваются для политик «TO_VPN» и «Internet».
Добавьте устройства в нужные группы (узнайте их IP-адреса) и выполните команду:
iptables-save | grep MARK
Например, для политики Internet можно увидеть строку:
-j MARK --set-xmark 0xffffaaa/0xffffffff
А для TO_VPN:
-j MARK --set-xmark 0xffffaab/0xffffffff
Запомните свои маркеры. У вас они будут отличаться.
Скрипт iptables
Теперь создаём скрипт для маршрутизации трафика:
Создайте файл
/opt/root/iptables.sh
и сделайте его исполняемым:
chmod +x /opt/root/iptables.sh
Внутри файла укажите следующие строки:
[ -n "$(iptables-save | grep TO_VPN)" ] && exit 0
ipset create bypass hash:net -exist
iptables -t mangle -N TO_VPN
iptables -t mangle -A TO_VPN -j MARK --set-mark 0xffffaab
iptables -t mangle -A TO_VPN -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff
iptables -t mangle -A PREROUTING -p all -m mark --mark 0xffffaaa -m set --match-set bypass dst -j TO_VPN
iptables -t mangle -A OUTPUT -p udp -d 1.1.1.1 --dport 53 -j TO_VPN
Где:
-p all
— любой протокол,-m mark --mark 0xffffaaa
— инициатор пакета из группы «Internet»,-m set --match-set bypass dst
— IP адрес назначения соответствует списку IP-адресов bypass (этот ipset обновляется нашим DNS-сервером на лету).
Скрипт также ловит DNS-запросы из OUTPUT (локально сгенерированные запросы от dnsmasq). Транзитные DNS-запросы, например, если клиент использует сервер 8.8.8.8, пойдут без VPN.
Теперь вы можете запустить этот скрипт вручную для проверки. Если всё работает корректно, его можно добавить в автозагрузку:
Добавление в автозагрузку
Для добавления скрипта в автозагрузку создаём файл /opt/etc/ndm/netfilter.d/iptables_reload.sh
и делаем его исполняемым:
chmod +x /opt/etc/ndm/netfilter.d/iptables_reload.sh
Содержимое файла:
#!/bin/sh
[ "$type" == "ip6tables" ] && exit 0 # проверяем протокол
[ "$table" == "mangle" ] || exit 0 # проверяем таблицу
logger "iptables $table reloaded: load /opt/root/iptables.sh"
/opt/root/iptables.sh
Таким образом, скрипт будет вызываться роутером при каждой перезагрузке таблицы mangle или nat.
Теперь всё готово! Вы можете протестировать настройки и убедиться, что выборочный роутинг через VPN работает корректно.