
Приблизительно два года назад я начал разрабатывать свою программу AntiBlock, о которой я писал ранее. Версия, которую я описал тогда, была далека от завершения. Но сейчас уже применятся другая архитектура, появился скрипт для сборки пакета и удобная служба, с конфигурационным файлом. GUI для LuCI.
AntiBlock кратко
С помощью обработки DNS запросов, программа направляет только заблокированные сайты через VPN, а остальные идут без изменений.
Изменения в архитектуре
Чтобы не мучать людей, которые хотели бы только установить приложение, оставлю описание архитектуры под спойлером.
Скрытый текст
Прошлая версия добавляла IP-адреса, полученные из DNS-запросов заблокированных сайтов, в таблицу маршрутизации и удаляла их при истечении актуальности. Но такой подход имел недостаток, что если два сайта висят на одном IP-адресе и только один из них заблокированный, то оба пойдут через VPN. Новая версия лишена такого недостатка.
В коде остался этот подход, но так как он расходует больше памяти, он отключен на уровне службы.
Новая версия использует более интересный подход:
Программа создает TUN устройство и дает ему подсеть например 10.7.0.1/16.
Если программа встречает 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 будет описано далее.
А в DNS-запросе IP-адрес домена заменяется на 10.7.0.2.
Domain
IP
example.com
10.7.0.2
Клиент обращается по адресу 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
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
.

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

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

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 настроек



Так же настройки можно сделать через файл /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'
Так же надо убедиться что служба добавлена в автозапуск и включена:
Картинка статуса службы

Убедиться что DoH работает можно на сайте.
Картинка что должен показать сайт

Важная проверка
Необходимо перейти в закладку DHCP and DNS
Картинка как выглядит закладка DHCP and DNS

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

Forwards
Убедиться что в поле DNS Forwards
, при включенной службе AntiBlock, только listen_IP#listen_port
. Если будут другие поля, то это сломает всю логику работы программы.
Картинка правильного примера поля 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, помогу чем смогу.