Дано: роутер с OpenWrt и ряд доменов, трафик к которым (включая поддомены) надо заворачивать через отдельный интерфейс. При этом IP-адреса, соответствующие доменам, периодически меняются, что не должно ломать конфигурацию.
Решение:
В dnsmasq есть фича, позволяющая при ресолвинге доменов добавлять полученные адреса в определённый ipset. Далее маршруты до этих адресов можно завернуть на нужный интерфейс разными способами, я воспользовался mwan3 (просто потому что он был у меня уже установлен и настроен, хотя это не самая простая вещь).
Необходимый софт: dnsmasq-full (в устанавливаемой по умолчанию сборке dnsmasq поддержка ipset отключена), ipset, mwan3, обвязка для них в uci/luci, ну и то, что нужно для поднятия интерфейса, в который, собственно, и заворачивается трафик (wireguard в моём случае). Чтобы не париться установкой пакетов, я сразу собрал образ, в котором это всё есть, с помощью ImageBuilder. Команда сборки такая: make image PROFILE=netgear_wndr3800 PACKAGES='dnsmasq-full ipset kmod-wireguard luci luci-app-mwan3 luci-app-upnp luci-app-wireguard luci-i18n-base-ru luci-i18n-firewall-ru luci-i18n-mwan3-ru luci-i18n-wireguard-ru mwan3 stubby wireguard-tools luci-i18n-opkg-ru -dnsmasq' (здесь netgear_wndr3800 — модель моего роутера, надо заменить на свою; stubby добавлен для решения другой задачи, но не то чтобы совсем не связанной с данной). Тем, кто не пользуется mwan3, рекомендую заменить его на vpn-policy-routing (в комплекте с luci-app-vpn-policy-routing и luci-i18n-vpn-policy-routing-ru): он не такой навороченный, с ним легче разобраться.
Далее по шагам.
- Настройка интерфейса. Описание опущу, здесь у каждого своё. Из важного далее упомяну только, что в моём случае интерфейс называется wg0.
- Создание маршрута по умолчанию через этот интерфейс. Поскольку надо, чтобы трафик по умолчанию всё же шёл через интерфейс WAN, а через wg0 — только когда мы явно его туда направим, этот маршрут должен иметь бо́льшую метрику, чем уже существующий шлюз по умолчанию через сеть провайдера.
В зависимости от того, как создаётся интерфейс, настройка отличается. В случае wireguard в настройках самого интерфейса возможности задать его в качестве шлюза по умолчанию нет, поэтому надо прописать его как статический маршрут. В моём случае настройка в /etc/config/network выглядит так:Здесь сеть назначения 0.0.0.0/0 означает, что это шлюз по умолчанию, 192.0.2.1 — адрес удалённого сервера, выполняющего роль шлюза, в виртуальной сети, а метрика 50 больше метрики для провайдерского шлюза по умолчанию (10). Маршрут можно создать через веб-интерфейс.Код: Выделить всё
config route option interface 'wg0' option target '0.0.0.0/0' option gateway '192.0.2.1' option metric '50'
- Создание пустого ipset. В OpenWrt до версии 21.02 включительно с firewall3 ему соответствует такая секция в /etc/config/firewall:
Имя вместо 'tunnel' можно задать любое, остальные опции должны быть точно такими, как у меня.
Код: Выделить всё
config ipset option name 'tunnel' option match 'src_ip' option storage 'hash' option enabled '1'
Вот тут веб-интерфейсом не обойтись. После правки конфига надо сделать fw3 reload. Проверить, что ipset создался, можно командой ipset list tunnel. - Настройка dnsmasq. Тоже не вынесена в веб-интерфейс. В /etc/config/dhcp добавляется примерно такая секция:
Здесь вместо 'filter' можно использовать любое имя. Число доменов может быть любое. Для применения настроек надо сделать /etc/init.d/dnsmasq restart. Если в дальнейшем потребуется добавить домены в список, после этого также потребуется выполнение /etc/init.d/dnsmasq restart.
Код: Выделить всё
config ipset 'filter' list name 'tunnel' list domain 'example.net' list domain 'example.org'
- Настройка vpn-policy-routing (проще) или mwan3 (сложнее). Тут уже можно воспользоваться веб-интерфейсом, чтобы направить адреса из ipset под названием tunnel через нужный интерфейс (wg0).