Как стать автором
Обновить

Установка программы модификации сетевых пакетов NFQWS на роутер Keenetiс

Уровень сложностиСредний
Время на прочтение11 мин
Количество просмотров133K

Привет, Хабр!

Сегодня рассмотрим вариант установки утилиты модификации сетевых пакетов 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, я вижу три возможных варианта:

  1. Подбирать параметры запуска TPWS (но их там не так много), чтобы они не ломали загрузку приложения YouTube, а все остальное работало, как должно. Мне этого так и не удалось добиться.

  2. Вычислить доменные адреса, по которым приложение YouTube загружает интерфейс и включить их в exclude список TPWS. Должно работать если эти домены не заблокированы;

  3. И самый неправильный способ – это останавливать работу TPWS на время первоначальной загрузки интерфейса приложения, а затем для просмотра видео запускать его.

Я пошел другим более гибким и правильным путем, использования утилиты zapret в режиме NFQWS. Этот режим имеет ряд преимуществ пред режимом TPWS – больше параметров модификации сетевых пакетов, а также возможность модификации трафика по протоколу QUIC.

Инструкция по установке NFQWS на роутер keenetic

Данная инструкция будет выполнятся на примере роутера Keenetic ultra (kn-1810).

Для установки утилиты zapret, предварительно в веб-интерфейсе роутера нужно обязательно установить в прошивке компоненты: "Протокол IPv6" и "Модули ядра подсистемы Netfilter" (появляется только после выбора компонента "Протокол IPv6").

Модули ядра подсистемы Netfilter
Модули ядра подсистемы Netfilter
Протокол IPv6
Протокол IPv6

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

После развертывания Entware на роутере с помощью терминальной программы Putty создаем SSH подключения, с указанием IP-адрес роутера (по умолчанию 192.168.1.1) и порта 222. Дальше авторизуемся с использованием логина: root и пароля: keenetic.

Далее можно приступать непосредственно к установке утилиты NFQWS:

  1. Устанавливаем пакеты с помощью команды:

    opkg update

    opkg install coreutils-sort curl git-http grep gzip ipset iptables kmod_ndms xtables-addons_legacy

  2. Приходим папку opt:

    cd /opt/

  3. Скачиваем Zapret с github:

    git clone --depth=1 https://github.com/bol-van/zapret.git

  4. Для начала узнаем имя внешнего сетевого интерфейса (WAN) на роутере. Его можно узнать воспользовавшись командой ifconfig, которая выведет все сетевые интерфейсы в системе. Просто находим тот интерфейс, у которого будет ваш внешний IP адрес. В моем случае – это eth3.

  5. Переходим в папку zapret и выполняем скрипт:

    cd zapret
    ./install_easy.sh

  6. Далее отвечаем на все вопросы, как скриншоте:

    Выполнение скрипта install_easy.sh
    Выполнение скрипта install_easy.sh
  7. Выбираем свой ранее найденное имя внешнего сетевого интерфейса (WAN):

    Выбираем имя внешнего сетевого интерфейса (WAN)
    Выбираем имя внешнего сетевого интерфейса (WAN)
  8. Важно: выбираем режим фильтрации трафика (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
    Завершение выполнения скрипта install_easy.sh
  9. Правим скрипт 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 будет выдавать ошибки при попытке применить необходимые правила.

    Затем в секции do_start(), do_stop() и restart-fw|restart_fw добавляем следующие коды:

    for IFACE_N in $IFACE_WAN; do
    iptables -t nat -A POSTROUTING -o $IFACE_N -j MASQUERADE
    done

    for IFACE_N in $IFACE_WAN; do
    iptables -t nat -D POSTROUTING -o $IFACE_N -j MASQUERADE
    done

    Итоговый скрипт 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; }
    	for IFACE_N in $IFACE_WAN; do
    		iptables -t nat -A POSTROUTING -o $IFACE_N -j MASQUERADE
        done
    }
    do_stop()
    {
    	zapret_stop_daemons
    	[ "$INIT_APPLY_FW" != "1" ] || zapret_unapply_firewall
    	for IFACE_N in $IFACE_WAN; do
    		iptables -t nat -D POSTROUTING -o $IFACE_N -j MASQUERADE
    	done
    }
    
    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
    		for IFACE_N in $IFACE_WAN; do
    			iptables -t nat -D POSTROUTING -o $IFACE_N -j MASQUERADE
    		done
    			
    		zapret_apply_firewall
    		for IFACE_N in $IFACE_WAN; do
    			iptables -t nat -A POSTROUTING -o $IFACE_N -j MASQUERADE
    		done
    		;;
    	
    	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 закончена, сохраняем и выходим из текстового редактора.

    При запуске скрипта zapret в режиме поддержки протокола QUIC будут подыматься два отдельных процесса NFQWS, первый будет обрабатывать трафик по протоколам HTTP и HTTPS на очереди NFQUEUE №200, а второй трафик протокола QUIC на очереди NFQUEUE №210.

  10. После сохранения файла zapret делаем ссылку на скрипт zapret в автозагрузку:

    ln -fs /opt/zapret/init.d/sysv/zapret /opt/etc/init.d/S90-zapret

  11. Далее необходимо создать скрипт, чтобы брандмауэр 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.

  12. Аналогично создаем скрипт отключения проверки контрольной суммы пакетов:

    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

  13. И теперь в конце настроим конфиг NFQWS, находящийся по пути /opt/zapret/config.

    В командной строке - с помощью текстового редактора, или лучше с компьютера через сеть редактируем:

    vi /opt/zapret/config

  14. Необходимо внести следующие правки:

    Раскомментировать строчку

    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=0 --dpi-desync-fooling=md5sig,badsum --dpi-desync-repeats=15 --dpi-desync-any-protocol --dpi-desync-cutoff=d4 --dpi-desync-fake-tls=/opt/zapret/files/fake/tls_clienthello_www_google_com.bin"

    И для протокола QUIC (с данными параметрами будет запущен второй процесс NFQWS):

    NFQWS_OPT_DESYNC_QUIC="--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
    
    # 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=15 --dpi-desync-any-protocol --dpi-desync-cutoff=d4 --dpi-desync-fake-tls=/opt/zapret/files/fake/tls_clienthello_www_google_com.bin"
    #NFQWS_OPT_DESYNC_HTTP=
    #NFQWS_OPT_DESYNC_HTTPS=
    #NFQWS_OPT_DESYNC_HTTP6=
    #NFQWS_OPT_DESYNC_HTTPS6=
    NFQWS_OPT_DESYNC_QUIC="--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"
    #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

  15. На этом настройка роутера завершена и можно запускать в работу NFQWS и проверять работоспособность с помощью команды:

    /opt/zapret/init.d/sysv/zapret start

    Для перезагрузки NFQWS использовать команду:

    /opt/zapret/init.d/sysv/zapret restart

    Для остановки NFQWS использовать команду:

    /opt/zapret/init.d/sysv/zapret stop

  16. Также для повышения безопасности и предотвращения возможности перехвата DNS-трафика рекомендуется на роутере настроить протоколы DNS over TLS и/или DNS over HTTPS в соответствии с инструкцией - Прокси-серверы DNS-over-TLS и DNS-over-HTTPS для шифрования DNS-запросов:

    Настройка DNS over TLS и/или DNS over HTTPS
    Настройка DNS over TLS и/или DNS over HTTPS
  17. В случае проблем с доступностью или скоростью доступа к каким-то сайтам меняем параметры в NFQWS_OPT_DESYNC_QUIC и/или NFQWS_OPT_DESYNC, перезагружаем утилиту NFQWS с помощью команды и опять проверяем, и так делаем по циклу пока не получим нужный результат.

  18. Так как zapret на github автором периодически обновляется, то не лишним будет иногда его обновлять и у себя. Для это достаточно выполнить команды:

    cd /opt/zapret
    git pull

    Ваша конфигурация при обновлении не будет перезаписана, повторная настройка не требуется. Единственное, если в конфиге автором будут добавляться/изменяться переменные, тогда для отражения в конфиге и использования этих изменений у вас - необходимо выполнить повторную конфигурацию с помощью install_easy.sh .

Теги:
Хабы:
Всего голосов 53: ↑53 и ↓0+62
Комментарии663

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
26 октября
ProIT Network Fest
Санкт-Петербург
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань