launch system: support separate and multiple hostlists

This commit is contained in:
bol-van 2022-07-27 16:35:05 +03:00
parent 895af0f629
commit 4347cce3b6
9 changed files with 95 additions and 84 deletions

31
common/list.sh Normal file
View File

@ -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\""
}

View File

@ -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)

View File

@ -174,7 +174,8 @@ nfqws takes the following parameters:
--dpi-desync-fake-quic=<filename> ; file containing fake QUIC Initial
--dpi-desync-fake-unknown-udp=<filename> ; 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=<filename> ; apply fooling only to the listed hosts (one host per line, subdomains auto apply)
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude=<filename> ; 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=<sec> ; if local leg sends something and closes and remote leg is still connecting then cancel connection attempt after N seconds
--hostlist=<filename> ; only act on host in the list (one host per line, subdomains auto apply, gzip lists supported)
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude=<filename> ; 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=<numeric_offset> ; 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 :

View File

@ -1,4 +1,4 @@
zapret v.47
zapret v.48
English
-------
@ -226,7 +226,8 @@ nfqws
--dpi-desync-fake-unknown-udp=<filename> ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--hostlist=<filename> ; применять дурение только к хостам из листа
--hostlist=<filename> ; применять дурение только к хостам из листа. может быть множество листов, они обьединяются. пустой обший лист = его отсутствие
--hostlist-exclude=<filename> ; не применять дурение к хостам из листа. может быть множество листов, они обьединяются
Параметры манипуляции могут сочетаться в любых комбинациях.
@ -586,11 +587,12 @@ tpws - это transparent proxy.
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
; в файле должен быть хост на каждой строке.
; список читается 1 раз при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
; для списка РКН может потребоваться система с 128 Mb памяти !
; расчитывайте требование RAM для процесса как 3-5 кратный размер файла списка.
; по сигналу HUP список будет перечитан при следующем принятом соединении
; список может быть запакован в gzip. формат автоматически распознается и разжимается
; списков может быть множество, они обьединяются. пустой общий лист = его отсутствие
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов, они обьединяются
Параметры манипуляции могут сочетаться в любых комбинациях.
@ -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/, лучше всего в субфолдер.

View File

@ -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

View File

@ -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

View File

@ -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,...

View File

@ -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"

View File

@ -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"