Выборочный роутинг по доменным именам на маршрутизаторах Keenetic

Эта статья предназначена для тех, кто хочет настроить выборочный роутинг на основе доменных имен на своих маршрутизаторах Keenetic. Основная цель — обойти блокировки по конкретным доменным именам, без необходимости добавлять сотни маршрутов в таблицу маршрутизации вручную. Такой подход значительно упрощает процесс и позволяет гибко управлять трафиком через VPN-туннели.

Эта инструкция собрана из различных источников и протестирована на версии KeeneticOS 4.3 beta — всё работает стабильно. Процесс на других версиях KeeneticOS 4.x будет идентичным.

Предварительные условия

  1. Роутер Keenetic с подключённым внешним сервером WireGuard (WG) или Amnezia. Используются стандартные средства Keenetic для подключения туннеля.

    Важно: статья касается перенаправления трафика в зависимости от домена, а не настройки VPN.

  2. На туннеле должен быть установлен чекбокс «использовать для выхода в интернет».

  3. Установленные компоненты операционной системы: Протокол IPv6, Модули ядра подсистемы Netfilter.

  4. Установите Entware по этой инструкции.

  5. Получите доступ к SSH с установленным Entware. После этого выполните следующие команды:

opkg update
opkg install mc dnsmasq-full ipset iptables

Настройка DNS-сервера

  1. Откройте файл /opt/etc/dnsmasq.conf и добавьте строку:

conf-file=/opt/etc/unblock.dnsmasq

Весь конфиг для dnsmasq будет храниться в файле /opt/etc/unblock.dnsmasq

  1. Создайте файл /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
  1. Перезапустите сервер dnsmasq:

/opt/etc/init.d/S56dnsmasq restart
  1. Отключите автоматическое получение DNS-серверов в настройках интерфейса провайдера.

  2. В настройках DNS роутера укажите сервер с портом 5354 (например, 192.168.2.1:5354). У меня это 192.168.2.1:5354, у вас адрес может отличаться.

    Примечание: localhost и 127.0.0.1 Keenetic не позволяет указать.

    PS: Я у себя оставил DoH сервера Яндекса и дополнительно прописал только домены из списка выше. Это решение на ваше усмотрение, но в случае падения туннеля я не хочу остаться без интернета. По этой же причине я не хотел делегировать роль DNS-сервера целиком сервису dnsmasq.

Подготовка политик доступа

Далее будем использовать возможности интерфейса Keenetic для настройки политик доступа.

  1. Переходим в раздел «Приоритеты подключений». Нам нужно создать две новые политики доступа:

    • Политика «TO_VPN» будет использоваться для устройств, которые должны выходить в интернет только через VPN. Оставляем галочку только у VPN соединения.

    • Политика «Internet» будет использоваться для всех остальных устройств. Вы должны перенести все устройства из »политики по умолчанию». Эти устройства будут подключаться к интернету через основного провайдера, но для доменов, указанных в конфигурации dnsmasq, трафик будет перенаправляться через VPN (политика «TO_VPN»).

1331f8916eaa5884a90505d663e214c0.jpg049e1780d7ab959e41fab92ec60a50fa.jpg

Маркирование трафика

Keenetic маркирует трафик в зависимости от группы устройств. Нам нужно выяснить, какие маркеры присваиваются для политик «TO_VPN» и «Internet».

  1. Добавьте устройства в нужные группы (узнайте их IP-адреса) и выполните команду:

iptables-save | grep MARK

Например, для политики Internet можно увидеть строку:

-j MARK --set-xmark 0xffffaaa/0xffffffff

А для TO_VPN:

-j MARK --set-xmark 0xffffaab/0xffffffff

Запомните свои маркеры. У вас они будут отличаться.

Скрипт iptables

Теперь создаём скрипт для маршрутизации трафика:

  1. Создайте файл /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.

  1. Теперь вы можете запустить этот скрипт вручную для проверки. Если всё работает корректно, его можно добавить в автозагрузку:

Добавление в автозагрузку

Для добавления скрипта в автозагрузку создаём файл /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 работает корректно.

© Habrahabr.ru