From 4347cce3b62b8518196dd702330532e344fee327 Mon Sep 17 00:00:00 2001 From: bol-van Date: Wed, 27 Jul 2022 16:35:05 +0300 Subject: [PATCH] launch system: support separate and multiple hostlists --- common/list.sh | 31 +++++++++++++++++++ docs/changes.txt | 6 ++++ docs/readme.eng.md | 32 ++++++++++++------- docs/readme.txt | 54 ++++++++++++++++++++------------- init.d/macos/functions | 11 +------ init.d/openwrt/zapret | 9 ------ init.d/sysv/functions | 10 +----- ipset/get_antizapret_domains.sh | 13 +------- ipset/get_reestr_hostlist.sh | 13 +------- 9 files changed, 95 insertions(+), 84 deletions(-) create mode 100644 common/list.sh diff --git a/common/list.sh b/common/list.sh new file mode 100644 index 0000000..f8d7c4e --- /dev/null +++ b/common/list.sh @@ -0,0 +1,31 @@ +find_hostlists() +{ + [ -n "$HOSTLIST_BASE" ] || HOSTLIST_BASE="$ZAPRET_BASE/ipset" + + HOSTLIST="$HOSTLIST_BASE/zapret-hosts.txt.gz" + [ -f "$HOSTLIST" ] || HOSTLIST="$HOSTLIST_BASE/zapret-hosts.txt" + [ -f "$HOSTLIST" ] || HOSTLIST= + + HOSTLIST_USER="$HOSTLIST_BASE/zapret-hosts-user.txt.gz" + [ -f "$HOSTLIST_USER" ] || HOSTLIST_USER="$HOSTLIST_BASE/zapret-hosts-user.txt" + [ -f "$HOSTLIST_USER" ] || HOSTLIST_USER= + + HOSTLIST_EXCLUDE="$HOSTLIST_BASE/zapret-hosts-user-exclude.txt.gz" + [ -f "$HOSTLIST_EXCLUDE" ] || HOSTLIST_EXCLUDE="$HOSTLIST_BASE/zapret-hosts-user-exclude.txt" + [ -f "$HOSTLIST_EXCLUDE" ] || HOSTLIST_EXCLUDE= +} + +filter_apply_hostlist_target() +{ + # $1 - var name of tpws or nfqws params + + [ "$MODE_FILTER" = "hostlist" ] || return + + local HOSTLIST_BASE HOSTLIST HOSTLIST_USER HOSTLIST_EXCLUDE + + find_hostlists + + [ -n "$HOSTLIST" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST\"" + [ -n "$HOSTLIST_USER" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST_USER\"" + [ -n "$HOSTLIST_EXCLUDE" ] && eval $1="\"\$$1 --hostlist-exclude=$HOSTLIST_EXCLUDE\"" +} diff --git a/docs/changes.txt b/docs/changes.txt index ef59f63..02202ee 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -227,3 +227,9 @@ v47 nfqws: QUIC initial decryption nfqws: udplen, fakeknown dpi desync modes + +v48 + +nfqws, tpws : multiple --hostlist and --hostlist-exclude support +launch system, ipset : no more list merging. all lists are passed separately to nfqws and tpws +nfqws : udplen fooling supports packet shrinking (negative increment value) diff --git a/docs/readme.eng.md b/docs/readme.eng.md index ce6c4ef..20022e9 100644 --- a/docs/readme.eng.md +++ b/docs/readme.eng.md @@ -174,7 +174,8 @@ nfqws takes the following parameters: --dpi-desync-fake-quic= ; file containing fake QUIC Initial --dpi-desync-fake-unknown-udp= ; file containing unknown udp protocol fake payload --dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N - --hostlist= ; apply fooling only to the listed hosts (one host per line, subdomains auto apply) + --hostlist= ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) + --hostlist-exclude= ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) ``` The manipulation parameters can be combined in any way. @@ -523,7 +524,8 @@ tpws is transparent proxy. ; its worth to make a reserve with 1.5 multiplier. by default maxfiles is (X*connections)*1.5+16 --max-orphan-time= ; if local leg sends something and closes and remote leg is still connecting then cancel connection attempt after N seconds - --hostlist= ; only act on host in the list (one host per line, subdomains auto apply, gzip lists supported) + --hostlist= ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) + --hostlist-exclude= ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) --split-http-req=method|host ; split http request at specified logical position. --split-pos= ; split at specified pos. split-http-req takes precedence over split-pos for http reqs. --split-any-protocol ; split not only http and https @@ -662,13 +664,25 @@ LISTS_RELOAD=- disables reloading ip list backend. ## Domain name filtering -An alternative to ipset is to use tpws or nfqws with a list of domains. Only one list is supported. +An alternative to ipset is to use tpws or nfqws with a list(s) of domains. +Both `tpws` and `nfqws` take any number of include (`--hostlist`) and exclude (`--hostlist-exclude`) domain lists. +All lists of the same type are combined internally leaving only 2 lists : include and exclude. -Enter the blocked domains to `ipset/zapret-hosts-users.txt`. Remove `ipset/zapret-hosts.txt.gz`. -Then the init script will run tpws with the `zapret-hosts-users.txt` list. +Exclude list is checked first. Fooling is cancelled if domain belongs to exclude list. +If include list is present and domain does not belong to that list fooling is also cancelled. +Empty list means absent list. Otherwise fooling goes on. -Other option ( Roskomnadzor list - `get_hostlist.sh` ) is russian specific. -You can write your own replacement for `get_hostlist.sh`. +Launch system looks for 2 include lists : +`ipset/zapret-hosts-users.txt.gz` or `ipset/zapret-hosts-users.txt` +`ipset/zapret-hosts.txt.gz` or `ipset/zapret-hosts.txt` +and 1 exclude list +`ipset/zapret-hosts-users-exclude.txt.gz` or `ipset/zapret-hosts-users-exclude.txt` + +If `MODE_FILTER=hostlist` all present lists are passed to `nfqws` or `tpws`. +If all include lists are empty it works like no include lists exist at all. +If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Just make it empty. + +Subdomains auto apply. For example, "ru" in the list affects "*.ru" . When filtering by domain name, daemons should run without filtering by ipset. When using large regulator lists estimate the amount of RAM on the router ! @@ -943,10 +957,6 @@ Example : `--uid 1:3003` In iptables use : `! --uid-owner 1` instead of `! --uid-owner tpws`. -Nfqws should be executed with `--uid 1`. Otherwise on some devices and newer androids -kernel may partially hang. Looks like processes with certain uids can be suspended. -With buggy chineese cellular interface driver this can lead to device hang. - Write your own shell script with iptables and tpws, run it using your root manager. Autorun scripts are here : diff --git a/docs/readme.txt b/docs/readme.txt index 492816a..56699de 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -1,4 +1,4 @@ -zapret v.47 +zapret v.48 English ------- @@ -226,7 +226,8 @@ nfqws --dpi-desync-fake-unknown-udp= ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт --dpi-desync-udplen-increment= ; насколько увеличивать длину udp пейлоада в режиме udplen --dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N - --hostlist= ; применять дурение только к хостам из листа + --hostlist= ; применять дурение только к хостам из листа. может быть множество листов, они обьединяются. пустой обший лист = его отсутствие + --hostlist-exclude= ; не применять дурение к хостам из листа. может быть множество листов, они обьединяются Параметры манипуляции могут сочетаться в любых комбинациях. @@ -586,11 +587,12 @@ tpws - это transparent proxy. --hostlist= ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются. ; в файле должен быть хост на каждой строке. ; список читается 1 раз при старте и хранится в памяти в виде иерархической структуры для быстрого поиска. - ; для списка РКН может потребоваться система с 128 Mb памяти ! - ; расчитывайте требование RAM для процесса как 3-5 кратный размер файла списка. ; по сигналу HUP список будет перечитан при следующем принятом соединении ; список может быть запакован в gzip. формат автоматически распознается и разжимается + ; списков может быть множество, они обьединяются. пустой общий лист = его отсутствие ; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello. + --hostlist-exclude= ; не применять дурение к доменам из листа. может быть множество листов, они обьединяются + Параметры манипуляции могут сочетаться в любых комбинациях. @@ -828,19 +830,36 @@ ip2net фильтрует входные данные, выкидывая неп ---------------------------- Альтернативой ipset является использование tpws или nfqws со списком доменов. -Может быть только один hostlist. +Оба демона принимают неограниченное количество листов include (--hostlist) и exclude (--hostlist-exclude). +Все листы одного типа обьединяются, и таким образом остаются только 2 листа. +Прежде всего проверяется exclude list. При вхождении в него происходит отказ от дурения. +Далее при наличии include list проверяется домен на вхождение в него. При невхождении в список отказ от дурения. +Пустой список приравнивается к его отсутствию. +В иных случаях происходит дурение. +Нет ни одного списка - дурение всегда. +Есть только exclude список - дурение всех, кроме. +Есть только include список - дурение только их. +Есть оба - дурение только include, кроме exclude. -Поддерживаются следующие варианты : -1) Внесите домены для дурения в ipset/zapret-hosts-users.txt. Удалите ipset/zapret-hosts.txt.gz. -Тогда init скрипт будет запускать tpws/nfqws с листом zapret-hosts-users.txt. +В системе запуска это обыграно следующим образом. +Присутствуют 2 include списка : +ipset/zapret-hosts-users.txt.gz или ipset/zapret-hosts-users.txt +ipset/zapret-hosts.txt.gz или ipset/zapret-hosts.txt +и 1 exclude список +ipset/zapret-hosts-users-exclude.txt.gz или ipset/zapret-hosts-users-exclude.txt -2) Список доменов РКН может быть получен скриптами ipset/get_reestr_hostlist.sh или ipset/get_antizapret_domains.sh +При режиме фильтрации MODE_FILTER=hostlist система запуска передает nfqws или tpws все листы, файлы которых присутствуют. +Если вдруг листы include присутствуют, но все они пустые, то работа аналогична отсутствию include листа. +Файл есть, но не смотря на это дурится все, кроме exclude. +Если вам нужен именно такой режим - не обязательно удалять zapret-hosts-users.txt. Достаточно сделать его пустым. + +Поддомены учитываются автоматически. Например, строчка "ru" вносит в список "*.ru". Строчка "*.ru" в списке не сработает. + +Список доменов РКН может быть получен скриптами ipset/get_reestr_hostlist.sh или ipset/get_antizapret_domains.sh - кладется в ipset/zapret-hosts.txt.gz. -Этот скрипт автоматически добавляет к списку РКН домены из zapret-hosts-user.txt и исключает zapret-hosts-exclude.txt. -init скрипт будет запускать tpws/nfqws с листом zapret-hosts.txt.gz. При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset. -tpws и nfqws решают нужно ли применять дурение в зависимости от поля Host: в http запросе или SNI в TLS ClientHello. +tpws и nfqws решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (http, tls, quic). При использовании больших списков, в том числе списка РКН, оцените объем RAM на роутере ! Если после запуска демона RAM под завязку или случаются oom, значит нужно отказаться от таких больших списков. @@ -1190,15 +1209,8 @@ tpws будет работать в любом случае, он не треб magisk : /data/adb/service.d supersu : /system/su.d -nfqws может иметь такой глюк. При запуске с uid по умолчанию (0x7FFFFFFF) при условии работы на сотовом интерфейсе -и отключенном кабеле внешнего питания система может частично виснуть. Перестает работать тач и кнопки, -но анимация на экране может продолжаться. Если экран был погашен, то включить его кнопкой power невозможно. -Это, видимо, связано с переводом в suspend процессов с определенным UID. UID соответствует приложению или -системному сервису. По UID android определяет политику power saving. -Так же возможно, что глюк связан с кривым драйвером сотового интерфейса от китайцев, поскольку при использовании -wifi такого не наблюдается. suspend обработчика nfqueue на обычном linux не вызывает подобных фатальных последствий. -Изменение UID на низкий (--uid 1 подойдет) позволяет решить эту проблему. -Глюк был замечен на android 8.1 на девайсе , основанном на платформе mediatek. +Я не проверял не прибивают ли новые андроиды iptables по своей прихоти в процессе работы +или при подключении/отключении wifi, mobile data, ... Ответ на вопрос куда поместить tpws на android без рута, чтобы потом его запускать из приложений. Файл заливаем через adb shell в /data/local/tmp/, лучше всего в субфолдер. diff --git a/init.d/macos/functions b/init.d/macos/functions index ab640f6..fc78b13 100644 --- a/init.d/macos/functions +++ b/init.d/macos/functions @@ -4,14 +4,11 @@ . "$ZAPRET_BASE/config" . "$ZAPRET_BASE/common/base.sh" . "$ZAPRET_BASE/common/pf.sh" +. "$ZAPRET_BASE/common/list.sh" IPSET_DIR=$ZAPRET_BASE/ipset . "$IPSET_DIR/def.sh" -HOSTLIST="$ZHOSTLIST.gz" -[ -f "$HOSTLIST" ] || HOSTLIST="$ZHOSTLIST" -[ -f "$HOSTLIST" ] || HOSTLIST="$ZUSERLIST" - PIDDIR=/var/run [ -n "$TPPORT" ] || TPPORT=988 [ -n "$WS_USER" ] || WS_USER=daemon @@ -61,12 +58,6 @@ do_daemon() on_off_function run_daemon stop_daemon "$@" } -filter_apply_hostlist_target() -{ - # $1 - var name of tpws or nfqws params - [ "$MODE_FILTER" = "hostlist" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST\"" -} - tpws_apply_binds() { local o diff --git a/init.d/openwrt/zapret b/init.d/openwrt/zapret index 86b53d3..ecf12ba 100755 --- a/init.d/openwrt/zapret +++ b/init.d/openwrt/zapret @@ -43,9 +43,6 @@ PIDDIR=/var/run NFQWS_OPT_BASE="--user=$WS_USER --dpi-desync-fwmark=$DESYNC_MARK" [ -n "$TPWS" ] || TPWS="$ZAPRET_BASE/tpws/tpws" -HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts.txt.gz" -[ -f "$HOSTLIST" ] || HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts.txt" -[ -f "$HOSTLIST" ] || HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts-user.txt" TPWS_OPT_BASE="--user=$WS_USER" TPWS_OPT_BASE4="--bind-addr=$TPWS_LOCALHOST4" TPWS_OPT_BASE6="--bind-addr=::1" @@ -100,12 +97,6 @@ stop_tpws() } -filter_apply_hostlist_target() -{ - # $1 - var name of tpws or nfqws params - [ "$MODE_FILTER" = "hostlist" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST\"" -} - tpws_apply_socks_binds() { local o diff --git a/init.d/sysv/functions b/init.d/sysv/functions index ed84af4..726668c 100644 --- a/init.d/sysv/functions +++ b/init.d/sysv/functions @@ -9,6 +9,7 @@ . "$ZAPRET_BASE/common/ipt.sh" . "$ZAPRET_BASE/common/nft.sh" . "$ZAPRET_BASE/common/linux_fw.sh" +. "$ZAPRET_BASE/common/list.sh" user_exists() @@ -74,9 +75,6 @@ NFQWS_OPT_DESYNC_HTTPS6="${NFQWS_OPT_DESYNC_HTTPS6:-$NFQWS_OPT_DESYNC_HTTPS}" [ -n "$TPPORT" ] || TPPORT=988 [ -n "$TPWS" ] || TPWS="$ZAPRET_BASE/tpws/tpws" TPWS_LOCALHOST4=127.0.0.127 -HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts.txt.gz" -[ -f "$HOSTLIST" ] || HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts.txt" -[ -f "$HOSTLIST" ] || HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts-user.txt" TPWS_OPT_BASE="$USEROPT" TPWS_OPT_BASE4="--bind-addr=$TPWS_LOCALHOST4" @@ -145,12 +143,6 @@ nft_fill_ifsets_overload() } -filter_apply_hostlist_target() -{ - # $1 - var name of tpws or nfqws params - [ "$MODE_FILTER" = "hostlist" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST\"" -} - run_daemon() { # $1 - daemon number : 1,2,3,... diff --git a/ipset/get_antizapret_domains.sh b/ipset/get_antizapret_domains.sh index b1cbe4c..b0e669e 100755 --- a/ipset/get_antizapret_domains.sh +++ b/ipset/get_antizapret_domains.sh @@ -21,24 +21,13 @@ curl -H "Accept-Encoding: gzip" -k --fail --max-time 600 --connect-timeout 5 --r exit 2 } -composite_list() -{ - # combine reestr and user list - if [ -f "$ZUSERLIST_EXCLUDE" ]; then - nice -n 5 $GREP -xvFf "$ZUSERLIST_EXCLUDE" "$ZDOM" - else - cat "$ZDOM" - fi - [ -f "$ZUSERLIST" ] && $AWK '{ print tolower($0) }' <"$ZUSERLIST" -} - dlsize=$(LANG=C wc -c "$ZDOM" | xargs | cut -f 1 -d ' ') if test $dlsize -lt 102400; then echo list file is too small. can be bad. exit 2 fi -composite_list | sort -u | zz "$ZHOSTLIST" +sort -u "$ZDOM" | zz "$ZHOSTLIST" rm -f "$ZDOM" diff --git a/ipset/get_reestr_hostlist.sh b/ipset/get_reestr_hostlist.sh index bab1818..77ec571 100755 --- a/ipset/get_reestr_hostlist.sh +++ b/ipset/get_reestr_hostlist.sh @@ -26,24 +26,13 @@ reestr_list() LANG=C cut -s -f2 -d';' "$ZREESTR" | LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }' } -composite_list() -{ - # combine reestr and user list - if [ -f "$ZUSERLIST_EXCLUDE" ]; then - reestr_list | nice -n 5 $GREP -xvFf "$ZUSERLIST_EXCLUDE" - else - reestr_list - fi - [ -f "$ZUSERLIST" ] && $AWK '{ print tolower($0) }' <"$ZUSERLIST" -} - dlsize=$(LANG=C wc -c "$ZREESTR" | xargs | cut -f 1 -d ' ') if test $dlsize -lt 204800; then echo list file is too small. can be bad. exit 2 fi -composite_list | sort -u | zz "$ZHOSTLIST" +reestr_list | sort -u | zz "$ZHOSTLIST" rm -f "$ZREESTR"