Приблизительно два года назад я начал разрабатывать свою программу AntiBlock, о которой я писал ранее. Версия, которую я описал тогда, была далека от завершения. Но сейчас уже применятся другая архитектура, появился скрипт для сборки пакета и удобная служба, с конфигурационным файлом. GUI для LuCI.

AntiBlock кратко

С помощью обработки DNS запросов, программа направляет только заблокированные сайты через VPN, а остальные идут без изменений.

Изменения в архитектуре

Чтобы не мучать людей, которые хотели бы только установить приложение, оставлю описание архитектуры под спойлером.

Скрытый текст

Прошлая версия добавляла IP-адреса, полученные из DNS-запросов заблокированных сайтов, в таблицу маршрутизации и удаляла их при истечении актуальности. Но такой подход имел недостаток, что если два сайта висят на одном IP-адресе и только один из них заблокированный, то оба пойдут через VPN. Новая версия лишена такого недостатка.

В коде остался этот подход, но так как он расходует больше памяти, он отключен на уровне службы.

Новая версия использует более интересный подход:

  1. Программа создает TUN устройство и дает ему подсеть например 10.7.0.1/16.

  2. Если программа встречает DNS-запрос с заблокированным доменом:

    Domain

    IP

    example.com

    93.184.215.14

    , то она добавляет в хеш-таблицу запись:

    Key

    Value

    10.7.0.2

    93.184.215.14

    10.7.0.2 - свободный IP-адрес из подсети 10.7.0.1/17, почему из подсети 10.7.0.1/17, а не 10.7.0.1/16 будет описано далее.

  3. А в DNS-запросе IP-адрес домена заменяется на 10.7.0.2.

    Domain

    IP

    example.com

    10.7.0.2

  4. Клиент обращается по адресу 10.7.0.2. TUN устройство принимает пакет:

    Source IP

    Destination IP

    192.168.1.10:25090

    10.7.0.2:443

    Из хеш-таблицы получаем значение по ключу Destination IP:

    Key

    Value

    10.7.0.2

    93.184.215.14

  5. TUN устройство выполняет роль NAT. У подсети 10.7.0.1/16 две 17 подсети 10.7.0.1/17 и 10.7.128.1/17. Для дальнейшей обработки Destination IP 10.7.0.2 переводим из 10.7.0.1/17 в 10.7.128.1/17, просто инверсией нужного бита и получаем 10.7.128.2. Зачем это нужно будет объяснено далее. Заменяем поля у пакета:

    Source IP

    Destination IP

    10.7.128.2:25091

    93.184.215.14:443

    Source port 25090 поменялся на 25091, потому что Source port 25090 был занят, и мы нашли первый свободный порт. Запоминаем в другую хеш-таблицу:

    Key

    Value

    10.7.128.2:25091

    93.184.215.14:443

    192.168.1.10:25090

    Другая хеш-таблица необходима, чтобы произвести обратные преобразования, когда пакет пойдет до клиента.

Подсети 10.7.0.1/17 и 10.7.128.1/17 используются, чтобы отличать пакеты, которые должны направиться в VPN(клиент->TUN->VPN) от пакетов, которые должны направиться прямо к клиенту(VPN->TUN->клиент). Так как маршрутизация на VPN происходит по Source IP Route Rules, то если всегда использовалась бы подсеть 10.7.0.1/16 любой пакет, исходящий из TUN, направлялся бы на VPN и не попадал бы на обратном пути к клиенту.

ip rule add from 10.7.128.1/17 table 200
Схема новой архитектуры

Установка из репозитория

В OpenWrt 24.10 и программу и веб интерфейс включили в репозиторий.

Их можно установить через:

opkg update
opkg install antiblock
opkg install luci-app-antiblock

Сборка для OpenWrt

Для сборки пакета на OpenWrt был написал скрипт:

https://github.com/karen07/openwrt-package-autobuild.git

Скачиваем репозиторий:

git clone https://github.com/karen07/openwrt-package-autobuild.git

Запускаем скрипт:

./auto_install.sh antiblock ROUTER_NAME

Если вы хотите установить GUI для LuCI надо запустить:

./auto_install.sh luci-app-antiblock ROUTER_NAME

где ROUTER_NAME название роутера из ssh config или например root@192.168.1.1

При запуске на Ubuntu или Arch скрипт сам поставит необходимые зависимости.

А так же сам сходит на роутер узнает его архитектуру, скачает нужный SDK, соберет и установит пакет AntiBlock на роутер.

Настройка службы

Конфигурационный файл лежит по пути /etc/config/antiblock , по умолчанию файл пустой. Настроить все эти поля можно будет через GUI для LuCI.

config antiblock 'config'
        option enabled '1'
        option url 'https://antifilter.download/list/domains.lst'
        option file '/root/my_urls.txt'
        option DNS '127.0.0.1:5060'
        option listen '127.0.0.1:5053'
        option VPN_name 'VPN'
        option output '/tmp/antiblock/'
        option log '1'
        option stat '1'

Обязательно хотя бы один параметр:

  • url - url файла, в котором лежат заблокированные домены, выкачивается заново каждые 24 часа, домены идут построчно, последний домен тоже оканчивается новой строкой

  • file - путь до файла, в котором лежат заблокированные домены, подходит для ручной настройки списка заблокированных доменов, домены идут построчно, последний домен тоже оканчивается новой строкой

Обязательные параметры:

  • DNS - IP-адрес и порт DNS сервера, на который будут отправляться запросы

  • listen - IP-адрес и порт, на котором AntiBlock будет слушать входящие запросы

  • VPN_name - название интерфейса, на который будут маршрутизироваться запросы на заблокированные домены, не обязательно название VPN интерфейса, может быть любой интерфейс

Не обязательные параметры:

  • output - папка, в которую будут сохраняться лог и статистика

  • log - включить полное логирование запросов в файл log.txt, помогает когда надо выявить домен, который потом можно включить в файл с заблокированными доменами

  • stat - включить вывод статистики работы программы в файл stat.txt, интересно отслеживать сколько всего было запросов DNS

Проверить запустилась служба или нет, можно командой:

logread | grep antiblock

Пример удачного запуска:

Antiblock started 2.0.0
Get urls from url https://antifilter.download/list/domains.lst
Get urls from file /root/my_urls.txt
DNS 127.0.0.1:5060
Listen 127.0.0.1:5053
Gateway IP 10.8.0.5

Thread client data started
Thread DNS data started

Readed domains from file 7 from url 669479

Для добавление службы в автозапуск:

service antiblock enable

Для применения новых настроек из конфигурационного файла:

service antiblock restart

Например для ютуба необходимы записи в файл дополнительных URL:

ytimg.com
youtube.com
googlevideo.com
youtubei.googleapis.com

А так же если не использовать DoH, который будет описан в следующей главе. Необходимо поменять параметры:

option DNS '127.0.0.1:5060'
option listen '127.0.0.1:5053'

Например на :

option DNS '1.1.1.1:53'
option listen '192.168.1.1:5053'

Настройка через LuCI

Настойки находятся в Services далее в закладке AntiBlock.

Закладка WebGUI настроек

В первой вкладе можно выставить аргументы.

Настройки AntiBlock

Во второй вкладе можно добавить пользовательские URLs, если настроен аргумент "File".

Настройки URLs

DoH - DNS over HTTPS

Чтобы совсем не переживать за DNS, я использую вместе со своей программой:

https-dns-proxy

Название пакета для установки:

luci-app-https-dns-proxy

Это DNS proxy, принимающий DNS UDP запросы и переводящий их в HTTPS. Получается такой конвейер, Dnsmasq отправляет UDP DNS в AntiBlock, AntiBlock отправляет UDP DNS в https-dns-proxy, https-dns-proxy отправляет HTTPS DNS например в CloudFlare.

Для корректной работы вместе с моей программой необходимо выставить такие настройки. Найти настройки можно в закладке Services далее в закладке HTTPS DNS Proxy.

Картинки WebGUI настроек
Закладка WebGUI настроек
WebGUI настройки https-dns-proxy
WebGUI настройки https-dns-proxy

Так же настройки можно сделать через файл /etc/config/https-dns-proxy:

config main 'config'
	option dnsmasq_config_update '-'
	option force_dns '0'
	list force_dns_port '53'
	list force_dns_port '853'
	option procd_trigger_wan6 '0'

config https-dns-proxy
	option resolver_url 'https://cloudflare-dns.com/dns-query'
	option listen_addr '127.0.0.1'
	option listen_port '5060'

Так же надо убедиться что служба добавлена в автозапуск и включена:

Картинка статуса службы
WebGUI настройки https-dns-proxy

Убедиться что DoH работает можно на сайте.

Картинка что должен показать сайт
Лог проверки DoH

Важная проверка

Необходимо перейти в закладку DHCP and DNS

Картинка как выглядит закладка DHCP and DNS
Закладка DHCP and DNS

Перейти в Закладка Forwards

Картинка как выглядит закладка Forwards
Закладка Forwards

Убедиться что в поле DNS Forwards, при включенной службе AntiBlock, только listen_IP#listen_port. Если будут другие поля, то это сломает всю логику работы программы.

Картинка правильного примера поля DNS Forwards
Поле DNS Forwards

Дисклеймер

Разработка еще не окончена, AntiBlock тестировался на роутерах с ARM и MIPS, но все равно сохраняется вероятность неожиданного поведения на других устройствах. AntiBlock потребляет примерно 22 мегабайта ОЗУ. Так много, потому что уже 673508 заблокированных доменов, и они весят 12 мегабайт, хеш таблица поверх них весит еще 5 мегабайт. IPv6 тоже не работает, поэтому чтобы корректно работало, надо чтобы DNS запросы были только для IPv4 адресов. Я решил эту проблему так:

service odhcpd disable
service odhcpd stop
uci delete dhcp.odhcpd
uci delete network.wan6

Из за особенностей менеджера служб OpenWrt, при падение исполняемого файла AntiBlock, служба не перезапускается, и наступает DNS блэкаут. Если резко пропал интернет, но например Telegram работает, значит может быть упала программа. Такое очень мало вероятно, но "Предупреждён — значит вооружён". Проверить это можно через:

ps | grep antiblock

Если что то не взлетит, обращайтесь в комментарии или в GitHub Issues, помогу чем смогу.