Привет, Хабр!
Сегодня рассмотрим вариант установки утилиты модификации сетевых пакетов Zapret на роутеры Keenetic. В отличии от простого использования на конкретных устройствах, при установке на роутер появляется возможность обрабатывать трафик идущий от всех устройств, подключенных к домашней локальной сети (ПК, смартфоны и смарт телевизоры).
Указанная утилита предлагает два основных режима работы – это TPWS или NFQWS. При использовании в режиме TPWS есть недостатки, заключающиеся в том, что в этом режиме не модифицируется протокол QUIC (HTTP/3), а также приложение YouTube на смарт телевизорах с WebOS или Android TV перестает вообще запускаться.
Информация по протоколам YouTube и возникающим проблемам при использовании
Для начала попробуем определиться с тем, какие протоколы используются YouTube на различных устройствах:
В браузерах на ПК может использоваться как новый протокол QUIC (трафик идет по протоколу UDP на порт 443), так и классический HTTPS (трафик идет по протоколу TCP на порт 443).
В приложении YouTube на Android, напротив, уже изначально используется протокол QUIC. Выяснилось это сразу после запуска TPWS – в браузерах на ПК все работало без проблем, а вот на Android устройствах, как без использования данной утилиты;
С приложением YouTube на WebOS еще куда запутаннее: там загрузка интерфейса идет по протоколу HTTPS (TCP порт 443), а видео протоколу QUIC (UDP порт 443). Но в случае, если подключение по QUIC не доступно, тогда приложения, что на Android устройствах, что WebOS переходят на протокол HTTPS. Так чтобы на телевизоре и телефоне YouTube не тормозил при работе с TPWS, необходимо блокировать трафик UDP на порт 443, для того, чтобы заставить приложения подключатся по протоколу HTTPS. Но это не решит проблему с поломкой загрузки интерфейса приложения на WebOS (Android TV) при работе с TPWS.
В качестве вариантов решения данной проблемы при использовании утилиты в режиме TPWS, я вижу три возможных варианта:
Подбирать параметры запуска TPWS (но их там не так много), чтобы они не ломали загрузку приложения YouTube, а все остальное работало, как должно. Мне этого так и не удалось добиться.
Вычислить доменные адреса, по которым приложение YouTube загружает интерфейс и включить их в exclude список TPWS. Должно работать если эти домены не заблокированы;
И самый неправильный способ – это останавливать работу TPWS на время первоначальной загрузки интерфейса приложения, а затем для просмотра видео запускать его.
Я пошел другим более гибким и правильным путем, использования утилиты zapret в режиме NFQWS. Этот режим имеет ряд преимуществ пред режимом TPWS – больше параметров модификации сетевых пакетов, а также возможность модификации трафика по протоколу QUIC.
Инструкция по установке NFQWS на роутер keenetic
Данная инструкция будет выполнятся на примере роутера Keenetic ultra (kn-1810).
Для установки утилиты zapret, предварительно в веб-интерфейсе роутера нужно обязательно установить в прошивке компоненты: "Протокол IPv6" и "Модули ядра подсистемы Netfilter" (появляется только после выбора компонента "Протокол IPv6").


Далее необходимо подготовить внешний USB-накопитель и установить на него систему пакетов репозитория Entware согласно инструкции - Установка-системы-пакетов-репозитория-Entware-на-USB-накопитель.
После развертывания Entware на роутере с помощью терминальной программы Putty создаем SSH подключения, с указанием IP-адрес роутера (по умолчанию 192.168.1.1) и порта 222. Дальше авторизуемся с использованием логина: root и пароля: keenetic.
Далее можно приступать непосредственно к установке утилиты NFQWS:
Для начала узнаем имя внешнего сетевого интерфейса (WAN) на роутере. Его можно узнать воспользовавшись командой
ifconfig
, которая выведет все сетевые интерфейсы в системе. Просто находим тот интерфейс, у которого будет ваш внешний IP адрес. В моем случае – этоeth3
.Устанавливаем пакеты с помощью команды:
opkg update
opkg install coreutils-sort curl grep gzip ipset iptables kmod_ndms xtables-addons_legacy
Скачиваем на свой компьютер с github архив с последним tar.gz релизом Zapret и закидываем этот архив в папку tmp USB-накопителя роутера (можно с помощью сервера SMB (FTP) или через файловый менеджера USB-накопителей в веб-интерфейсе).
Приходим в папку tmp на роутере:
cd /opt/tmp
Распаковываем скаченный архив Zapret с помощью команды:
tar xvzf zapret-v70.3.tar.gz
Где
zapret-v70.3.tar.gz
меняем на имя вашего скаченного архива (меняется в каждом релизе).После окончания распаковки архива переходим в распакованную папку:
cd ./zapret-v70.3
Где
zapret-v70.3
меняем на имя вашей распакованной из архива папки (меняется в каждом релизе).Выполняем скрипт установки:
./install_easy.shВ начале установки этот скрипт автоматически скопирует все файлы из папки
zapret-v70
в/opt/zapret/
.Далее отвечаем на все вопросы, как скриншоте:
Выполнение скрипта install_easy.sh Выбираем имя внутреннего сетевого интерфейса (LAN),
br0
- обычно в роутере:Выбираем имя внутреннего сетевого интерфейса (LAN) Но заворот трафика на nfqws происходит всегда после маршрутизации, поэтому к нему применима только фильтрация по WAN, так что LAN в этом режиме работы неважен.
Выбираем свое ранее найденное имя внешнего сетевого интерфейса (WAN):
Выбираем имя внешнего сетевого интерфейса (WAN) Важно: выбираем режим фильтрации трафика (none, ipset, hostlist, autohostlist).
none
- фильтрация отключена, весь трафик обрабатывается утилитой. Простейший вариант. Рекомендую его использовать, если не хотите заморачиваться настройкой списков адресов, а хотите просто, чтобы быстро и просто все работало.ipset
- фильтрация трафика с помощьюipset
. Сложный режим, как работает читаем в инструкции.hostlist
- фильтрация списком хостов из файлов:/opt/zapret/ipset/zapret-hosts-user.txt
- прописывайте свои домены, которые нужно обрабатывать или в файле/opt/zapret/ipset/zapret-hosts-user-exclude.txt
- домены, которые нужно исключить из обработки. Пишется по одному доменному имени или IP-адресу на строчку. То что там изначально написано в файлах - удаляем. Рекомендую это режим использовать, если хотите обрабатывать только определенные адреса или наоборот если хотите исключить из обработки некоторые адреса.autohostlist
-режим hostlist + распознавание блокировок и ведение автоматического листа.Режим фильтра также можно потом менять через параметр
MODE_FILTER
в/opt/zapret/config
.Далее делаем свой выбор:
Завершение работы скрипта install_easy.sh Правим скрипт c именем zapret в командной строке с помощью предпочитаемого текстового редактора (в качестве примера vi) или можно зайти с компьютера через сеть на USB-накопитель (если он расшарен с помощью сервера SMB) и редактировать в текстовом редакторе на компьютере:
vi /opt/zapret/init.d/sysv/zapret
Добавляем в функцию
do_start()
код загрузки модулей ядра linux (xt_multiport.ko, xt_connbytes.ko, xt_NFQUEUE.ko), так как они по умолчанию не загружаются, а без нихiptables
будет выдавать ошибки при попытке применить необходимые правила.Итоговый скрипт
zapret
получается:#!/bin/sh ### BEGIN INIT INFO # Provides: zapret # Required-Start: $local_fs $network # Required-Stop: $local_fs $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 ### END INIT INFO SCRIPT=$(readlink -f "$0") EXEDIR=$(dirname "$SCRIPT") ZAPRET_BASE=$(readlink -f "$EXEDIR/../..") . "$EXEDIR/functions" NAME=zapret DESC=anti-zapret do_start() { if lsmod | grep "xt_multiport " &> /dev/null ; then echo "xt_multiport.ko is already loaded" else if insmod /lib/modules/$(uname -r)/xt_multiport.ko &> /dev/null; then echo "iptable_raw.ko loaded" else echo "Cannot find xt_multiport.ko kernel module, aborting" exit 1 fi fi if lsmod | grep "xt_connbytes " &> /dev/null ; then echo "xt_connbytes.ko is already loaded" else if insmod /lib/modules/$(uname -r)/xt_connbytes.ko &> /dev/null; then echo "xt_connbytes.ko loaded" else echo "Cannot find xt_connbytes.ko kernel module, aborting" exit 1 fi fi if lsmod | grep "xt_NFQUEUE " &> /dev/null ; then echo "xt_NFQUEUE.ko is already loaded" else if insmod /lib/modules/$(uname -r)/xt_NFQUEUE.ko &> /dev/null; then echo "xt_NFQUEUE.ko loaded" else echo "Cannot find xt_NFQUEUE.ko kernel module, aborting" exit 1 fi fi zapret_run_daemons [ "$INIT_APPLY_FW" != "1" ] || { zapret_apply_firewall; } } do_stop() { zapret_stop_daemons [ "$INIT_APPLY_FW" != "1" ] || zapret_unapply_firewall } case "$1" in start) do_start ;; stop) do_stop ;; restart) do_stop do_start ;; start-fw|start_fw) zapret_apply_firewall ;; stop-fw|stop_fw) zapret_unapply_firewall ;; restart-fw|restart_fw) zapret_unapply_firewall zapret_apply_firewall ;; start-daemons|start_daemons) zapret_run_daemons ;; stop-daemons|stop_daemons) zapret_stop_daemons ;; restart-daemons|restart_daemons) zapret_stop_daemons zapret_run_daemons ;; reload-ifsets|reload_ifsets) zapret_reload_ifsets ;; list-ifsets|list_ifsets) zapret_list_ifsets ;; list-table|list_table) zapret_list_table ;; *) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|restart|start-fw|stop-fw|restart-fw|start-daemons|stop-daemons|restart-daemons|reload-ifsets|list-ifsets|list-table}" >&2 exit 1 ;; esac exit 0
Все, на этом правка скрипта
zapret
закончена, сохраняем и выходим из текстового редактора.Копируем скрипт 10-keenetic-udp-fix для кинетика против отсутствия маскарада без ndmmark командой:
cp -a /opt/zapret/init.d/custom.d.examples.linux/10-keenetic-udp-fix /opt/zapret/init.d/sysv/custom.d/10-keenetic-udp-fix
После сохранения файла zapret делаем ссылку на скрипт
zapret
в автозагрузку:ln -fs /opt/zapret/init.d/sysv/zapret /opt/etc/init.d/S90-zapret
Далее необходимо создать скрипт, чтобы брандмауэр
netfilter
не забывал настроенные выше правила (иначе система быстро перезапишет наши правила). Делаем это также в командной строке с помощью текстового редактора:vi /opt/etc/ndm/netfilter.d/000-zapret.sh
Вставляем в файл следующий код:
#!/bin/sh [ "$table" != "mangle" ] && [ "$table" != "nat" ] && exit 0 /opt/zapret/init.d/sysv/zapret restart-fw exit 0
И даем право на исполнение скрипту
000-zapret.sh
с помощью команды:chmod +x /opt/etc/ndm/netfilter.d/000-zapret.sh
Данный скрипт будет вызывать наш ранее правленый скрипт zapret с параметром restart-fw, где мы прописали правила iptables.
Аналогично создаем скрипт отключения проверки контрольной суммы пакетов:
vi /opt/etc/init.d/S00fix
Вставляем в файл следующий код:
#!/bin/sh start() { sysctl -w net.netfilter.nf_conntrack_checksum=0 &> /dev/null } stop() { sysctl -w net.netfilter.nf_conntrack_checksum=1 &> /dev/null } case "$1" in 'start') start ;; 'stop') stop ;; *) stop start ;; esac exit 0
Также не забываем дать права на исполнения данному скрипту:
chmod +x /opt/etc/init.d/S00fix
И теперь в конце настроим конфиг NFQWS, находящийся по пути /opt/zapret/config.
В командной строке - с помощью текстового редактора, или лучше с компьютера через сеть редактируем:
vi /opt/zapret/config
Необходимо внести следующие правки:
Раскомментировать строчку
WS_USER=nobody
Далее необходимо прописать параметры для запуска процесса NFQWS. Тут нужно подбирать под себя, какие параметры дадут нужный результат.
В моем случае, для протокола HTTP:
--filter-tcp=80 --dpi-desync=fake,multisplit --dpi-desync-ttl=0 --dpi-desync-fooling=md5sig,badsum --new
Для протокола HTTPS:
--filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=method+2,midsld,5 --dpi-desync-ttl=0 --dpi-desync-fooling=md5sig,badsum,badseq --dpi-desync-repeats=15 --dpi-desync-fake-tls=/opt/zapret/files/fake/tls_clienthello_www_google_com.bin --new
И для протокола QUIC:
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=15 --dpi-desync-ttl=0 --dpi-desync-any-protocol --dpi-desync-cutoff=d4 --dpi-desync-fooling=md5sig,badsum --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_initial_www_google_com.bin
Также если ошиблись с именем внешнего интерфейса (WAN), то меняем в
IFACE_WAN
. Также можно прописать несколько используемых WAN интерфейсов через пробел, например -IFACE_WAN="eth3 eth2"
.Мой готовый конфиг (представлен только для информации, ваш конфиг генерируется скриптом
install_easy.sh
согласно вашим параметрам, и в нем нужно поменять только выше указанные поля) :# this file is included from init scripts # change values here # can help in case /tmp has not enough space #TMPDIR=/opt/zapret/tmp # redefine user for zapret daemons. required on Keenetic WS_USER=nobody # override firewall type : iptables,nftables,ipfw FWTYPE=iptables # nftables only : set this to 0 to use pre-nat mode. default is post-nat. # pre-nat mode disables some bypass techniques for forwarded traffic but allows to see client IP addresses in debug log #POSTNAT=0 # options for ipsets # maximum number of elements in sets. also used for nft sets SET_MAXELEM=522288 # too low hashsize can cause memory allocation errors on low RAM systems , even if RAM is enough # too large hashsize will waste lots of RAM IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM" # dynamically generate additional ip. $1 = ipset/nfset/table name #IPSET_HOOK="/etc/zapret.ipset.hook" # options for ip2net. "-4" or "-6" auto added by ipset create script IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4" IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5" # options for auto hostlist AUTOHOSTLIST_RETRANS_THRESHOLD=3 AUTOHOSTLIST_FAIL_THRESHOLD=3 AUTOHOSTLIST_FAIL_TIME=60 # 1 = debug autohostlist positives to ipset/zapret-hosts-auto-debug.log AUTOHOSTLIST_DEBUGLOG=0 # number of parallel threads for domain list resolves MDIG_THREADS=30 # ipset/*.sh can compress large lists GZIP_LISTS=1 # command to reload ip/host lists after update # comment or leave empty for auto backend selection : ipset or ipfw if present # on BSD systems with PF no auto reloading happens. you must provide your own command # set to "-" to disable reload #LISTS_RELOAD="pfctl -f /etc/pf.conf" # mark bit used by nfqws to prevent loop DESYNC_MARK=0x40000000 DESYNC_MARK_POSTNAT=0x20000000 TPWS_SOCKS_ENABLE=0 # tpws socks listens on this port on localhost and LAN interfaces TPPORT_SOCKS=987 # use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir # hostlist markers are replaced to empty string if MODE_FILTER does not satisfy # <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list TPWS_SOCKS_OPT=" --filter-tcp=80 --methodeol <HOSTLIST> --new --filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST> " TPWS_ENABLE=0 TPWS_PORTS=80,443 # use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir # hostlist markers are replaced to empty string if MODE_FILTER does not satisfy # <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list TPWS_OPT=" --filter-tcp=80 --methodeol <HOSTLIST> --new --filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST> " NFQWS_ENABLE=1 # redirect outgoing traffic with connbytes limiter applied in both directions. NFQWS_PORTS_TCP=80,443 NFQWS_PORTS_UDP=443 # PKT_OUT means connbytes dir original # PKT_IN means connbytes dir reply # this is --dpi-desync-cutoff=nX kernel mode implementation for linux. it saves a lot of CPU. NFQWS_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD)) NFQWS_TCP_PKT_IN=3 NFQWS_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD)) NFQWS_UDP_PKT_IN=0 # redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter # normally it's needed only for stateless DPI that matches every packet in a single TCP session # typical example are plain HTTP keep alives # this mode can be very CPU consuming. enable with care ! #NFQWS_PORTS_TCP_KEEPALIVE=80 #NFQWS_PORTS_UDP_KEEPALIVE= # use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir # hostlist markers are replaced to empty string if MODE_FILTER does not satisfy # <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list NFQWS_OPT=" --filter-tcp=80 --dpi-desync=fake,multisplit --dpi-desync-ttl=0 --dpi-desync-fooling=md5sig,badsum <HOSTLIST> --new --filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=method+2,midsld,5 --dpi-desync-ttl=0 --dpi-desync-fooling=md5sig,badsum,badseq --dpi-desync-repeats=15 --dpi-desync-fake-tls=/opt/zapret/files/fake/tls_clienthello_www_google_com.bin <HOSTLIST> --new --filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=15 --dpi-desync-ttl=0 --dpi-desync-any-protocol --dpi-desync-cutoff=d4 --dpi-desync-fooling=md5sig,badsum --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_initial_www_google_com.bin <HOSTLIST> " # none,ipset,hostlist,autohostlist MODE_FILTER=none # openwrt only : donttouch,none,software,hardware FLOWOFFLOAD=donttouch # openwrt: specify networks to be treated as LAN. default is "lan" #OPENWRT_LAN="lan lan2 lan3" # openwrt: specify networks to be treated as WAN. default wans are interfaces with default route #OPENWRT_WAN4="wan vpn" #OPENWRT_WAN6="wan6 vpn6" # for routers based on desktop linux and macos. has no effect in openwrt. # CHOOSE LAN and optinally WAN/WAN6 NETWORK INTERFACES # or leave them commented if its not router # it's possible to specify multiple interfaces like this : IFACE_LAN="eth0 eth1 eth2" # if IFACE_WAN6 is not defined it take the value of IFACE_WAN IFACE_LAN=br0 IFACE_WAN=eth3 #IFACE_WAN6="ipsec0 wireguard0 he_net" # should start/stop command of init scripts apply firewall rules ? # not applicable to openwrt with firewall3+iptables INIT_APPLY_FW=1 # firewall apply hooks #INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret.hook.pre_up" #INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up" #INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret.hook.pre_down" #INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret.hook.post_down" # do not work with ipv4 #DISABLE_IPV4=1 # do not work with ipv6 DISABLE_IPV6=0 # select which init script will be used to get ip or host list # possible values : get_user.sh get_antizapret.sh get_combined.sh get_reestr.sh get_hostlist.sh # comment if not required #GETLIST=
На этом настройка роутера завершена и можно удалить (с использованием того же метода, которым закидывали архив на роутер) из папки tmp USB-накопителя роутера папку
zapret-v70.3
и архивzapret-v70.3.tar.gz
(конкретные имена зависят от релиза).Теперь можно запускать в работу NFQWS и проверять работоспособность с помощью команды:
/opt/zapret/init.d/sysv/zapret start
Для перезагрузки NFQWS использовать команду:
/opt/zapret/init.d/sysv/zapret restart
Для остановки NFQWS использовать команду:
/opt/zapret/init.d/sysv/zapret stop
Также для повышения безопасности и предотвращения возможности перехвата DNS-трафика рекомендуется на роутере настроить протоколы DNS over TLS и/или DNS over HTTPS в соответствии с инструкцией - Прокси-серверы DNS-over-TLS и DNS-over-HTTPS для шифрования DNS-запросов:
Настройка DNS over TLS и/или DNS over HTTPS В случае проблем с доступностью или скоростью доступа к каким-то сайтам меняем параметры
в --filter-tcp=80
и/или--filter-tcp=443
и/или--filter-udp=443
, перезагружаем утилиту NFQWS с помощью команды и опять проверяем, и так делаем по циклу пока не получим нужный результат. Если ломается что-то, что раньше работало, то рекомендуется сначала пробывать менять параметрыdpi-desync-ttl
в конфиге: начинаем от 1 и увеличиваем с шагом 1 и проверять, чтобы пробивала не доступные соединения, но не ломало рабочие. При dpi-desync-ttl=0 (по умолчанию) будет оригинальный TTL у фейков, в таком случаи они гарантировано пойдут ограничители, но также могут на некоторых серверах сломать соединения, если ими не будут отброшены, как некорректные, учитывая параметрыdpi-desync-fooling
. Если не удается найти решение, чтобы все работало и ничего нужного не ломалась, то используем режим фильтрацииhostlist
.Также некоторым может пригодиться для работы диска:
1) Останавливаем
zapret
командой:/opt/zapret/init.d/sysv/zapret stop
2) Копируем скрипт 50-discord командой:
cp -a /opt/zapret/init.d/custom.d.examples.linux/50-discord /opt/zapret/init.d/sysv/custom.d/50-discord
3) Запускаем
zapret
командой:/opt/zapret/init.d/sysv/zapret start
После этого будет поднят отдельный процесс
NFQWS
для модификации трафика на портахUDP 50000-50099
. Стратегия модификации задается в переменнойNFQWS_OPT_DESYNC_DISCORD
этого скрипта.Так как Zapret на github автором периодически обновляется и выходят новые релизы, то не лишним будет иногда его обновлять и у себя. Для это придется проделать все по новой начиная с пункта 3 инструкции и заканчивая 18 пунктом, за исключением пунктов 12-14 (их делать не нужно).
Но предварительно нужно остановить Zapret командой:
/opt/zapret/init.d/sysv/zapret stop
И удалить папку
zapret
с накопителя командой:rm -r /opt/zapret/