Привет, Хабр!
Сегодня рассмотрим вариант установки утилиты модификации сетевых пакетов Zapret на роутеры Keenetic. В отличии от простого использования на конкретных устройствах, при установке на роутер появляется возможность обрабатывать трафик идущий от всех устройств, подключенных к домашней локальной сети (ПК, смартфоны и смарт телевизоры).
Указанная утилита предлагает два основных режима работы – это TPWS или NFQWS. При использовании в режиме TPWS есть недостатки, заключающиеся в том, что в этом режиме не модифицируется протокол QUIC (HTTP/3), а также приложение YouTube на смарт телевизорах с WebOS или Android TV перестает вообще запускаться.
Информация по протоколам YouTube и возникающим проблемам при использовании
Для начала попробуем определиться с тем, какие протоколы используются YouTube на различных устройствах:
В браузерах на ПК может использоваться как новый протокол QUIC (трафик идет по протоколу UDP на порт 443), так и классический HTTPS (трафик идет по протоколу TCP на порт 443). Однако, у меня хоть в браузере и включена поддержка протокола QUIC, но YouTube мне так и не удалось через него заставить работать - все время трафик идет через HTTPS;
В приложении 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, необходимо сначала сначала подготовить внешний USB-накопитель и установить на него систему пакетов репозитория Entware согласно инструкции - Установка-системы-пакетов-репозитория-Entware-на-USB-накопитель.
Также предварительно в веб-интерфейсе роутера нужно обязательно установить в прошивке компоненты: "Протокол IPv6" и "Модули ядра подсистемы Netfilter" (появляется только после выбора компонента "Протокол IPv6").


После развертывания Entware на роутере с помощью терминальной программы Putty создаем SSH подключения, с указанием IP-адрес роутера (по умолчанию 192.168.1.1) и порта 222. Дальше авторизуемся с использованием логина: root и пароля: keenetic.
Далее можно приступать непосредственно к установке утилиты NFQWS:
Устанавливаем пакеты с помощью команды:
opkg install coreutils-sort curl git-http grep gzip ipset iptables kmod_ndms xtables-addons_legacy-
Приходим папку opt:
cd /opt/ -
Скачиваем Zapret с github:
git clone --depth=1 https://github.com/bol-van/zapret.git Для начала узнаем имя внешнего сетевого интерфейса (WAN) на роутере. Его можно узнать воспользовавшись командой
ifconfig, которая выведет все сетевые интерфейсы в системе. Просто находим тот интерфейс, у которого будет ваш внешний IP адрес. В моем случае – этоeth3.-
Переходим в папку zapret и выполняем скрипт:
cd zapret
./install_easy.sh -
Далее отвечаем на все вопросы, как скриншоте:

Выполнение скрипта install_easy.sh -
Выбираем свой ранее найденное имя внешнего сетевого интерфейса (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будет выдавать ошибки при попытке применить необходимые правила.Затем в секции
restart-fw|restart_fwдобавляемiptables -t nat -D POSTROUTING -o $IFACE_WAN -j MASQUERADEиiptables -t nat -A POSTROUTING -o $IFACE_WAN -j MASQUERADE.#!/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; } iptables -t nat -A POSTROUTING -o $IFACE_WAN -j MASQUERADE } do_stop() { zapret_stop_daemons [ "$INIT_APPLY_FW" != "1" ] || zapret_unapply_firewall iptables -t nat -D POSTROUTING -o $IFACE_WAN -j MASQUERADE } 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 iptables -t nat -D POSTROUTING -o $IFACE_WAN -j MASQUERADE zapret_apply_firewall iptables -t nat -A POSTROUTING -o $IFACE_WAN -j MASQUERADE ;; 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 закончена, сохраняем и выходим из текстового редактора.
В небольшая информация по используемым правилам iptables (точнее вариант, а так могут немного меняться в зависимости от конфигурации):
Команда, которая перенаправляет исходящий и проходящий в сторону внешнего интерфейса
$IFACE_WAN(eth3) трафик HTTP (TCP порт 80) на очередь NFQUEUE №200:iptables -t mangle -I POSTROUTING -o $IFACE_WAN -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypassКоманда перенаправляет исходящий и проходящий в сторону внешнего интерфейса
$IFACE_WAN(eth3) трафик HTTPS (TCP порт 443) на очередь NFQUEUE №200:iptables -t mangle -I POSTROUTING -o $IFACE_WAN -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypassКоманда перенаправляет исходящий и проходящий в сторону внешнего интерфейса
$IFACE_WAN(eth3) трафик QUIC (UDP порт 443) на очередь NFQUEUE №210:iptables -t mangle -I POSTROUTING -o $IFACE_WAN -p udp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 210 --queue-bypassТакже согласно комментарию автора данной утилиты для успешной работы с протоком QUIC через NFQWS на роутера Keenetic необходимо добавить маскарад на исходящий интерфейс WAN:
iptables -t nat -A POSTROUTING -o $IFACE_WAN -j MASQUERADEДанные правила представлены для случая использования протокола IPv4, а в случае также использования протокола IPv6 правила там аналогичны, но используется команда
ip6tables.При запуске скрипта
zapretв режиме поддержки протокола QUIC будут подыматься два отдельных процесса NFQWS, первый будет обрабатывать трафик по протоколам HTTP и HTTPS на очереди NFQUEUE №200, а второй трафик протокола QUIC на очереди NFQUEUE №210. -
После сохранения файла 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 [ "$type" == "ip6tables" ] && exit 0 [ "$table" != "mangle" ] && exit 0 /opt/zapret/init.d/sysv/zapret restart-fwИ даем право на исполнения скрипту
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() { echo 0 > /proc/sys/net/netfilter/nf_conntrack_checksum } stop() { echo 1 > /proc/sys/net/netfilter/nf_conntrack_checksum } 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 трафика протокола QUIC изменить MODE_QUIC на:
MODE_QUIC=1Далее необходимо прописать параметры для запуска процессов NFQWS. Тут нужно подбирать под себя, какие параметры дадут нужный результат.
В моем случае, для протоколов HTTP и HTTPS (с данными параметрами будет запущен первый процесс NFQWS):
NFQWS_OPT_DESYNC="--dpi-desync=fake,disorder2 --dpi-desync-split-pos=1 --dpi-desync-ttl=6 --dpi-desync-fooling=badsum --dpi-desync-repeats=6 --dpi-desync-any-protocol --dpi-desync-cutoff=d4"И для протокола QUIC (с данными параметрами будет запущен второй процесс NFQWS):
NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake,disorder2 --dpi-desync-repeats=6 --dpi-desync-any-protocol --dpi-desync-cutoff=d4"Мой готовый конфиг:
# 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 # 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" # override ports #HTTP_PORTS=80-81,85 #HTTPS_PORTS=443,500-501 #QUIC_PORTS=443,444 # CHOOSE OPERATION MODE # MODE : nfqws,tpws,tpws-socks,filter,custom # nfqws : nfqws for dpi desync # tpws : tpws transparent mode # tpws-socks : tpws socks mode # filter : no daemon, just create ipset or download hostlist # custom : custom mode. should modify custom init script and add your own code MODE=nfqws # apply fooling to http MODE_HTTP=1 # for nfqws only. support http keep alives. enable only if DPI checks for http request in any outgoing packet MODE_HTTP_KEEPALIVE=0 # apply fooling to https MODE_HTTPS=1 # apply fooling to quic MODE_QUIC=1 # none,ipset,hostlist,autohostlist MODE_FILTER=none # CHOOSE NFQWS DAEMON OPTIONS for DPI desync mode. run "nfq/nfqws --help" for option list DESYNC_MARK=0x40000000 DESYNC_MARK_POSTNAT=0x20000000 NFQWS_OPT_DESYNC="--dpi-desync=fake,disorder2 --dpi-desync-split-pos=1 --dpi-desync-ttl=0 --dpi-desync-fooling=md5sig,badsum --dpi-desync-repeats=6 --dpi-desync-any-protocol --dpi-desync-cutoff=d4" #NFQWS_OPT_DESYNC_HTTP= #NFQWS_OPT_DESYNC_HTTPS= #NFQWS_OPT_DESYNC_HTTP6= #NFQWS_OPT_DESYNC_HTTPS6= NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake,disorder2 --dpi-desync-repeats=6 --dpi-desync-ttl=0 --dpi-desync-any-protocol --dpi-desync-cutoff=d4 --dpi-desync-fooling=md5sig,badsum" #NFQWS_OPT_DESYNC_QUIC6= # CHOOSE TPWS DAEMON OPTIONS. run "tpws/tpws --help" for option list TPWS_OPT="--hostspell=HOST --split-http-req=method --split-pos=3 --oob" # 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=get_user.shТакже если ошиблись с именем внешнего интерфейса (WAN), то меняем в
IFACE_WAN. -
На этом настройка роутера завершена и можно запускать в работу 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-серверы провайдера на публичные. Прописываем IP адреса DNS -
8.8.8.8и8.8.4.4, и не забываем поставить галочку игнорировать DNS предлагаемые провайдером интернета:
Настройки роутера для работы с публичными DNS-серверами В случае проблем с доступностью или скоростью доступа к каким-то сайтам меняем параметры в
NFQWS_OPT_DESYNC_QUICи/илиNFQWS_OPT_DESYNC, перезагружаем утилиту NFQWS с помощью команды и опять проверяем, и так делаем по циклу пока не получим нужный результат.