mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-30 05:50:53 +03:00
Compare commits
13 Commits
1fdf5477b4
...
bb74fa765a
Author | SHA1 | Date | |
---|---|---|---|
|
bb74fa765a | ||
|
ee5d4c5017 | ||
|
d04eb28c7f | ||
|
ce2a51a137 | ||
|
4f37c19771 | ||
|
9d43dfdc71 | ||
|
b176af43a4 | ||
|
a6ef91124e | ||
|
1a722c1b78 | ||
|
2452a529eb | ||
|
daac1d2127 | ||
|
acfd844a49 | ||
|
2464d27550 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,4 +1,5 @@
|
|||||||
readonly HOSTLIST_MARKER="<HOSTLIST>"
|
readonly HOSTLIST_MARKER="<HOSTLIST>"
|
||||||
|
readonly HOSTLIST_NOAUTO_MARKER="<HOSTLIST_NOAUTO>"
|
||||||
|
|
||||||
find_hostlists()
|
find_hostlists()
|
||||||
{
|
{
|
||||||
@ -24,10 +25,9 @@ filter_apply_hostlist_target()
|
|||||||
{
|
{
|
||||||
# $1 - var name of tpws or nfqws params
|
# $1 - var name of tpws or nfqws params
|
||||||
|
|
||||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7
|
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parmNA
|
||||||
eval v="\$$1"
|
eval v="\$$1"
|
||||||
contains "$v" "$HOSTLIST_MARKER" &&
|
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
|
||||||
{
|
|
||||||
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
|
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
|
||||||
{
|
{
|
||||||
find_hostlists
|
find_hostlists
|
||||||
@ -40,13 +40,16 @@ filter_apply_hostlist_target()
|
|||||||
parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
|
parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
|
||||||
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
|
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
|
||||||
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
|
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
|
||||||
|
parm8="--hostlist=$HOSTLIST_AUTO"
|
||||||
}
|
}
|
||||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}"
|
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}"
|
||||||
|
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm8:+ $parm8}"
|
||||||
}
|
}
|
||||||
|
v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")"
|
||||||
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"
|
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"
|
||||||
[ "$MODE_FILTER" = autohostlist -a "$AUTOHOSTLIST_DEBUGLOG" = 1 ] && {
|
[ "$MODE_FILTER" = autohostlist -a "$AUTOHOSTLIST_DEBUGLOG" = 1 ] && {
|
||||||
v="$v --hostlist-auto-debug=$HOSTLIST_AUTO_DEBUGLOG"
|
v="$v --hostlist-auto-debug=$HOSTLIST_AUTO_DEBUGLOG"
|
||||||
}
|
}
|
||||||
eval $1=\""$v"\"
|
eval $1=\""$v"\"
|
||||||
}
|
fi
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,9 @@ DESYNC_MARK_POSTNAT=0x20000000
|
|||||||
TPWS_SOCKS_ENABLE=0
|
TPWS_SOCKS_ENABLE=0
|
||||||
# tpws socks listens on this port on localhost and LAN interfaces
|
# tpws socks listens on this port on localhost and LAN interfaces
|
||||||
TPPORT_SOCKS=987
|
TPPORT_SOCKS=987
|
||||||
# use <HOSTLIST> placeholders to engage standard hostlists and autohostlist in ipset dir
|
# use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir
|
||||||
# they are replaced to empty string if MODE_FILTER does not satisfy
|
# 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="
|
TPWS_SOCKS_OPT="
|
||||||
--filter-tcp=80 --methodeol <HOSTLIST> --new
|
--filter-tcp=80 --methodeol <HOSTLIST> --new
|
||||||
--filter-tcp=443 --split-tls=sni --disorder <HOSTLIST>
|
--filter-tcp=443 --split-tls=sni --disorder <HOSTLIST>
|
||||||
@ -59,8 +60,9 @@ TPWS_SOCKS_OPT="
|
|||||||
|
|
||||||
TPWS_ENABLE=0
|
TPWS_ENABLE=0
|
||||||
TPWS_PORTS=80,443
|
TPWS_PORTS=80,443
|
||||||
# use <HOSTLIST> placeholders to engage standard hostlists and autohostlist in ipset dir
|
# use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir
|
||||||
# they are replaced to empty string if MODE_FILTER does not satisfy
|
# 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="
|
TPWS_OPT="
|
||||||
--filter-tcp=80 --methodeol <HOSTLIST> --new
|
--filter-tcp=80 --methodeol <HOSTLIST> --new
|
||||||
--filter-tcp=443 --split-tls=sni --disorder <HOSTLIST>
|
--filter-tcp=443 --split-tls=sni --disorder <HOSTLIST>
|
||||||
@ -83,12 +85,13 @@ NFQWS_UDP_PKT_IN=0
|
|||||||
# this mode can be very CPU consuming. enable with care !
|
# this mode can be very CPU consuming. enable with care !
|
||||||
#NFQWS_PORTS_TCP_KEEPALIVE=80
|
#NFQWS_PORTS_TCP_KEEPALIVE=80
|
||||||
#NFQWS_PORTS_UDP_KEEPALIVE=
|
#NFQWS_PORTS_UDP_KEEPALIVE=
|
||||||
# use <HOSTLIST> placeholders to engage standard hostlists and autohostlist in ipset dir
|
# use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir
|
||||||
# they are replaced to empty string if MODE_FILTER does not satisfy
|
# 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="
|
NFQWS_OPT="
|
||||||
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
||||||
--filter-tcp=443 --dpi-desync=fake,disorder2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
--filter-tcp=443 --dpi-desync=fake,disorder2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
||||||
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST>
|
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST_NOAUTO>
|
||||||
"
|
"
|
||||||
|
|
||||||
# none,ipset,hostlist,autohostlist
|
# none,ipset,hostlist,autohostlist
|
||||||
|
@ -346,3 +346,8 @@ v67:
|
|||||||
|
|
||||||
mdig: --dns-make-query, --dns-parse-query for side-channel resolving (DoH)
|
mdig: --dns-make-query, --dns-parse-query for side-channel resolving (DoH)
|
||||||
blockcheck: use DoH resolvers if DNS spoof is detected
|
blockcheck: use DoH resolvers if DNS spoof is detected
|
||||||
|
blockcheck: restring fooling to testing domain's IPs
|
||||||
|
nfqws,tpws: internal hostlist deduplication to save RAM
|
||||||
|
nfqws,tpws: hostlist/ipset auto reload on file change. no more HUP.
|
||||||
|
nfqws,tpws: --filter-tcp, --filter-udp take comma separated port range list
|
||||||
|
config: <HOSTLIST_NOAUTO> marker
|
||||||
|
@ -111,27 +111,31 @@ badseq может работать только на https и не работа
|
|||||||
с использованием мультистратегии. Как работают мультистратегии описано в readme.txt.
|
с использованием мультистратегии. Как работают мультистратегии описано в readme.txt.
|
||||||
|
|
||||||
Если кратко, то обычно параметры конструируются так :
|
Если кратко, то обычно параметры конструируются так :
|
||||||
"--filter-udp=443 'параметры для quic' <HOSTLIST> --new
|
"--filter-udp=443 'параметры для quic' <HOSTLIST_NOAUTO> --new
|
||||||
--filter-tcp=80-443 'обьединенные параметры для http и https' <HOSTLIST>"
|
--filter-tcp=80-443 'обьединенные параметры для http и https' <HOSTLIST>"
|
||||||
|
|
||||||
Или так :
|
Или так :
|
||||||
"--filter-udp=443 "параметры для quic" <HOSTLIST> --new
|
"--filter-udp=443 "параметры для quic" <HOSTLIST_NOAUTO> --new
|
||||||
--filter-tcp=80 'параметры для http' <HOSTLIST> --new
|
--filter-tcp=80 'параметры для http' <HOSTLIST> --new
|
||||||
--filter-tcp=443 'параметры для https' <HOSTLIST>"
|
--filter-tcp=443 'параметры для https' <HOSTLIST>"
|
||||||
|
|
||||||
"<HOSTLIST>" так и пишется. Его не надо на что-то заменять. Это сделают скрипты запуска, если вы выбрали режим
|
"<HOSTLIST>" и "<HOSTLIST_NOAUTO>" так и пишутся. Их не надо на что-то заменять. Это сделают скрипты запуска,
|
||||||
фильтрации по хостлистам, и уберут в противном случае.
|
если вы выбрали режим фильтрации по хостлистам, и уберут в противном случае.
|
||||||
Если для какого-то протокола надо дурить все без стандартного хостлиста - просто уберите оттуда "<HOSTLIST>".
|
Если для какого-то протокола надо дурить все без стандартного хостлиста - просто уберите оттуда "<HOSTLIST>"
|
||||||
|
и "<HOSTLIST_NOAUTO>".
|
||||||
Можно писать свои параметры --hostlist и --hostlist-exclude для дополнительных хостлистов
|
Можно писать свои параметры --hostlist и --hostlist-exclude для дополнительных хостлистов
|
||||||
или в профилях специализаций под конкретный ресурс. В последнем случае стандартный хостлист там не нужен.
|
или в профилях специализаций под конкретный ресурс. В последнем случае стандартный хостлист там не нужен.
|
||||||
Следует избегать указания собственных параметров --hostlist на листы из директории ipset.
|
Следует избегать указания собственных параметров --hostlist на листы из директории ipset.
|
||||||
Эта логика включена в "<HOSTLIST>".
|
Эта логика включена в "<HOSTLIST>" и "<HOSTLIST_NOAUTO>".
|
||||||
|
Отличие "<HOSTLIST_NOAUTO>" в том, что стандартный автолист по этому профилю используется как обычный,
|
||||||
|
то есть без автоматического добавления доменов. Однако, добавления в других профилях автоматически
|
||||||
|
отражаются во всех остальных.
|
||||||
|
|
||||||
Если стратегии отличаются по версии ip протокола, и вы не можете их обьединить, фильтр пишется так :
|
Если стратегии отличаются по версии ip протокола, и вы не можете их обьединить, фильтр пишется так :
|
||||||
"--filter-l3=ipv4 --filter-udp=443 "параметры для quic ipv4" <HOSTLIST> --new
|
"--filter-l3=ipv4 --filter-udp=443 "параметры для quic ipv4" <HOSTLIST_NOAUTO> --new
|
||||||
--filter-l3=ipv4 --filter-tcp=80 'параметры для http ipv4' <HOSTLIST> --new
|
--filter-l3=ipv4 --filter-tcp=80 'параметры для http ipv4' <HOSTLIST> --new
|
||||||
--filter-l3=ipv4 --filter-tcp=443 'параметры для https ipv4' <HOSTLIST> --new
|
--filter-l3=ipv4 --filter-tcp=443 'параметры для https ipv4' <HOSTLIST> --new
|
||||||
--filter-l3=ipv6 --filter-udp=443 "параметры для quic ipv6" <HOSTLIST> --new
|
--filter-l3=ipv6 --filter-udp=443 "параметры для quic ipv6" <HOSTLIST_NOAUTO> --new
|
||||||
--filter-l3=ipv6 --filter-tcp=80 'параметры для http ipv6' <HOSTLIST> --new
|
--filter-l3=ipv6 --filter-tcp=80 'параметры для http ipv6' <HOSTLIST> --new
|
||||||
--filter-l3=ipv6 --filter-tcp=443 'параметры для https ipv6' <HOSTLIST>"
|
--filter-l3=ipv6 --filter-tcp=443 'параметры для https ipv6' <HOSTLIST>"
|
||||||
|
|
||||||
|
@ -209,8 +209,8 @@ nfqws takes the following parameters:
|
|||||||
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives
|
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives
|
||||||
--new ; begin new strategy
|
--new ; begin new strategy
|
||||||
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
|
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
|
||||||
--filter-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp.
|
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported.
|
||||||
--filter-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp.
|
--filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported.
|
||||||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
|
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
|
||||||
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
||||||
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
||||||
@ -642,7 +642,7 @@ tpws is transparent proxy.
|
|||||||
|
|
||||||
--new ; begin new strategy
|
--new ; begin new strategy
|
||||||
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
|
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
|
||||||
--filter-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation
|
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. comma separated list supported.
|
||||||
--filter-l7=[http|tls|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
|
--filter-l7=[http|tls|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
|
||||||
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
||||||
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
||||||
@ -854,7 +854,7 @@ If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Ju
|
|||||||
|
|
||||||
Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
|
Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
|
||||||
|
|
||||||
tpws and nfqws reread lists on HUP signal.
|
tpws and nfqws automatically reload lists if their modification date is changed.
|
||||||
|
|
||||||
When filtering by domain name, daemons should run without filtering by ipset.
|
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 !
|
When using large regulator lists estimate the amount of RAM on the router !
|
||||||
@ -864,7 +864,7 @@ When using large regulator lists estimate the amount of RAM on the router !
|
|||||||
This mode analyzes both client requests and server replies.
|
This mode analyzes both client requests and server replies.
|
||||||
If a host is not in any list and a situation similar to block occurs host is automatically added to the special list both in memory and file.
|
If a host is not in any list and a situation similar to block occurs host is automatically added to the special list both in memory and file.
|
||||||
Use exclude hostlist to prevent autohostlist triggering.
|
Use exclude hostlist to prevent autohostlist triggering.
|
||||||
If it did happen - delete the undesired record from the file and restart tpws/nfqws or send them SIGHUP to force lists reload.
|
If it did happen - delete the undesired record from the file.
|
||||||
|
|
||||||
In case of nfqws it's required to redirect both incoming and outgoing traffic to the queue.
|
In case of nfqws it's required to redirect both incoming and outgoing traffic to the queue.
|
||||||
It's strongly recommended to use connbytes filter or nfqws will process gigabytes of incoming traffic.
|
It's strongly recommended to use connbytes filter or nfqws will process gigabytes of incoming traffic.
|
||||||
@ -892,7 +892,7 @@ Otherwise it's nothing to lose.
|
|||||||
However false positives still can occur in case target website is behaving abnormally
|
However false positives still can occur in case target website is behaving abnormally
|
||||||
(may be due to DDoS attack or server malfunction). If it happens bypass strategy
|
(may be due to DDoS attack or server malfunction). If it happens bypass strategy
|
||||||
may start to break the website. This situation can only be controlled manually.
|
may start to break the website. This situation can only be controlled manually.
|
||||||
Remove undesired domain from the autohostlist file, restart nfqws/tpws or send them SIGHUP.
|
Remove undesired domain from the autohostlist file.
|
||||||
Use exclude hostlist to prevent further auto additions.
|
Use exclude hostlist to prevent further auto additions.
|
||||||
|
|
||||||
It's possible to use one auto hostlist with multiple processes. All processes check for file modification time.
|
It's possible to use one auto hostlist with multiple processes. All processes check for file modification time.
|
||||||
@ -935,6 +935,8 @@ To use standard updatable hostlists from the `ipset` dir use `<HOSTLIST>` placeh
|
|||||||
with hostlist parameters if `MODE_FILTER` variable enables hostlists and is removed otherwise.
|
with hostlist parameters if `MODE_FILTER` variable enables hostlists and is removed otherwise.
|
||||||
Standard hostlists are expected in final (fallback) strategies closing groups of filter parameters.
|
Standard hostlists are expected in final (fallback) strategies closing groups of filter parameters.
|
||||||
Don't use `<HOSTLIST>` in highly specialized profiles. Use your own filter or hostlist(s).
|
Don't use `<HOSTLIST>` in highly specialized profiles. Use your own filter or hostlist(s).
|
||||||
|
`<HOSTLIST_AUTO>` marker uses standard autohostlist as usual hostlist thus disabling auto additions in this profile.
|
||||||
|
If any other profile adds something this profile accepts the change automatically.
|
||||||
|
|
||||||
|
|
||||||
`tpws` socks proxy mode switch
|
`tpws` socks proxy mode switch
|
||||||
@ -1009,7 +1011,7 @@ It's advised also to remove these ports from `connbytes`-limited interception li
|
|||||||
NFQWS_OPT="
|
NFQWS_OPT="
|
||||||
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
||||||
--filter-tcp=443 --dpi-desync=fake,disorder2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
--filter-tcp=443 --dpi-desync=fake,disorder2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
||||||
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST>
|
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST_NOAUTO>
|
||||||
"
|
"
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -1199,7 +1201,8 @@ Note that DNS check is mostly Russia targeted. It checks several pre-defined blo
|
|||||||
verifies system DNS answers with public DNS answers. Because ISP can block public DNS or redirect any DNS queries
|
verifies system DNS answers with public DNS answers. Because ISP can block public DNS or redirect any DNS queries
|
||||||
to their servers `blockcheck.sh` also checks that all returned answers are unique. Usually if DNS is blocked
|
to their servers `blockcheck.sh` also checks that all returned answers are unique. Usually if DNS is blocked
|
||||||
ISP returns single ip for all blocked domains to redirect you to their "access denied" page.
|
ISP returns single ip for all blocked domains to redirect you to their "access denied" page.
|
||||||
`blockcheck.sh` works in Linux and FreeBSD.
|
DoH servers are used automatically for checks if DNS spoof is detected.
|
||||||
|
`blockcheck.sh` works on all systems supported by `zapret`.
|
||||||
|
|
||||||
### desktop linux system
|
### desktop linux system
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
zapret v.66
|
zapret v.67
|
||||||
|
|
||||||
English
|
English
|
||||||
-------
|
-------
|
||||||
@ -269,8 +269,14 @@ nfqws
|
|||||||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
|
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
|
||||||
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
||||||
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
||||||
--hostlist=<filename> ; применять дурение только к хостам из листа. может быть множество листов, они объединяются. пустой обший лист = его отсутствие
|
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
||||||
--hostlist-exclude=<filename> ; не применять дурение к хостам из листа. может быть множество листов, они объединяются
|
; в файле должен быть хост на каждой строке.
|
||||||
|
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||||||
|
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||||||
|
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
||||||
|
; списков может быть множество. пустой общий лист = его отсутствие
|
||||||
|
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||||||
|
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
|
||||||
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
||||||
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
||||||
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
||||||
@ -278,11 +284,11 @@ nfqws
|
|||||||
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
||||||
--new ; начало новой стратегии
|
--new ; начало новой стратегии
|
||||||
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
||||||
--filter-tcp=[~]port1[-port2] ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp.
|
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую.
|
||||||
--filter-udp=[~]port1[-port2] ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает udp.
|
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает udp. поддерживается список через запятую.
|
||||||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
||||||
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip.
|
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||||
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip.
|
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||||
|
|
||||||
Параметры манипуляции могут сочетаться в любых комбинациях.
|
Параметры манипуляции могут сочетаться в любых комбинациях.
|
||||||
|
|
||||||
@ -773,22 +779,22 @@ tpws - это transparent proxy.
|
|||||||
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
|
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
|
||||||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
||||||
; в файле должен быть хост на каждой строке.
|
; в файле должен быть хост на каждой строке.
|
||||||
; список читается 1 раз при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||||||
; по сигналу HUP список будет перечитан при следующем принятом соединении
|
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||||||
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
||||||
; списков может быть множество, они объединяются. пустой общий лист = его отсутствие
|
; списков может быть множество. пустой общий лист = его отсутствие
|
||||||
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||||||
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов, они объединяются
|
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
|
||||||
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
||||||
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
||||||
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
||||||
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
||||||
--new ; начало новой стратегии
|
--new ; начало новой стратегии
|
||||||
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
||||||
--filter-tcp=[~]port1[-port2] ; фильтр портов tcp для текущей стратегии. ~ означает инверсию.
|
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
|
||||||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
||||||
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip.
|
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||||
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip.
|
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||||
|
|
||||||
|
|
||||||
--debug позволяет выводить подробный лог действий на консоль, в syslog или в файл.
|
--debug позволяет выводить подробный лог действий на консоль, в syslog или в файл.
|
||||||
@ -1154,9 +1160,7 @@ ipset/get_reestr_resolvable_domains.sh
|
|||||||
ipset/get_refilter_domains.sh
|
ipset/get_refilter_domains.sh
|
||||||
- кладется в ipset/zapret-hosts.txt.gz.
|
- кладется в ipset/zapret-hosts.txt.gz.
|
||||||
|
|
||||||
Чтобы обновить списки, перезапускать nfqws или tpws не нужно. Обновляете файлы, затем даете сигнал HUP.
|
При изменении времени модификации файлов списки перечитываются автоматически.
|
||||||
По HUP листы будут перечитаны. Если вдруг какого-то листа не окажется, процесс завершится с ошибкой.
|
|
||||||
Скрипты получения листов из ipset сами выдают HUP в конце.
|
|
||||||
|
|
||||||
При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset.
|
При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset.
|
||||||
tpws и nfqws решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (http, tls, quic).
|
tpws и nfqws решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (http, tls, quic).
|
||||||
@ -1230,7 +1234,7 @@ nfqws и tpws могут сечь варианты 1-3, 4 они не распо
|
|||||||
По логу можно понять как избежать ложных срабатываний и подходит ли вообще вам этот режим.
|
По логу можно понять как избежать ложных срабатываний и подходит ли вообще вам этот режим.
|
||||||
|
|
||||||
Можно использовать один autohostlist с множеством процессов. Все процессы проверяют время модификации файла.
|
Можно использовать один autohostlist с множеством процессов. Все процессы проверяют время модификации файла.
|
||||||
Если файл был изменен в другом процессе, то происходит перечитывание всех include листов, включая autohostlist.
|
Если файл был изменен в другом процессе, происходит его перечитывание.
|
||||||
Все процессы должны работать под одним uid, чтобы были права доступа на файл.
|
Все процессы должны работать под одним uid, чтобы были права доступа на файл.
|
||||||
|
|
||||||
Скрипты zapret ведут autohostlist в ipset/zapret-hosts-auto.txt.
|
Скрипты zapret ведут autohostlist в ipset/zapret-hosts-auto.txt.
|
||||||
@ -1252,6 +1256,7 @@ install_easy.sh при апгрейде zapret сохраняет этот фа
|
|||||||
Если DNS подменяется и провайдер перехватывает обращения к сторонним DNS, настройте dnscrypt.
|
Если DNS подменяется и провайдер перехватывает обращения к сторонним DNS, настройте dnscrypt.
|
||||||
Еще один эффективный вариант - использовать ресолвер от yandex 77.88.8.88 на нестандартном порту 1253.
|
Еще один эффективный вариант - использовать ресолвер от yandex 77.88.8.88 на нестандартном порту 1253.
|
||||||
Многие провайдеры не анализируют обращения к DNS на нестандартных портах.
|
Многие провайдеры не анализируют обращения к DNS на нестандартных портах.
|
||||||
|
blockcheck если видит подмену DNS автоматически переключается на DoH сервера.
|
||||||
|
|
||||||
Следует прогнать blockcheck по нескольким заблокированным сайтам и выявить общий характер блокировок.
|
Следует прогнать blockcheck по нескольким заблокированным сайтам и выявить общий характер блокировок.
|
||||||
Разные сайты могут быть заблокированы по-разному, нужно искать такую технику, которая работает на большинстве.
|
Разные сайты могут быть заблокированы по-разному, нужно искать такую технику, которая работает на большинстве.
|
||||||
@ -1276,6 +1281,24 @@ Blockcheck имеет 3 уровня сканирования.
|
|||||||
standard дает возможность провести исследование как и на что реагирует DPI в плане методов обхода.
|
standard дает возможность провести исследование как и на что реагирует DPI в плане методов обхода.
|
||||||
force дает максимум проверок даже в случаях, когда ресурс работает без обхода или с более простыми стратегиями.
|
force дает максимум проверок даже в случаях, когда ресурс работает без обхода или с более простыми стратегиями.
|
||||||
|
|
||||||
|
Есть ряд других параметров, которые не будут спрашиваться в диалоге, но которые можно переопределить через
|
||||||
|
переменные. Переопределение работает только из рутового шелла. При повышении привилегий через su/sudo переменные теряются.
|
||||||
|
|
||||||
|
DOMAINS - список тестируемых доменов через пробел
|
||||||
|
CURL_MAX_TIME - время таймаута curl в секундах
|
||||||
|
CURL_MAX_TIME_QUIC - время таймаута curl для quic. если не задано, используется значение CURL_MAX_TIME
|
||||||
|
HTTP_PORT, HTTPS_PORT, QUIC_PORT - номера портов для соответствующих протоколов
|
||||||
|
SKIP_DNSCHECK=1 - отказ от проверки DNS
|
||||||
|
SKIP_TPWS=1 - отказ от тестов tpws
|
||||||
|
SKIP_PKTWS=1 - отказ от тестов nfqws/dvtws/winws
|
||||||
|
PKTWS_EXTRA, TPWS_EXTRA - дополнительные параметры nfqws/dvtws/winws и tpws
|
||||||
|
PKTWS_EXTRA_1 .. PKTWS_EXTRA_9, TPWS_EXTRA_1 .. TPWS_EXTRA_9 - отдельно дополнительные параметры, содержащие пробелы
|
||||||
|
SECURE_DNS=0|1 - принудительно выключить или включить DoH
|
||||||
|
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
|
||||||
|
DOH_SERVER - конкретный DoH URL, отказ от поиска
|
||||||
|
|
||||||
|
Пример запуска с переменными : SECURE_DNS=1 SKIP_TPWS=1 CURL_MAX_TIME=1 ./blockcheck.sh
|
||||||
|
|
||||||
СКАН ПОРТОВ
|
СКАН ПОРТОВ
|
||||||
Если в системе присутствует совместимый netcat (ncat от nmap или openbsd ncat. в openwrt по умолчанию нет.),
|
Если в системе присутствует совместимый netcat (ncat от nmap или openbsd ncat. в openwrt по умолчанию нет.),
|
||||||
то выполняется сканирование портов http или https всех IP адресов домена.
|
то выполняется сканирование портов http или https всех IP адресов домена.
|
||||||
@ -1417,6 +1440,9 @@ tpws-socks требует настройки параметров tpws, но н
|
|||||||
группе параметров фильтра. Таких мест может быть несколько.
|
группе параметров фильтра. Таких мест может быть несколько.
|
||||||
Не нужно использовать <HOSTLIST> в узких специализациях и в тех профилях, по которым точно не будет проходить
|
Не нужно использовать <HOSTLIST> в узких специализациях и в тех профилях, по которым точно не будет проходить
|
||||||
трафик с известными протоколами, откуда поддерживается извлечение имени хоста (http, tls, quic).
|
трафик с известными протоколами, откуда поддерживается извлечение имени хоста (http, tls, quic).
|
||||||
|
<HOSTLIST_NOAUTO> - это вариация, при которой стандартный автолист используется как обычный.
|
||||||
|
То есть на этом профиле не происходит автоматическое добавление заблокированных доменов.
|
||||||
|
Но если на другом профиле что-то будет добавлено, то этот профиль примет изменения автоматически.
|
||||||
|
|
||||||
# включение стандартной опции tpws в режиме socks
|
# включение стандартной опции tpws в режиме socks
|
||||||
TPWS_SOCKS_ENABLE=0
|
TPWS_SOCKS_ENABLE=0
|
||||||
@ -1462,7 +1488,7 @@ NFQWS_UDP_PKT_IN=0
|
|||||||
NFQWS_OPT="
|
NFQWS_OPT="
|
||||||
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
||||||
--filter-tcp=443 --dpi-desync=fake,disorder2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
--filter-tcp=443 --dpi-desync=fake,disorder2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
||||||
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST>
|
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST_NOAUTO>
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ blockcheck.sh написан на posix shell и требует некоторы
|
|||||||
Далее все как в *nix : 1 раз ./install_bin.sh , затем ./blockcheck.sh.
|
Далее все как в *nix : 1 раз ./install_bin.sh , затем ./blockcheck.sh.
|
||||||
WSL использовать нельзя, это не то же самое.
|
WSL использовать нельзя, это не то же самое.
|
||||||
|
|
||||||
cygwin для обычной работы winws не нужен. Разве что вы хотите посылать winws SIGHUP для перечитки листов без перезапуска.
|
cygwin для обычной работы winws не нужен.
|
||||||
|
|
||||||
автозапуск winws
|
автозапуск winws
|
||||||
----------------
|
----------------
|
||||||
|
13
ipset/def.sh
13
ipset/def.sh
@ -255,16 +255,3 @@ getipban()
|
|||||||
_get_ipban
|
_get_ipban
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
hup_zapret_daemons()
|
|
||||||
{
|
|
||||||
echo forcing zapret daemons to reload their hostlist
|
|
||||||
if exists killall; then
|
|
||||||
killall -HUP tpws nfqws dvtws 2>/dev/null
|
|
||||||
elif exists pkill; then
|
|
||||||
pkill -HUP ^tpws$ ^nfqws$ ^dvtws$
|
|
||||||
else
|
|
||||||
echo no mass killer available ! cant HUP zapret daemons
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -31,6 +31,4 @@ sort -u "$ZDOM" | zz "$ZHOSTLIST"
|
|||||||
|
|
||||||
rm -f "$ZDOM"
|
rm -f "$ZDOM"
|
||||||
|
|
||||||
hup_zapret_daemons
|
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -9,5 +9,3 @@ IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
|||||||
getexclude
|
getexclude
|
||||||
|
|
||||||
"$IPSET_DIR/create_ipset.sh"
|
"$IPSET_DIR/create_ipset.sh"
|
||||||
|
|
||||||
[ "$MODE_FILTER" = hostlist ] && hup_zapret_daemons
|
|
||||||
|
@ -9,5 +9,3 @@ IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
|||||||
getipban
|
getipban
|
||||||
|
|
||||||
"$IPSET_DIR/create_ipset.sh"
|
"$IPSET_DIR/create_ipset.sh"
|
||||||
|
|
||||||
[ "$MODE_FILTER" = hostlist ] && hup_zapret_daemons
|
|
||||||
|
@ -58,8 +58,6 @@ rm -f "$ZREESTR"
|
|||||||
[ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6"
|
[ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6"
|
||||||
rm -f "$IPB"
|
rm -f "$IPB"
|
||||||
|
|
||||||
hup_zapret_daemons
|
|
||||||
|
|
||||||
ipban_fin
|
ipban_fin
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -34,8 +34,6 @@ dl()
|
|||||||
|
|
||||||
dl "$URL" "$ZHOSTLIST" 65536 67108864
|
dl "$URL" "$ZHOSTLIST" 65536 67108864
|
||||||
|
|
||||||
hup_zapret_daemons
|
|
||||||
|
|
||||||
[ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
[ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||||
[ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
[ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||||
|
|
||||||
|
@ -37,6 +37,4 @@ getipban || FAIL=1
|
|||||||
|
|
||||||
dl "$URL" "$ZHOSTLIST" 32768 4194304
|
dl "$URL" "$ZHOSTLIST" 32768 4194304
|
||||||
|
|
||||||
hup_zapret_daemons
|
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -158,7 +158,7 @@ static bool dp_match(
|
|||||||
if ((dest->sa_family==AF_INET && !dp->filter_ipv4) || (dest->sa_family==AF_INET6 && !dp->filter_ipv6))
|
if ((dest->sa_family==AF_INET && !dp->filter_ipv4) || (dest->sa_family==AF_INET6 && !dp->filter_ipv6))
|
||||||
// L3 filter does not match
|
// L3 filter does not match
|
||||||
return false;
|
return false;
|
||||||
if ((l3proto==IPPROTO_TCP && !pf_in_range(saport(dest), &dp->pf_tcp)) || (l3proto==IPPROTO_UDP && !pf_in_range(saport(dest), &dp->pf_udp)))
|
if ((l3proto==IPPROTO_TCP && !port_filters_in_range(&dp->pf_tcp,saport(dest))) || (l3proto==IPPROTO_UDP && !port_filters_in_range(&dp->pf_udp,saport(dest))))
|
||||||
// L4 filter does not match
|
// L4 filter does not match
|
||||||
return false;
|
return false;
|
||||||
if (dp->filter_l7 && !l7_proto_match(l7proto, dp->filter_l7))
|
if (dp->filter_l7 && !l7_proto_match(l7proto, dp->filter_l7))
|
||||||
|
@ -333,6 +333,11 @@ bool pf_parse(const char *s, port_filter *pf)
|
|||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (!s) return false;
|
if (!s) return false;
|
||||||
|
if (*s=='*' && s[1]==0)
|
||||||
|
{
|
||||||
|
pf->from=1; pf->to=0xFFFF;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (*s=='~')
|
if (*s=='~')
|
||||||
{
|
{
|
||||||
pf->neg=true;
|
pf->neg=true;
|
||||||
|
50
nfq/nfqws.c
50
nfq/nfqws.c
@ -669,6 +669,28 @@ static bool parse_l7_list(char *opt, uint32_t *l7)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool parse_pf_list(char *opt, struct port_filters_head *pfl)
|
||||||
|
{
|
||||||
|
char *e,*p,c;
|
||||||
|
port_filter pf;
|
||||||
|
bool b;
|
||||||
|
|
||||||
|
for (p=opt ; p ; )
|
||||||
|
{
|
||||||
|
if ((e = strchr(p,',')))
|
||||||
|
{
|
||||||
|
c=*e;
|
||||||
|
*e=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
b = pf_parse(p,&pf) && port_filter_add(pfl,&pf);
|
||||||
|
if (e) *e++=c;
|
||||||
|
if (!b) return false;
|
||||||
|
|
||||||
|
p = e;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool wf_make_l3(char *opt, bool *ipv4, bool *ipv6)
|
static bool wf_make_l3(char *opt, bool *ipv4, bool *ipv6)
|
||||||
{
|
{
|
||||||
@ -853,8 +875,8 @@ static void exithelp(void)
|
|||||||
"\nMULTI-STRATEGY:\n"
|
"\nMULTI-STRATEGY:\n"
|
||||||
" --new\t\t\t\t\t\t; begin new strategy\n"
|
" --new\t\t\t\t\t\t; begin new strategy\n"
|
||||||
" --filter-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
" --filter-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||||
" --filter-tcp=[~]port1[-port2]\t\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp.\n"
|
" --filter-tcp=[~]port1[-port2]|*\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
|
||||||
" --filter-udp=[~]port1[-port2]\t\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp.\n"
|
" --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
|
||||||
" --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
" --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
||||||
" --ipset=<filename>\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
" --ipset=<filename>\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||||
" --ipset-exclude=<filename>\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
" --ipset-exclude=<filename>\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||||
@ -1612,22 +1634,24 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 54: /* filter-tcp */
|
case 54: /* filter-tcp */
|
||||||
if (!pf_parse(optarg,&dp->pf_tcp))
|
if (!parse_pf_list(optarg,&dp->pf_tcp))
|
||||||
{
|
|
||||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
|
||||||
exit_clean(1);
|
|
||||||
}
|
|
||||||
// deny udp if not set
|
|
||||||
if (pf_is_empty(&dp->pf_udp)) dp->pf_udp.neg=true;
|
|
||||||
break;
|
|
||||||
case 55: /* filter-udp */
|
|
||||||
if (!pf_parse(optarg,&dp->pf_udp))
|
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
// deny tcp if not set
|
// deny tcp if not set
|
||||||
if (pf_is_empty(&dp->pf_tcp)) dp->pf_tcp.neg=true;
|
if (!port_filters_deny_if_empty(&dp->pf_udp))
|
||||||
|
exit_clean(1);
|
||||||
|
break;
|
||||||
|
case 55: /* filter-udp */
|
||||||
|
if (!parse_pf_list(optarg,&dp->pf_udp))
|
||||||
|
{
|
||||||
|
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
// deny tcp if not set
|
||||||
|
if (!port_filters_deny_if_empty(&dp->pf_tcp))
|
||||||
|
exit_clean(1);
|
||||||
break;
|
break;
|
||||||
case 56: /* filter-l7 */
|
case 56: /* filter-l7 */
|
||||||
if (!parse_l7_list(optarg,&dp->filter_l7))
|
if (!parse_l7_list(optarg,&dp->filter_l7))
|
||||||
|
13
nfq/params.c
13
nfq/params.c
@ -164,6 +164,9 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
|||||||
LIST_INIT(&entry->dp.hl_collection_exclude);
|
LIST_INIT(&entry->dp.hl_collection_exclude);
|
||||||
LIST_INIT(&entry->dp.ips_collection);
|
LIST_INIT(&entry->dp.ips_collection);
|
||||||
LIST_INIT(&entry->dp.ips_collection_exclude);
|
LIST_INIT(&entry->dp.ips_collection_exclude);
|
||||||
|
LIST_INIT(&entry->dp.pf_tcp);
|
||||||
|
LIST_INIT(&entry->dp.pf_udp);
|
||||||
|
|
||||||
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
|
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
|
||||||
entry->dp.desync_skip_nosni = true;
|
entry->dp.desync_skip_nosni = true;
|
||||||
entry->dp.desync_split_pos = 2;
|
entry->dp.desync_split_pos = 2;
|
||||||
@ -211,6 +214,8 @@ static void dp_entry_destroy(struct desync_profile_list *entry)
|
|||||||
hostlist_collection_destroy(&entry->dp.hl_collection_exclude);
|
hostlist_collection_destroy(&entry->dp.hl_collection_exclude);
|
||||||
ipset_collection_destroy(&entry->dp.ips_collection);
|
ipset_collection_destroy(&entry->dp.ips_collection);
|
||||||
ipset_collection_destroy(&entry->dp.ips_collection_exclude);
|
ipset_collection_destroy(&entry->dp.ips_collection_exclude);
|
||||||
|
port_filters_destroy(&entry->dp.pf_tcp);
|
||||||
|
port_filters_destroy(&entry->dp.pf_udp);
|
||||||
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
|
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
@ -223,3 +228,11 @@ void dp_list_destroy(struct desync_profile_list_head *head)
|
|||||||
dp_entry_destroy(entry);
|
dp_entry_destroy(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
|
||||||
|
{
|
||||||
|
struct desync_profile_list *dpl;
|
||||||
|
LIST_FOREACH(dpl, head, next)
|
||||||
|
if (dpl->dp.hostlist_auto)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -65,7 +65,7 @@ struct desync_profile
|
|||||||
int udplen_increment;
|
int udplen_increment;
|
||||||
|
|
||||||
bool filter_ipv4,filter_ipv6;
|
bool filter_ipv4,filter_ipv6;
|
||||||
port_filter pf_tcp,pf_udp;
|
struct port_filters_head pf_tcp,pf_udp;
|
||||||
uint32_t filter_l7; // L7_PROTO_* bits
|
uint32_t filter_l7; // L7_PROTO_* bits
|
||||||
|
|
||||||
// list of pointers to ipsets
|
// list of pointers to ipsets
|
||||||
@ -90,6 +90,7 @@ struct desync_profile_list {
|
|||||||
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
||||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
||||||
void dp_list_destroy(struct desync_profile_list_head *head);
|
void dp_list_destroy(struct desync_profile_list_head *head);
|
||||||
|
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
|
||||||
|
|
||||||
struct params_s
|
struct params_s
|
||||||
{
|
{
|
||||||
|
39
nfq/pools.c
39
nfq/pools.c
@ -448,3 +448,42 @@ bool ipset_collection_is_empty(const struct ipset_collection_head *head)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool port_filter_add(struct port_filters_head *head, const port_filter *pf)
|
||||||
|
{
|
||||||
|
struct port_filter_item *entry = malloc(sizeof(struct port_filter_item));
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
entry->pf = *pf;
|
||||||
|
LIST_INSERT_HEAD(head, entry, next);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
void port_filters_destroy(struct port_filters_head *head)
|
||||||
|
{
|
||||||
|
struct port_filter_item *entry;
|
||||||
|
while ((entry = LIST_FIRST(head)))
|
||||||
|
{
|
||||||
|
LIST_REMOVE(entry, next);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port)
|
||||||
|
{
|
||||||
|
const struct port_filter_item *item;
|
||||||
|
|
||||||
|
if (!LIST_FIRST(head)) return true;
|
||||||
|
LIST_FOREACH(item, head, next)
|
||||||
|
{
|
||||||
|
if (pf_in_range(port, &item->pf))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool port_filters_deny_if_empty(struct port_filters_head *head)
|
||||||
|
{
|
||||||
|
port_filter pf;
|
||||||
|
if (LIST_FIRST(head)) return true;
|
||||||
|
return pf_parse("0",&pf) && port_filter_add(head,&pf);
|
||||||
|
}
|
||||||
|
11
nfq/pools.h
11
nfq/pools.h
@ -130,3 +130,14 @@ struct ipset_item * ipset_collection_add(struct ipset_collection_head *head, str
|
|||||||
void ipset_collection_destroy(struct ipset_collection_head *head);
|
void ipset_collection_destroy(struct ipset_collection_head *head);
|
||||||
struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, const char *filename);
|
struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, const char *filename);
|
||||||
bool ipset_collection_is_empty(const struct ipset_collection_head *head);
|
bool ipset_collection_is_empty(const struct ipset_collection_head *head);
|
||||||
|
|
||||||
|
|
||||||
|
struct port_filter_item {
|
||||||
|
port_filter pf;
|
||||||
|
LIST_ENTRY(port_filter_item) next;
|
||||||
|
};
|
||||||
|
LIST_HEAD(port_filters_head, port_filter_item);
|
||||||
|
bool port_filter_add(struct port_filters_head *head, const port_filter *pf);
|
||||||
|
void port_filters_destroy(struct port_filters_head *head);
|
||||||
|
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
|
||||||
|
bool port_filters_deny_if_empty(struct port_filters_head *head);
|
||||||
|
@ -268,6 +268,11 @@ bool pf_parse(const char *s, port_filter *pf)
|
|||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (!s) return false;
|
if (!s) return false;
|
||||||
|
if (*s=='*' && s[1]==0)
|
||||||
|
{
|
||||||
|
pf->from=1; pf->to=0xFFFF;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (*s=='~')
|
if (*s=='~')
|
||||||
{
|
{
|
||||||
pf->neg=true;
|
pf->neg=true;
|
||||||
|
189
tpws/hostlist.c
189
tpws/hostlist.c
@ -1,7 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "hostlist.h"
|
#include "hostlist.h"
|
||||||
#include "gzip.h"
|
#include "gzip.h"
|
||||||
#include "params.h"
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
// inplace tolower() and add to pool
|
// inplace tolower() and add to pool
|
||||||
@ -97,22 +96,38 @@ bool AppendHostList(strpool **hostlist, const char *filename)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list)
|
static bool LoadHostList(struct hostlist_file *hfile)
|
||||||
{
|
{
|
||||||
struct str_list *file;
|
time_t t = file_mod_time(hfile->filename);
|
||||||
|
if (!t)
|
||||||
if (*hostlist)
|
|
||||||
{
|
{
|
||||||
StrPoolDestroy(hostlist);
|
// stat() error
|
||||||
*hostlist = NULL;
|
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||||
}
|
|
||||||
|
|
||||||
LIST_FOREACH(file, file_list, next)
|
|
||||||
{
|
|
||||||
if (!AppendHostList(hostlist, file->str)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (t==hfile->mod_time) return true; // up to date
|
||||||
|
StrPoolDestroy(&hfile->hostlist);
|
||||||
|
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
||||||
|
{
|
||||||
|
StrPoolDestroy(&hfile->hostlist);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
hfile->mod_time=t;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static bool LoadHostLists(struct hostlist_files_head *list)
|
||||||
|
{
|
||||||
|
bool bres=true;
|
||||||
|
struct hostlist_file *hfile;
|
||||||
|
|
||||||
|
LIST_FOREACH(hfile, list, next)
|
||||||
|
{
|
||||||
|
if (!LoadHostList(hfile))
|
||||||
|
// at least one failed
|
||||||
|
bres=false;
|
||||||
|
}
|
||||||
|
return bres;
|
||||||
|
}
|
||||||
|
|
||||||
bool NonEmptyHostlist(strpool **hostlist)
|
bool NonEmptyHostlist(strpool **hostlist)
|
||||||
{
|
{
|
||||||
@ -120,8 +135,27 @@ bool NonEmptyHostlist(strpool **hostlist)
|
|||||||
return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4);
|
return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void MakeAutolistsNonEmpty()
|
||||||
|
{
|
||||||
|
struct desync_profile_list *dpl;
|
||||||
|
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||||
|
{
|
||||||
|
if (dpl->dp.hostlist_auto)
|
||||||
|
NonEmptyHostlist(&dpl->dp.hostlist_auto->hostlist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SearchHostList(strpool *hostlist, const char *host)
|
bool LoadAllHostLists()
|
||||||
|
{
|
||||||
|
if (!LoadHostLists(¶ms.hostlists))
|
||||||
|
return false;
|
||||||
|
MakeAutolistsNonEmpty();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static bool SearchHostList(strpool *hostlist, const char *host)
|
||||||
{
|
{
|
||||||
if (hostlist)
|
if (hostlist)
|
||||||
{
|
{
|
||||||
@ -130,7 +164,7 @@ bool SearchHostList(strpool *hostlist, const char *host)
|
|||||||
while (p)
|
while (p)
|
||||||
{
|
{
|
||||||
bInHostList = StrPoolCheckStr(hostlist, p);
|
bInHostList = StrPoolCheckStr(hostlist, p);
|
||||||
VPRINT("Hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
|
VPRINT("hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
|
||||||
if (bInHostList) return true;
|
if (bInHostList) return true;
|
||||||
p = strchr(p, '.');
|
p = strchr(p, '.');
|
||||||
if (p) p++;
|
if (p) p++;
|
||||||
@ -139,73 +173,108 @@ bool SearchHostList(strpool *hostlist, const char *host)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool HostlistsReloadCheck(const struct hostlist_collection_head *hostlists)
|
||||||
|
{
|
||||||
|
struct hostlist_item *item;
|
||||||
|
LIST_FOREACH(item, hostlists, next)
|
||||||
|
{
|
||||||
|
if (!LoadHostList(item->hfile))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MakeAutolistsNonEmpty();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool HostlistsReloadCheckForProfile(const struct desync_profile *dp)
|
||||||
|
{
|
||||||
|
return HostlistsReloadCheck(&dp->hl_collection) && HostlistsReloadCheck(&dp->hl_collection_exclude);
|
||||||
|
}
|
||||||
// return : true = apply fooling, false = do not apply
|
// return : true = apply fooling, false = do not apply
|
||||||
static bool HostlistCheck_(strpool *hostlist, strpool *hostlist_exclude, const char *host, bool *excluded)
|
static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, const struct hostlist_collection_head *hostlists_exclude, const char *host, bool *excluded, bool bSkipReloadCheck)
|
||||||
{
|
{
|
||||||
|
struct hostlist_item *item;
|
||||||
|
|
||||||
if (excluded) *excluded = false;
|
if (excluded) *excluded = false;
|
||||||
if (hostlist_exclude)
|
|
||||||
|
if (!bSkipReloadCheck)
|
||||||
|
if (!HostlistsReloadCheck(hostlists) || !HostlistsReloadCheck(hostlists_exclude))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
LIST_FOREACH(item, hostlists_exclude, next)
|
||||||
{
|
{
|
||||||
VPRINT("Checking exclude hostlist\n");
|
VPRINT("[%s] exclude ", item->hfile->filename);
|
||||||
if (SearchHostList(hostlist_exclude, host))
|
if (SearchHostList(item->hfile->hostlist, host))
|
||||||
{
|
{
|
||||||
if (excluded) *excluded = true;
|
if (excluded) *excluded = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hostlist)
|
// old behavior compat: all include lists are empty means check passes
|
||||||
|
if (!hostlist_collection_is_empty(hostlists))
|
||||||
{
|
{
|
||||||
VPRINT("Checking include hostlist\n");
|
LIST_FOREACH(item, hostlists, next)
|
||||||
return SearchHostList(hostlist, host);
|
{
|
||||||
}
|
VPRINT("[%s] include ", item->hfile->filename);
|
||||||
|
if (SearchHostList(item->hfile->hostlist, host))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadIncludeHostListsForProfile(struct desync_profile *dp)
|
|
||||||
{
|
|
||||||
if (!LoadHostLists(&dp->hostlist, &dp->hostlist_files))
|
|
||||||
return false;
|
return false;
|
||||||
if (*dp->hostlist_auto_filename)
|
|
||||||
{
|
|
||||||
dp->hostlist_auto_mod_time = file_mod_time(dp->hostlist_auto_filename);
|
|
||||||
NonEmptyHostlist(&dp->hostlist);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HostlistCheck(struct desync_profile *dp, const char *host, bool *excluded)
|
|
||||||
|
// return : true = apply fooling, false = do not apply
|
||||||
|
bool HostlistCheck(const struct desync_profile *dp, const char *host, bool *excluded, bool bSkipReloadCheck)
|
||||||
{
|
{
|
||||||
VPRINT("* hostlist check for profile %d\n",dp->n);
|
VPRINT("* hostlist check for profile %d\n",dp->n);
|
||||||
if (*dp->hostlist_auto_filename)
|
return HostlistCheck_(&dp->hl_collection, &dp->hl_collection_exclude, host, excluded, bSkipReloadCheck);
|
||||||
{
|
|
||||||
time_t t = file_mod_time(dp->hostlist_auto_filename);
|
|
||||||
if (t!=dp->hostlist_auto_mod_time)
|
|
||||||
{
|
|
||||||
DLOG_CONDUP("Autohostlist '%s' from profile %d was modified. Reloading include hostlists for this profile.\n",dp->hostlist_auto_filename, dp->n);
|
|
||||||
if (!LoadIncludeHostListsForProfile(dp))
|
|
||||||
{
|
|
||||||
// what will we do without hostlist ?? sure, gonna die
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
dp->hostlist_auto_mod_time = t;
|
|
||||||
NonEmptyHostlist(&dp->hostlist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return HostlistCheck_(dp->hostlist, dp->hostlist_exclude, host, excluded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadIncludeHostLists()
|
|
||||||
|
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
|
||||||
{
|
{
|
||||||
struct desync_profile_list *dpl;
|
struct hostlist_file *hfile;
|
||||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
if (!(hfile=hostlist_files_search(hostlists, filename)))
|
||||||
if (!LoadIncludeHostListsForProfile(&dpl->dp))
|
if (!(hfile=hostlist_files_add(hostlists, filename)))
|
||||||
return false;
|
return NULL;
|
||||||
return true;
|
if (!hostlist_collection_search(hl_collection, filename))
|
||||||
|
if (!hostlist_collection_add(hl_collection, hfile))
|
||||||
|
return NULL;
|
||||||
|
return hfile;
|
||||||
}
|
}
|
||||||
bool LoadExcludeHostLists()
|
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||||
{
|
{
|
||||||
struct desync_profile_list *dpl;
|
if (!file_mod_time(filename))
|
||||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
{
|
||||||
if (!LoadHostLists(&dpl->dp.hostlist_exclude, &dpl->dp.hostlist_exclude_files))
|
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
|
||||||
return false;
|
return NULL;
|
||||||
return true;
|
}
|
||||||
|
return RegisterHostlist_(
|
||||||
|
¶ms.hostlists,
|
||||||
|
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,
|
||||||
|
filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostlistsDebug()
|
||||||
|
{
|
||||||
|
if (!params.debug) return;
|
||||||
|
|
||||||
|
struct hostlist_file *hfile;
|
||||||
|
struct desync_profile_list *dpl;
|
||||||
|
struct hostlist_item *hl_item;
|
||||||
|
|
||||||
|
LIST_FOREACH(hfile, ¶ms.hostlists, next)
|
||||||
|
VPRINT("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
|
||||||
|
|
||||||
|
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||||
|
{
|
||||||
|
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
|
||||||
|
if (hl_item->hfile!=dpl->dp.hostlist_auto)
|
||||||
|
VPRINT("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||||
|
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
|
||||||
|
VPRINT("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||||
|
if (dpl->dp.hostlist_auto)
|
||||||
|
VPRINT("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
|
||||||
bool AppendHostList(strpool **hostlist, const char *filename);
|
bool AppendHostList(strpool **hostlist, const char *filename);
|
||||||
bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list);
|
bool LoadAllHostLists();
|
||||||
bool LoadIncludeHostLists();
|
|
||||||
bool LoadExcludeHostLists();
|
|
||||||
bool NonEmptyHostlist(strpool **hostlist);
|
bool NonEmptyHostlist(strpool **hostlist);
|
||||||
bool SearchHostList(strpool *hostlist, const char *host);
|
|
||||||
// return : true = apply fooling, false = do not apply
|
// return : true = apply fooling, false = do not apply
|
||||||
bool HostlistCheck(struct desync_profile *dp,const char *host, bool *excluded);
|
bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *excluded, bool bSkipReloadCheck);
|
||||||
|
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||||
|
bool HostlistsReloadCheckForProfile(const struct desync_profile *dp);
|
||||||
|
void HostlistsDebug();
|
||||||
|
154
tpws/ipset.c
154
tpws/ipset.c
@ -3,6 +3,7 @@
|
|||||||
#include "gzip.h"
|
#include "gzip.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
|
|
||||||
// inplace tolower() and add to pool
|
// inplace tolower() and add to pool
|
||||||
static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||||
{
|
{
|
||||||
@ -116,37 +117,45 @@ static bool AppendIpset(ipset *ips, const char *filename)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadIpsets(ipset *ips, struct str_list_head *file_list)
|
static bool LoadIpset(struct ipset_file *hfile)
|
||||||
{
|
{
|
||||||
struct str_list *file;
|
time_t t = file_mod_time(hfile->filename);
|
||||||
|
if (!t)
|
||||||
ipsetDestroy(ips);
|
|
||||||
|
|
||||||
LIST_FOREACH(file, file_list, next)
|
|
||||||
{
|
{
|
||||||
if (!AppendIpset(ips, file->str)) return false;
|
// stat() error
|
||||||
}
|
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (t==hfile->mod_time) return true; // up to date
|
||||||
bool LoadIncludeIpsets()
|
ipsetDestroy(&hfile->ipset);
|
||||||
|
if (!AppendIpset(&hfile->ipset, hfile->filename))
|
||||||
{
|
{
|
||||||
struct desync_profile_list *dpl;
|
ipsetDestroy(&hfile->ipset);
|
||||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
|
||||||
if (!LoadIpsets(&dpl->dp.ips, &dpl->dp.ipset_files))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
hfile->mod_time=t;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool LoadExcludeIpsets()
|
static bool LoadIpsets(struct ipset_files_head *list)
|
||||||
{
|
{
|
||||||
struct desync_profile_list *dpl;
|
bool bres=true;
|
||||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
struct ipset_file *hfile;
|
||||||
if (!LoadIpsets(&dpl->dp.ips_exclude, &dpl->dp.ipset_exclude_files))
|
|
||||||
return false;
|
LIST_FOREACH(hfile, list, next)
|
||||||
return true;
|
{
|
||||||
|
if (!LoadIpset(hfile))
|
||||||
|
// at least one failed
|
||||||
|
bres=false;
|
||||||
|
}
|
||||||
|
return bres;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchIpset(const ipset *ips, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
bool LoadAllIpsets()
|
||||||
|
{
|
||||||
|
return LoadIpsets(¶ms.ipsets);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool SearchIpset(const ipset *ips, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
||||||
{
|
{
|
||||||
char s_ip[40];
|
char s_ip[40];
|
||||||
bool bInSet=false;
|
bool bInSet=false;
|
||||||
@ -172,24 +181,109 @@ bool SearchIpset(const ipset *ips, const struct in_addr *ipv4, const struct in6_
|
|||||||
return bInSet;
|
return bInSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IpsetCheck_(const ipset *ips, const ipset *ips_exclude, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
static bool IpsetsReloadCheck(const struct ipset_collection_head *ipsets)
|
||||||
{
|
{
|
||||||
if (!IPSET_EMPTY(ips_exclude))
|
struct ipset_item *item;
|
||||||
|
LIST_FOREACH(item, ipsets, next)
|
||||||
{
|
{
|
||||||
VPRINT("exclude ");
|
if (!LoadIpset(item->hfile))
|
||||||
if (SearchIpset(ips_exclude, ipv4, ipv6))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!IPSET_EMPTY(ips))
|
return true;
|
||||||
|
}
|
||||||
|
bool IpsetsReloadCheckForProfile(const struct desync_profile *dp)
|
||||||
{
|
{
|
||||||
VPRINT("include ");
|
return IpsetsReloadCheck(&dp->ips_collection) && IpsetsReloadCheck(&dp->ips_collection_exclude);
|
||||||
return SearchIpset(ips, ipv4, ipv6);
|
}
|
||||||
|
|
||||||
|
static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ipset_collection_head *ips_exclude, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
||||||
|
{
|
||||||
|
struct ipset_item *item;
|
||||||
|
|
||||||
|
if (!IpsetsReloadCheck(ips) || !IpsetsReloadCheck(ips_exclude))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
LIST_FOREACH(item, ips_exclude, next)
|
||||||
|
{
|
||||||
|
VPRINT("[%s] exclude ",item->hfile->filename);
|
||||||
|
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// old behavior compat: all include lists are empty means check passes
|
||||||
|
if (!ipset_collection_is_empty(ips))
|
||||||
|
{
|
||||||
|
LIST_FOREACH(item, ips, next)
|
||||||
|
{
|
||||||
|
VPRINT("[%s] include ",item->hfile->filename);
|
||||||
|
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IpsetCheck(struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
||||||
{
|
{
|
||||||
if (!PROFILE_IPSETS_EMPTY(dp)) VPRINT("* ipset check for profile %d\n",dp->n);
|
if (PROFILE_IPSETS_EMPTY(dp)) return true;
|
||||||
return IpsetCheck_(&dp->ips,&dp->ips_exclude,ipv4,ipv6);
|
VPRINT("* ipset check for profile %d\n",dp->n);
|
||||||
|
return IpsetCheck_(&dp->ips_collection,&dp->ips_collection_exclude,ipv4,ipv6);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
|
||||||
|
{
|
||||||
|
struct ipset_file *hfile;
|
||||||
|
if (!(hfile=ipset_files_search(ipsets, filename)))
|
||||||
|
if (!(hfile=ipset_files_add(ipsets, filename)))
|
||||||
|
return NULL;
|
||||||
|
if (!ipset_collection_search(ips_collection, filename))
|
||||||
|
if (!ipset_collection_add(ips_collection, hfile))
|
||||||
|
return NULL;
|
||||||
|
return hfile;
|
||||||
|
}
|
||||||
|
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||||
|
{
|
||||||
|
if (!file_mod_time(filename))
|
||||||
|
{
|
||||||
|
DLOG_ERR("cannot access ipset file '%s'\n",filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return RegisterIpset_(
|
||||||
|
¶ms.ipsets,
|
||||||
|
bExclude ? &dp->ips_collection_exclude : &dp->ips_collection,
|
||||||
|
filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *dbg_ipset_fill(const ipset *ips)
|
||||||
|
{
|
||||||
|
if (ips->ips4)
|
||||||
|
if (ips->ips6)
|
||||||
|
return "ipv4+ipv6";
|
||||||
|
else
|
||||||
|
return "ipv4";
|
||||||
|
else
|
||||||
|
if (ips->ips6)
|
||||||
|
return "ipv6";
|
||||||
|
else
|
||||||
|
return "empty";
|
||||||
|
}
|
||||||
|
void IpsetsDebug()
|
||||||
|
{
|
||||||
|
if (!params.debug) return;
|
||||||
|
|
||||||
|
struct ipset_file *hfile;
|
||||||
|
struct desync_profile_list *dpl;
|
||||||
|
struct ipset_item *ips_item;
|
||||||
|
|
||||||
|
LIST_FOREACH(hfile, ¶ms.ipsets, next)
|
||||||
|
VPRINT("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
|
||||||
|
|
||||||
|
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||||
|
{
|
||||||
|
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next)
|
||||||
|
VPRINT("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||||
|
LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next)
|
||||||
|
VPRINT("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "params.h"
|
#include "params.h"
|
||||||
#include "pools.h"
|
#include "pools.h"
|
||||||
|
|
||||||
bool LoadIncludeIpsets();
|
bool LoadAllIpsets();
|
||||||
bool LoadExcludeIpsets();
|
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6);
|
||||||
bool SearchIpset(const ipset *ips, const struct in_addr *ipv4, const struct in6_addr *ipv6);
|
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||||
bool IpsetCheck(struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6);
|
void IpsetsDebug();
|
||||||
|
@ -145,10 +145,13 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
|||||||
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
|
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
|
||||||
if (!entry) return NULL;
|
if (!entry) return NULL;
|
||||||
|
|
||||||
LIST_INIT(&entry->dp.hostlist_files);
|
LIST_INIT(&entry->dp.hl_collection);
|
||||||
LIST_INIT(&entry->dp.hostlist_exclude_files);
|
LIST_INIT(&entry->dp.hl_collection_exclude);
|
||||||
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
|
LIST_INIT(&entry->dp.ips_collection);
|
||||||
|
LIST_INIT(&entry->dp.ips_collection_exclude);
|
||||||
|
LIST_INIT(&entry->dp.pf_tcp);
|
||||||
|
|
||||||
|
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
|
||||||
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
|
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
|
||||||
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||||
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||||
@ -167,14 +170,11 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
|||||||
}
|
}
|
||||||
static void dp_entry_destroy(struct desync_profile_list *entry)
|
static void dp_entry_destroy(struct desync_profile_list *entry)
|
||||||
{
|
{
|
||||||
strlist_destroy(&entry->dp.hostlist_files);
|
hostlist_collection_destroy(&entry->dp.hl_collection);
|
||||||
strlist_destroy(&entry->dp.hostlist_exclude_files);
|
hostlist_collection_destroy(&entry->dp.hl_collection_exclude);
|
||||||
strlist_destroy(&entry->dp.ipset_files);
|
ipset_collection_destroy(&entry->dp.ips_collection);
|
||||||
strlist_destroy(&entry->dp.ipset_exclude_files);
|
ipset_collection_destroy(&entry->dp.ips_collection_exclude);
|
||||||
StrPoolDestroy(&entry->dp.hostlist_exclude);
|
port_filters_destroy(&entry->dp.pf_tcp);
|
||||||
StrPoolDestroy(&entry->dp.hostlist);
|
|
||||||
ipsetDestroy(&entry->dp.ips);
|
|
||||||
ipsetDestroy(&entry->dp.ips_exclude);
|
|
||||||
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
|
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
@ -187,11 +187,3 @@ void dp_list_destroy(struct desync_profile_list_head *head)
|
|||||||
dp_entry_destroy(entry);
|
dp_entry_destroy(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
|
|
||||||
{
|
|
||||||
struct desync_profile_list *dpl;
|
|
||||||
LIST_FOREACH(dpl, head, next)
|
|
||||||
if (*dpl->dp.hostlist_auto_filename)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
@ -50,20 +50,23 @@ struct desync_profile
|
|||||||
unsigned int tamper_start,tamper_cutoff;
|
unsigned int tamper_start,tamper_cutoff;
|
||||||
|
|
||||||
bool filter_ipv4,filter_ipv6;
|
bool filter_ipv4,filter_ipv6;
|
||||||
port_filter pf_tcp;
|
struct port_filters_head pf_tcp;
|
||||||
uint32_t filter_l7; // L7_PROTO_* bits
|
uint32_t filter_l7; // L7_PROTO_* bits
|
||||||
ipset ips,ips_exclude;
|
|
||||||
struct str_list_head ipset_files, ipset_exclude_files;
|
|
||||||
|
|
||||||
strpool *hostlist, *hostlist_exclude;
|
// list of pointers to ipsets
|
||||||
struct str_list_head hostlist_files, hostlist_exclude_files;
|
struct ipset_collection_head ips_collection, ips_collection_exclude;
|
||||||
char hostlist_auto_filename[PATH_MAX];
|
|
||||||
int hostlist_auto_fail_threshold, hostlist_auto_fail_time;
|
// list of pointers to hostlist files
|
||||||
time_t hostlist_auto_mod_time;
|
struct hostlist_collection_head hl_collection, hl_collection_exclude;
|
||||||
|
// pointer to autohostlist. NULL if no autohostlist for the profile.
|
||||||
|
struct hostlist_file *hostlist_auto;
|
||||||
|
int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold;
|
||||||
|
|
||||||
hostfail_pool *hostlist_auto_fail_counters;
|
hostfail_pool *hostlist_auto_fail_counters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PROFILE_IPSETS_EMPTY(dp) (IPSET_EMPTY(&dp->ips) && IPSET_EMPTY(&dp->ips_exclude))
|
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&dp->ips_collection) && ipset_collection_is_empty(&dp->ips_collection_exclude))
|
||||||
|
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&dp->hl_collection) && hostlist_collection_is_empty(&dp->hl_collection_exclude))
|
||||||
|
|
||||||
struct desync_profile_list {
|
struct desync_profile_list {
|
||||||
struct desync_profile dp;
|
struct desync_profile dp;
|
||||||
@ -72,7 +75,6 @@ struct desync_profile_list {
|
|||||||
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
||||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
||||||
void dp_list_destroy(struct desync_profile_list_head *head);
|
void dp_list_destroy(struct desync_profile_list_head *head);
|
||||||
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
|
|
||||||
|
|
||||||
struct params_s
|
struct params_s
|
||||||
{
|
{
|
||||||
@ -112,6 +114,11 @@ struct params_s
|
|||||||
int ttl_default;
|
int ttl_default;
|
||||||
char hostlist_auto_debuglog[PATH_MAX];
|
char hostlist_auto_debuglog[PATH_MAX];
|
||||||
|
|
||||||
|
// hostlist files with data for all profiles
|
||||||
|
struct hostlist_files_head hostlists;
|
||||||
|
// ipset files with data for all profiles
|
||||||
|
struct ipset_files_head ipsets;
|
||||||
|
|
||||||
bool tamper; // any tamper option is set
|
bool tamper; // any tamper option is set
|
||||||
bool tamper_lim; // tamper-start or tamper-cutoff set in any profile
|
bool tamper_lim; // tamper-start or tamper-cutoff set in any profile
|
||||||
struct desync_profile_list_head desync_profiles;
|
struct desync_profile_list_head desync_profiles;
|
||||||
|
218
tpws/pools.c
218
tpws/pools.c
@ -52,12 +52,6 @@ bool StrPoolAddStr(strpool **pp, const char *s)
|
|||||||
{
|
{
|
||||||
return StrPoolAddStrLen(pp, s, strlen(s));
|
return StrPoolAddStrLen(pp, s, strlen(s));
|
||||||
}
|
}
|
||||||
bool StrPoolAddUniqueStr(strpool **pp,const char *s)
|
|
||||||
{
|
|
||||||
if (StrPoolCheckStr(*pp,s))
|
|
||||||
return true;
|
|
||||||
return StrPoolAddStr(pp,s);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StrPoolCheckStr(strpool *p, const char *s)
|
bool StrPoolCheckStr(strpool *p, const char *s)
|
||||||
{
|
{
|
||||||
@ -160,6 +154,93 @@ void strlist_destroy(struct str_list_head *head)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename)
|
||||||
|
{
|
||||||
|
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
if (!(entry->filename = strdup(filename)))
|
||||||
|
{
|
||||||
|
free(entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
entry->mod_time=0;
|
||||||
|
entry->hostlist = NULL;
|
||||||
|
LIST_INSERT_HEAD(head, entry, next);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
static void hostlist_files_entry_destroy(struct hostlist_file *entry)
|
||||||
|
{
|
||||||
|
if (entry->filename) free(entry->filename);
|
||||||
|
StrPoolDestroy(&entry->hostlist);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
void hostlist_files_destroy(struct hostlist_files_head *head)
|
||||||
|
{
|
||||||
|
struct hostlist_file *entry;
|
||||||
|
while ((entry = LIST_FIRST(head)))
|
||||||
|
{
|
||||||
|
LIST_REMOVE(entry, next);
|
||||||
|
hostlist_files_entry_destroy(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, const char *filename)
|
||||||
|
{
|
||||||
|
struct hostlist_file *hfile;
|
||||||
|
|
||||||
|
LIST_FOREACH(hfile, head, next)
|
||||||
|
{
|
||||||
|
if (!strcmp(hfile->filename,filename))
|
||||||
|
return hfile;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile)
|
||||||
|
{
|
||||||
|
struct hostlist_item *entry = malloc(sizeof(struct hostlist_item));
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
entry->hfile = hfile;
|
||||||
|
LIST_INSERT_HEAD(head, entry, next);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
void hostlist_collection_destroy(struct hostlist_collection_head *head)
|
||||||
|
{
|
||||||
|
struct hostlist_item *entry;
|
||||||
|
while ((entry = LIST_FIRST(head)))
|
||||||
|
{
|
||||||
|
LIST_REMOVE(entry, next);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head *head, const char *filename)
|
||||||
|
{
|
||||||
|
struct hostlist_item *item;
|
||||||
|
|
||||||
|
LIST_FOREACH(item, head, next)
|
||||||
|
{
|
||||||
|
if (!strcmp(item->hfile->filename,filename))
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bool hostlist_collection_is_empty(const struct hostlist_collection_head *head)
|
||||||
|
{
|
||||||
|
const struct hostlist_item *item;
|
||||||
|
|
||||||
|
LIST_FOREACH(item, head, next)
|
||||||
|
{
|
||||||
|
if (item->hfile->hostlist)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ipset4Destroy(ipset4 **ipset)
|
void ipset4Destroy(ipset4 **ipset)
|
||||||
{
|
{
|
||||||
ipset4 *elem, *tmp;
|
ipset4 *elem, *tmp;
|
||||||
@ -281,3 +362,128 @@ void ipsetPrint(ipset *ipset)
|
|||||||
ipset4Print(ipset->ips4);
|
ipset4Print(ipset->ips4);
|
||||||
ipset6Print(ipset->ips6);
|
ipset6Print(ipset->ips6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *filename)
|
||||||
|
{
|
||||||
|
struct ipset_file *entry = malloc(sizeof(struct ipset_file));
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
if (!(entry->filename = strdup(filename)))
|
||||||
|
{
|
||||||
|
free(entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
entry->mod_time=0;
|
||||||
|
memset(&entry->ipset,0,sizeof(entry->ipset));
|
||||||
|
LIST_INSERT_HEAD(head, entry, next);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
static void ipset_files_entry_destroy(struct ipset_file *entry)
|
||||||
|
{
|
||||||
|
if (entry->filename) free(entry->filename);
|
||||||
|
ipsetDestroy(&entry->ipset);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
void ipset_files_destroy(struct ipset_files_head *head)
|
||||||
|
{
|
||||||
|
struct ipset_file *entry;
|
||||||
|
while ((entry = LIST_FIRST(head)))
|
||||||
|
{
|
||||||
|
LIST_REMOVE(entry, next);
|
||||||
|
ipset_files_entry_destroy(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char *filename)
|
||||||
|
{
|
||||||
|
struct ipset_file *hfile;
|
||||||
|
|
||||||
|
LIST_FOREACH(hfile, head, next)
|
||||||
|
{
|
||||||
|
if (!strcmp(hfile->filename,filename))
|
||||||
|
return hfile;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipset_item *ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile)
|
||||||
|
{
|
||||||
|
struct ipset_item *entry = malloc(sizeof(struct ipset_item));
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
entry->hfile = hfile;
|
||||||
|
LIST_INSERT_HEAD(head, entry, next);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
void ipset_collection_destroy(struct ipset_collection_head *head)
|
||||||
|
{
|
||||||
|
struct ipset_item *entry;
|
||||||
|
while ((entry = LIST_FIRST(head)))
|
||||||
|
{
|
||||||
|
LIST_REMOVE(entry, next);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, const char *filename)
|
||||||
|
{
|
||||||
|
struct ipset_item *item;
|
||||||
|
|
||||||
|
LIST_FOREACH(item, head, next)
|
||||||
|
{
|
||||||
|
if (!strcmp(item->hfile->filename,filename))
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bool ipset_collection_is_empty(const struct ipset_collection_head *head)
|
||||||
|
{
|
||||||
|
const struct ipset_item *item;
|
||||||
|
|
||||||
|
LIST_FOREACH(item, head, next)
|
||||||
|
{
|
||||||
|
if (!IPSET_EMPTY(&item->hfile->ipset))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool port_filter_add(struct port_filters_head *head, const port_filter *pf)
|
||||||
|
{
|
||||||
|
struct port_filter_item *entry = malloc(sizeof(struct port_filter_item));
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
entry->pf = *pf;
|
||||||
|
LIST_INSERT_HEAD(head, entry, next);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
void port_filters_destroy(struct port_filters_head *head)
|
||||||
|
{
|
||||||
|
struct port_filter_item *entry;
|
||||||
|
while ((entry = LIST_FIRST(head)))
|
||||||
|
{
|
||||||
|
LIST_REMOVE(entry, next);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port)
|
||||||
|
{
|
||||||
|
const struct port_filter_item *item;
|
||||||
|
|
||||||
|
if (!LIST_FIRST(head)) return true;
|
||||||
|
LIST_FOREACH(item, head, next)
|
||||||
|
{
|
||||||
|
if (pf_in_range(port, &item->pf))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool port_filters_deny_if_empty(struct port_filters_head *head)
|
||||||
|
{
|
||||||
|
port_filter pf;
|
||||||
|
if (LIST_FIRST(head)) return true;
|
||||||
|
return pf_parse("0",&pf) && port_filter_add(head,&pf);
|
||||||
|
}
|
||||||
|
60
tpws/pools.h
60
tpws/pools.h
@ -19,7 +19,6 @@ typedef struct strpool {
|
|||||||
|
|
||||||
void StrPoolDestroy(strpool **pp);
|
void StrPoolDestroy(strpool **pp);
|
||||||
bool StrPoolAddStr(strpool **pp,const char *s);
|
bool StrPoolAddStr(strpool **pp,const char *s);
|
||||||
bool StrPoolAddUniqueStr(strpool **pp,const char *s);
|
|
||||||
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
|
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
|
||||||
bool StrPoolCheckStr(strpool *p,const char *s);
|
bool StrPoolCheckStr(strpool *p,const char *s);
|
||||||
|
|
||||||
@ -29,7 +28,6 @@ struct str_list {
|
|||||||
};
|
};
|
||||||
LIST_HEAD(str_list_head, str_list);
|
LIST_HEAD(str_list_head, str_list);
|
||||||
|
|
||||||
|
|
||||||
typedef struct hostfail_pool {
|
typedef struct hostfail_pool {
|
||||||
char *str; /* key */
|
char *str; /* key */
|
||||||
int counter; /* value */
|
int counter; /* value */
|
||||||
@ -49,6 +47,30 @@ bool strlist_add(struct str_list_head *head, const char *filename);
|
|||||||
void strlist_destroy(struct str_list_head *head);
|
void strlist_destroy(struct str_list_head *head);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct hostlist_file {
|
||||||
|
char *filename;
|
||||||
|
time_t mod_time;
|
||||||
|
strpool *hostlist;
|
||||||
|
LIST_ENTRY(hostlist_file) next;
|
||||||
|
};
|
||||||
|
LIST_HEAD(hostlist_files_head, hostlist_file);
|
||||||
|
|
||||||
|
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename);
|
||||||
|
void hostlist_files_destroy(struct hostlist_files_head *head);
|
||||||
|
struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, const char *filename);
|
||||||
|
|
||||||
|
struct hostlist_item {
|
||||||
|
struct hostlist_file *hfile;
|
||||||
|
LIST_ENTRY(hostlist_item) next;
|
||||||
|
};
|
||||||
|
LIST_HEAD(hostlist_collection_head, hostlist_item);
|
||||||
|
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile);
|
||||||
|
void hostlist_collection_destroy(struct hostlist_collection_head *head);
|
||||||
|
struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head *head, const char *filename);
|
||||||
|
bool hostlist_collection_is_empty(const struct hostlist_collection_head *head);
|
||||||
|
|
||||||
|
|
||||||
typedef struct ipset4 {
|
typedef struct ipset4 {
|
||||||
struct cidr4 cidr; /* key */
|
struct cidr4 cidr; /* key */
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
@ -85,3 +107,37 @@ void ipset6Print(ipset6 *ipset);
|
|||||||
|
|
||||||
void ipsetDestroy(ipset *ipset);
|
void ipsetDestroy(ipset *ipset);
|
||||||
void ipsetPrint(ipset *ipset);
|
void ipsetPrint(ipset *ipset);
|
||||||
|
|
||||||
|
|
||||||
|
struct ipset_file {
|
||||||
|
char *filename;
|
||||||
|
time_t mod_time;
|
||||||
|
ipset ipset;
|
||||||
|
LIST_ENTRY(ipset_file) next;
|
||||||
|
};
|
||||||
|
LIST_HEAD(ipset_files_head, ipset_file);
|
||||||
|
|
||||||
|
struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *filename);
|
||||||
|
void ipset_files_destroy(struct ipset_files_head *head);
|
||||||
|
struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char *filename);
|
||||||
|
|
||||||
|
struct ipset_item {
|
||||||
|
struct ipset_file *hfile;
|
||||||
|
LIST_ENTRY(ipset_item) next;
|
||||||
|
};
|
||||||
|
LIST_HEAD(ipset_collection_head, ipset_item);
|
||||||
|
struct ipset_item * ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile);
|
||||||
|
void ipset_collection_destroy(struct ipset_collection_head *head);
|
||||||
|
struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, const char *filename);
|
||||||
|
bool ipset_collection_is_empty(const struct ipset_collection_head *head);
|
||||||
|
|
||||||
|
|
||||||
|
struct port_filter_item {
|
||||||
|
port_filter pf;
|
||||||
|
LIST_ENTRY(port_filter_item) next;
|
||||||
|
};
|
||||||
|
LIST_HEAD(port_filters_head, port_filter_item);
|
||||||
|
bool port_filter_add(struct port_filters_head *head, const port_filter *pf);
|
||||||
|
void port_filters_destroy(struct port_filters_head *head);
|
||||||
|
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
|
||||||
|
bool port_filters_deny_if_empty(struct port_filters_head *head);
|
||||||
|
@ -24,40 +24,36 @@ static bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7)
|
|||||||
(l7proto==TLS && (filter_l7 & L7_PROTO_TLS));
|
(l7proto==TLS && (filter_l7 & L7_PROTO_TLS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dp_match_l3l4(struct desync_profile *dp, const struct sockaddr *dest)
|
|
||||||
{
|
|
||||||
return ((dest->sa_family==AF_INET && dp->filter_ipv4) || (dest->sa_family==AF_INET6 && dp->filter_ipv6)) &&
|
|
||||||
pf_in_range(saport(dest), &dp->pf_tcp) &&
|
|
||||||
IpsetCheck(dp, dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL);
|
|
||||||
}
|
|
||||||
static bool dp_impossible(struct desync_profile *dp, const char *hostname, t_l7proto l7proto)
|
|
||||||
{
|
|
||||||
return !PROFILE_IPSETS_EMPTY(dp) &&
|
|
||||||
((dp->filter_l7 && !l7_proto_match(l7proto, dp->filter_l7)) || (!*dp->hostlist_auto_filename && !hostname && (dp->hostlist || dp->hostlist_exclude)));
|
|
||||||
}
|
|
||||||
static bool dp_match(struct desync_profile *dp, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto)
|
static bool dp_match(struct desync_profile *dp, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto)
|
||||||
{
|
{
|
||||||
// impossible case, hard filter
|
if (!HostlistsReloadCheckForProfile(dp)) return false;
|
||||||
// impossible check avoids relatively slow ipset search
|
|
||||||
if (!dp_impossible(dp,hostname,l7proto) && dp_match_l3l4(dp,dest))
|
if ((dest->sa_family==AF_INET && !dp->filter_ipv4) || (dest->sa_family==AF_INET6 && !dp->filter_ipv6))
|
||||||
{
|
// L3 filter does not match
|
||||||
// soft filter
|
return false;
|
||||||
|
if (!port_filters_in_range(&dp->pf_tcp,saport(dest)))
|
||||||
|
// L4 filter does not match
|
||||||
|
return false;
|
||||||
if (dp->filter_l7 && !l7_proto_match(l7proto, dp->filter_l7))
|
if (dp->filter_l7 && !l7_proto_match(l7proto, dp->filter_l7))
|
||||||
|
// L7 filter does not match
|
||||||
|
return false;
|
||||||
|
if (!dp->hostlist_auto && !hostname && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||||
|
// avoid cpu consuming ipset check. profile cannot win if regular hostlists are present without auto hostlist and hostname is unknown.
|
||||||
|
return false;
|
||||||
|
if (!IpsetCheck(dp, dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL))
|
||||||
|
// target ip does not match
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// autohostlist profile matching l3/l4 filter always win
|
// autohostlist profile matching l3/l4 filter always win
|
||||||
if (*dp->hostlist_auto_filename) return true;
|
if (dp->hostlist_auto) return true;
|
||||||
|
|
||||||
if (dp->hostlist || dp->hostlist_exclude)
|
if (PROFILE_HOSTLISTS_EMPTY(dp))
|
||||||
{
|
|
||||||
// without known hostname first profile matching l3/l4 filter and without hostlist filter wins
|
|
||||||
if (hostname)
|
|
||||||
return HostlistCheck(dp, hostname, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// profile without hostlist filter wins
|
// profile without hostlist filter wins
|
||||||
return true;
|
return true;
|
||||||
}
|
else if (hostname)
|
||||||
|
// without known hostname first profile matching l3/l4 filter and without hostlist filter wins
|
||||||
|
return HostlistCheck(dp, hostname, NULL, true);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static struct desync_profile *dp_find(struct desync_profile_list_head *head, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto)
|
static struct desync_profile *dp_find(struct desync_profile_list_head *head, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto)
|
||||||
@ -100,6 +96,8 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
|
|
||||||
DBGPRINT("tamper_out\n");
|
DBGPRINT("tamper_out\n");
|
||||||
|
|
||||||
|
if (!ctrack->dp) return;
|
||||||
|
|
||||||
if (params.debug)
|
if (params.debug)
|
||||||
{
|
{
|
||||||
char ip_port[48];
|
char ip_port[48];
|
||||||
@ -181,10 +179,10 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
VPRINT("desync profile changed by revealed l7 protocol or hostname !\n");
|
VPRINT("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bDiscoveredHostname && *ctrack->dp->hostlist_auto_filename)
|
if (bDiscoveredHostname && ctrack->dp->hostlist_auto)
|
||||||
{
|
{
|
||||||
bool bHostExcluded;
|
bool bHostExcluded;
|
||||||
if (!HostlistCheck(ctrack->dp, Host, &bHostExcluded))
|
if (!HostlistCheck(ctrack->dp, Host, &bHostExcluded, false))
|
||||||
{
|
{
|
||||||
ctrack->b_ah_check = !bHostExcluded;
|
ctrack->b_ah_check = !bHostExcluded;
|
||||||
VPRINT("Not acting on this request\n");
|
VPRINT("Not acting on this request\n");
|
||||||
@ -193,8 +191,6 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctrack->dp) return;
|
|
||||||
|
|
||||||
switch(l7proto)
|
switch(l7proto)
|
||||||
{
|
{
|
||||||
case HTTP:
|
case HTTP:
|
||||||
@ -415,21 +411,21 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
|||||||
|
|
||||||
VPRINT("auto hostlist (profile %d) : rechecking %s to avoid duplicates\n", dp->n, hostname);
|
VPRINT("auto hostlist (profile %d) : rechecking %s to avoid duplicates\n", dp->n, hostname);
|
||||||
bool bExcluded=false;
|
bool bExcluded=false;
|
||||||
if (!HostlistCheck(dp, hostname, &bExcluded) && !bExcluded)
|
if (!HostlistCheck(dp, hostname, &bExcluded, false) && !bExcluded)
|
||||||
{
|
{
|
||||||
VPRINT("auto hostlist (profile %d) : adding %s to %s\n", dp->n, hostname, dp->hostlist_auto_filename);
|
VPRINT("auto hostlist (profile %d) : adding %s to %s\n", dp->n, hostname, dp->hostlist_auto->filename);
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : client %s : proto %s : adding to %s", hostname, dp->n, client_ip_port, l7proto_str(l7proto), dp->hostlist_auto_filename);
|
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : client %s : proto %s : adding to %s", hostname, dp->n, client_ip_port, l7proto_str(l7proto), dp->hostlist_auto->filename);
|
||||||
if (!StrPoolAddStr(&dp->hostlist, hostname))
|
if (!StrPoolAddStr(&dp->hostlist_auto->hostlist, hostname))
|
||||||
{
|
{
|
||||||
DLOG_ERR("StrPoolAddStr out of memory\n");
|
DLOG_ERR("StrPoolAddStr out of memory\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!append_to_list_file(dp->hostlist_auto_filename, hostname))
|
if (!append_to_list_file(dp->hostlist_auto->filename, hostname))
|
||||||
{
|
{
|
||||||
DLOG_PERROR("write to auto hostlist:");
|
DLOG_PERROR("write to auto hostlist:");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dp->hostlist_auto_mod_time = file_mod_time(dp->hostlist_auto_filename);
|
dp->hostlist_auto->mod_time = file_mod_time(dp->hostlist_auto->filename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
111
tpws/tpws.c
111
tpws/tpws.c
@ -43,25 +43,9 @@
|
|||||||
|
|
||||||
struct params_s params;
|
struct params_s params;
|
||||||
|
|
||||||
bool bHup = false;
|
|
||||||
static void onhup(int sig)
|
static void onhup(int sig)
|
||||||
{
|
{
|
||||||
printf("HUP received !\n");
|
printf("HUP received !\n");
|
||||||
printf("Will reload hostlists and ipsets on next request (if any)\n");
|
|
||||||
bHup = true;
|
|
||||||
}
|
|
||||||
// should be called in normal execution
|
|
||||||
void dohup(void)
|
|
||||||
{
|
|
||||||
if (bHup)
|
|
||||||
{
|
|
||||||
if (!LoadIncludeHostLists() || !LoadExcludeHostLists() || !LoadIncludeIpsets() || !LoadExcludeIpsets())
|
|
||||||
{
|
|
||||||
// what will we do without hostlist or ipset ?? sure, gonna die
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
bHup = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onusr2(int sig)
|
static void onusr2(int sig)
|
||||||
@ -180,7 +164,7 @@ static void exithelp(void)
|
|||||||
"\nMULTI-STRATEGY:\n"
|
"\nMULTI-STRATEGY:\n"
|
||||||
" --new\t\t\t\t\t; begin new strategy\n"
|
" --new\t\t\t\t\t; begin new strategy\n"
|
||||||
" --filter-l3=ipv4|ipv6\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
" --filter-l3=ipv4|ipv6\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||||
" --filter-tcp=[~]port1[-port2]\t\t; TCP port filter. ~ means negation\n"
|
" --filter-tcp=[~]port1[-port2]|*\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
|
||||||
" --filter-l7=[http|tls|unknown]\t\t; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
" --filter-l7=[http|tls|unknown]\t\t; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
||||||
" --ipset=<filename>\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
" --ipset=<filename>\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||||
" --ipset-exclude=<filename>\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
" --ipset-exclude=<filename>\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||||
@ -230,6 +214,9 @@ static void exithelp(void)
|
|||||||
static void cleanup_params(void)
|
static void cleanup_params(void)
|
||||||
{
|
{
|
||||||
dp_list_destroy(¶ms.desync_profiles);
|
dp_list_destroy(¶ms.desync_profiles);
|
||||||
|
|
||||||
|
hostlist_files_destroy(¶ms.hostlists);
|
||||||
|
ipset_files_destroy(¶ms.ipsets);
|
||||||
}
|
}
|
||||||
static void exithelp_clean(void)
|
static void exithelp_clean(void)
|
||||||
{
|
{
|
||||||
@ -312,10 +299,7 @@ static bool wf_make_l3(char *opt, bool *ipv4, bool *ipv6)
|
|||||||
*ipv6 = true;
|
*ipv6 = true;
|
||||||
else return false;
|
else return false;
|
||||||
|
|
||||||
if (e)
|
if (e) *e++=c;
|
||||||
{
|
|
||||||
*e++=c;
|
|
||||||
}
|
|
||||||
p = e;
|
p = e;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -341,15 +325,36 @@ static bool parse_l7_list(char *opt, uint32_t *l7)
|
|||||||
*l7 |= L7_PROTO_UNKNOWN;
|
*l7 |= L7_PROTO_UNKNOWN;
|
||||||
else return false;
|
else return false;
|
||||||
|
|
||||||
if (e)
|
if (e) *e++=c;
|
||||||
{
|
|
||||||
*e++=c;
|
|
||||||
}
|
|
||||||
p = e;
|
p = e;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool parse_pf_list(char *opt, struct port_filters_head *pfl)
|
||||||
|
{
|
||||||
|
char *e,*p,c;
|
||||||
|
port_filter pf;
|
||||||
|
bool b;
|
||||||
|
|
||||||
|
for (p=opt ; p ; )
|
||||||
|
{
|
||||||
|
if ((e = strchr(p,',')))
|
||||||
|
{
|
||||||
|
c=*e;
|
||||||
|
*e=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
b = pf_parse(p,&pf) && port_filter_add(pfl,&pf);
|
||||||
|
if (e) *e++=c;
|
||||||
|
if (!b) return false;
|
||||||
|
|
||||||
|
p = e;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void parse_params(int argc, char *argv[])
|
void parse_params(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
@ -367,6 +372,10 @@ void parse_params(int argc, char *argv[])
|
|||||||
#if defined(__OpenBSD__) || defined(__APPLE__)
|
#if defined(__OpenBSD__) || defined(__APPLE__)
|
||||||
params.pf_enable = true; // OpenBSD and MacOS have no other choice
|
params.pf_enable = true; // OpenBSD and MacOS have no other choice
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LIST_INIT(¶ms.hostlists);
|
||||||
|
LIST_INIT(¶ms.ipsets);
|
||||||
|
|
||||||
if (can_drop_root())
|
if (can_drop_root())
|
||||||
{
|
{
|
||||||
params.uid = params.gid = 0x7FFFFFFF; // default uid:gid
|
params.uid = params.gid = 0x7FFFFFFF; // default uid:gid
|
||||||
@ -726,29 +735,29 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 36: /* hostlist */
|
case 36: /* hostlist */
|
||||||
if (!strlist_add(&dp->hostlist_files, optarg))
|
if (!RegisterHostlist(dp, false, optarg))
|
||||||
{
|
{
|
||||||
DLOG_ERR("strlist_add failed\n");
|
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 37: /* hostlist-exclude */
|
case 37: /* hostlist-exclude */
|
||||||
if (!strlist_add(&dp->hostlist_exclude_files, optarg))
|
if (!RegisterHostlist(dp, true, optarg))
|
||||||
{
|
{
|
||||||
DLOG_ERR("strlist_add failed\n");
|
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 38: /* hostlist-auto */
|
case 38: /* hostlist-auto */
|
||||||
if (*dp->hostlist_auto_filename)
|
if (dp->hostlist_auto)
|
||||||
{
|
{
|
||||||
DLOG_ERR("only one auto hostlist per profile is supported\n");
|
DLOG_ERR("only one auto hostlist per profile is supported\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
FILE *F = fopen(optarg,"a+t");
|
FILE *F = fopen(optarg,"a+b");
|
||||||
if (!F)
|
if (!F)
|
||||||
{
|
{
|
||||||
DLOG_ERR("cannot create %s\n", optarg);
|
DLOG_ERR("cannot create %s\n", optarg);
|
||||||
@ -764,13 +773,11 @@ void parse_params(int argc, char *argv[])
|
|||||||
if (params.droproot && chown(optarg, params.uid, -1))
|
if (params.droproot && chown(optarg, params.uid, -1))
|
||||||
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", optarg);
|
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", optarg);
|
||||||
}
|
}
|
||||||
if (!strlist_add(&dp->hostlist_files, optarg))
|
if (!(dp->hostlist_auto=RegisterHostlist(dp, false, optarg)))
|
||||||
{
|
{
|
||||||
DLOG_ERR("strlist_add failed\n");
|
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
strncpy(dp->hostlist_auto_filename, optarg, sizeof(dp->hostlist_auto_filename));
|
|
||||||
dp->hostlist_auto_filename[sizeof(dp->hostlist_auto_filename) - 1] = '\0';
|
|
||||||
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
|
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
|
||||||
break;
|
break;
|
||||||
case 39: /* hostlist-auto-fail-threshold */
|
case 39: /* hostlist-auto-fail-threshold */
|
||||||
@ -965,7 +972,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 58: /* filter-tcp */
|
case 58: /* filter-tcp */
|
||||||
if (!pf_parse(optarg,&dp->pf_tcp))
|
if (!parse_pf_list(optarg,&dp->pf_tcp))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@ -979,17 +986,17 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 60: /* ipset */
|
case 60: /* ipset */
|
||||||
if (!strlist_add(&dp->ipset_files, optarg))
|
if (!RegisterIpset(dp, false, optarg))
|
||||||
{
|
{
|
||||||
DLOG_ERR("strlist_add failed\n");
|
DLOG_ERR("failed to register ipset '%s'\n", optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 61: /* ipset-exclude */
|
case 61: /* ipset-exclude */
|
||||||
if (!strlist_add(&dp->ipset_exclude_files, optarg))
|
if (!RegisterIpset(dp, true, optarg))
|
||||||
{
|
{
|
||||||
DLOG_ERR("strlist_add failed\n");
|
DLOG_ERR("failed to register ipset '%s'\n", optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
@ -1062,7 +1069,6 @@ void parse_params(int argc, char *argv[])
|
|||||||
dp = &dpl->dp;
|
dp = &dpl->dp;
|
||||||
if (dp->split_tls==tlspos_none && dp->split_pos) dp->split_tls=tlspos_pos;
|
if (dp->split_tls==tlspos_none && dp->split_pos) dp->split_tls=tlspos_pos;
|
||||||
if (dp->split_http_req==httpreqpos_none && dp->split_pos) dp->split_http_req=httpreqpos_pos;
|
if (dp->split_http_req==httpreqpos_none && dp->split_pos) dp->split_http_req=httpreqpos_pos;
|
||||||
if (*dp->hostlist_auto_filename) dp->hostlist_auto_mod_time = file_mod_time(dp->hostlist_auto_filename);
|
|
||||||
if (params.skip_nodelay && (dp->split_tls || dp->split_http_req || dp->split_pos))
|
if (params.skip_nodelay && (dp->split_tls || dp->split_http_req || dp->split_pos))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Cannot split with --skip-nodelay\n");
|
DLOG_ERR("Cannot split with --skip-nodelay\n");
|
||||||
@ -1070,26 +1076,21 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LoadIncludeHostLists())
|
if (!LoadAllHostLists())
|
||||||
{
|
{
|
||||||
DLOG_ERR("Include hostlist load failed\n");
|
DLOG_ERR("hostlists load failed\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
if (!LoadExcludeHostLists())
|
if (!LoadAllIpsets())
|
||||||
{
|
{
|
||||||
DLOG_ERR("Exclude hostlist load failed\n");
|
DLOG_ERR("ipset load failed\n");
|
||||||
exit_clean(1);
|
|
||||||
}
|
|
||||||
if (!LoadIncludeIpsets())
|
|
||||||
{
|
|
||||||
DLOG_ERR("Include ipset load failed\n");
|
|
||||||
exit_clean(1);
|
|
||||||
}
|
|
||||||
if (!LoadExcludeIpsets())
|
|
||||||
{
|
|
||||||
DLOG_ERR("Exclude ipset load failed\n");
|
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VPRINT("\nlists summary:\n");
|
||||||
|
HostlistsDebug();
|
||||||
|
IpsetsDebug();
|
||||||
|
VPRINT("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1469,8 +1469,6 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dohup();
|
|
||||||
|
|
||||||
for (i = 0; i < num_events; i++)
|
for (i = 0; i < num_events; i++)
|
||||||
{
|
{
|
||||||
conn = (tproxy_conn_t*)events[i].data.ptr;
|
conn = (tproxy_conn_t*)events[i].data.ptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user