mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b2d89c5d22 | ||
|
778b611f86 | ||
|
ffaf91c251 | ||
|
326b42fafd | ||
|
94d4238af2 | ||
|
15e22fa1bd | ||
|
bd8decddc5 | ||
|
2db1ebafe3 | ||
|
33bcf6f7b4 | ||
|
f037f1acb2 | ||
|
cdd9b32b27 | ||
|
7934125c09 | ||
|
6493d55977 | ||
|
cafbb17e70 | ||
|
9ac73f7d2f | ||
|
08a6e8e069 | ||
|
644a934099 | ||
|
0eec445af0 | ||
|
b8acc1b979 | ||
|
123eb057ae | ||
|
56d06456fb | ||
|
a6efe05aa6 | ||
|
a1d29b0c3a | ||
|
756603338b | ||
|
8b73e2ea8e | ||
|
2a0e952153 | ||
|
1065202349 | ||
|
307d38f6af | ||
|
8ac4fc0af5 | ||
|
af89d03118 | ||
|
d89daaaeac | ||
|
f62b289cb5 | ||
|
5f9fa28251 | ||
|
bd67b41f32 | ||
|
00619c8dab | ||
|
58e26c3e9d | ||
|
eddbc3c3e0 | ||
|
2cc73de15c | ||
|
9762f2d22b | ||
|
8c9aa188c3 | ||
|
2f151c0943 | ||
|
9498456c4a | ||
|
860607bce2 | ||
|
94f59511f0 | ||
|
b07ce8d8ca |
13
Makefile
13
Makefile
@@ -15,6 +15,19 @@ all: clean
|
|||||||
done \
|
done \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
systemd: clean
|
||||||
|
@mkdir -p "$(TGT)"; \
|
||||||
|
for dir in $(DIRS); do \
|
||||||
|
find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \
|
||||||
|
$(MAKE) -C "$$dir" systemd || exit; \
|
||||||
|
for exe in "$$dir/"*; do \
|
||||||
|
if [ -f "$$exe" ] && [ -x "$$exe" ]; then \
|
||||||
|
mv -f "$$exe" "${TGT}" ; \
|
||||||
|
ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \
|
||||||
|
fi \
|
||||||
|
done \
|
||||||
|
done
|
||||||
|
|
||||||
android: clean
|
android: clean
|
||||||
@mkdir -p "$(TGT)"; \
|
@mkdir -p "$(TGT)"; \
|
||||||
for dir in $(DIRS); do \
|
for dir in $(DIRS); do \
|
||||||
|
@@ -1145,7 +1145,10 @@ test_has_fake()
|
|||||||
warn_fool()
|
warn_fool()
|
||||||
{
|
{
|
||||||
case "$1" in
|
case "$1" in
|
||||||
md5sig) echo 'WARNING ! although md5sig fooling worked it will not work on all sites. it typically works only on linux servers.' ;;
|
md5sig) echo 'WARNING ! although md5sig fooling worked it will not work on all sites. it typically works only on linux servers.'
|
||||||
|
[ "$2" = "fakedsplit" -o "$2" = "fakeddisorder" ] && \
|
||||||
|
echo "WARNING ! fakedsplit/fakeddisorder with md5sig fooling and low split position causes MTU overflow with multi-segment TLS (kyber)"
|
||||||
|
;;
|
||||||
datanoack) echo 'WARNING ! although datanoack fooling worked it may break NAT and may only work with external IP. Additionally it may require nftables to work correctly.' ;;
|
datanoack) echo 'WARNING ! although datanoack fooling worked it may break NAT and may only work with external IP. Additionally it may require nftables to work correctly.' ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -1272,7 +1275,7 @@ pktws_check_domain_http_bypass_()
|
|||||||
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
|
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
|
||||||
for fooling in $f; do
|
for fooling in $f; do
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
|
||||||
warn_fool $fooling
|
warn_fool $fooling $desync
|
||||||
[ "$SCANLEVEL" = quick ] && return
|
[ "$SCANLEVEL" = quick ] && return
|
||||||
need_wssize=0
|
need_wssize=0
|
||||||
}
|
}
|
||||||
|
@@ -97,7 +97,7 @@ NFQWS_OPT="
|
|||||||
# none,ipset,hostlist,autohostlist
|
# none,ipset,hostlist,autohostlist
|
||||||
MODE_FILTER=none
|
MODE_FILTER=none
|
||||||
|
|
||||||
# openwrt only : donttouch,none,software,hardware
|
# donttouch,none,software,hardware
|
||||||
FLOWOFFLOAD=donttouch
|
FLOWOFFLOAD=donttouch
|
||||||
|
|
||||||
# openwrt: specify networks to be treated as LAN. default is "lan"
|
# openwrt: specify networks to be treated as LAN. default is "lan"
|
||||||
|
@@ -452,3 +452,17 @@ install_easy: dnf packager support
|
|||||||
nfqws,tpws: hostlist/ipset track not only file mod time but also file size
|
nfqws,tpws: hostlist/ipset track not only file mod time but also file size
|
||||||
nfqws,tpws,ipset: return lists reload on HUP
|
nfqws,tpws,ipset: return lists reload on HUP
|
||||||
nfqws,blockcheck: --dpi-desync-fake-tls-mod
|
nfqws,blockcheck: --dpi-desync-fake-tls-mod
|
||||||
|
|
||||||
|
v70.1
|
||||||
|
|
||||||
|
nfqws: --dpi-desync-fake-tls-mod=dupsid
|
||||||
|
nfqws,tpws: test accessibility of list files after privs drop
|
||||||
|
nfqws,tpws: --version
|
||||||
|
|
||||||
|
v70.4
|
||||||
|
|
||||||
|
nfqws,tpws: ^ prefix in hostlist to disable subdomain matches
|
||||||
|
nfqws,tpws: optional systemd notify support. compile using 'make systemd'
|
||||||
|
nfqws,tpws: systemd instance templates for nfqws and tpws
|
||||||
|
nfqws,tpws: separate droproot from dropcaps
|
||||||
|
tpws: detect WSL 1 and warn about non-working options
|
||||||
|
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> Не пишите в issue вопросы типа "как скопировать файл", "как скачать", "как
|
> Не пишите в issue вопросы типа "как скопировать файл", "как скачать", "как
|
||||||
> запустить", ... То есть все , что касается базовых навыков обращения с ОС
|
> запустить" и т.п. То есть все, что касается базовых навыков обращения с ОС
|
||||||
> linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
|
> Linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
|
||||||
> возникают, рекомендую не использовать данный софт или искать помощь где-то в
|
> возникают, рекомендую не использовать данный софт или искать помощь где-то в
|
||||||
> другом месте. То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы
|
> другом месте. То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы
|
||||||
> все заработало, и совсем не хочет читать и изучать. Увы, такое не подвезли и
|
> все заработало, и совсем не хочет читать и изучать. Увы, такое не подвезли и
|
||||||
@@ -89,14 +89,15 @@
|
|||||||
>
|
>
|
||||||
> Проверить работает ли этот вариант можно так:
|
> Проверить работает ли этот вариант можно так:
|
||||||
> ```sh
|
> ```sh
|
||||||
> $ dig -p 53 @77.88.8.88 rutracker.org dig -p 1253 @77.88.8.88 rutracker.org
|
> $ dig -p 53 @77.88.8.88 rutracker.org
|
||||||
|
> $ dig -p 1253 @77.88.8.88 rutracker.org
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
> Если DNS действительно подменяется, и ответ на эти 2 команды разный,
|
> Если DNS действительно подменяется, и ответ на эти 2 команды разный,
|
||||||
> значит метод вероятно работает.
|
> значит метод вероятно работает.
|
||||||
>
|
>
|
||||||
> В openwrt DNS на нестандартном порту можно прописать в `/etc/config/dhcp`
|
> В openwrt DNS на нестандартном порту можно прописать в `/etc/config/dhcp`
|
||||||
> таким способом :
|
> таким способом:
|
||||||
>
|
>
|
||||||
> ```
|
> ```
|
||||||
> config dnsmasq
|
> config dnsmasq
|
||||||
@@ -163,7 +164,7 @@
|
|||||||
> Если кратко, то обычно параметры конструируются так:
|
> Если кратко, то обычно параметры конструируются так:
|
||||||
> ```sh
|
> ```sh
|
||||||
> "--filter-udp=443 'параметры для quic' <HOSTLIST_NOAUTO> --new
|
> "--filter-udp=443 'параметры для quic' <HOSTLIST_NOAUTO> --new
|
||||||
> --filter-tcp=80,443 'обьединенные параметры для http и https' <HOSTLIST>"
|
> --filter-tcp=80,443 'объединенные параметры для http и https' <HOSTLIST>"
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
> Или так:
|
> Или так:
|
||||||
@@ -193,7 +194,7 @@
|
|||||||
> "--filter-l3=ipv4 --filter-udp=443 lпараметры для quic ipv4' <HOSTLIST_NOAUTO> --new
|
> "--filter-l3=ipv4 --filter-udp=443 lпараметры для 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_NOAUTO> --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>"
|
||||||
> ```
|
> ```
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# zapret v70
|
# zapret v70.4
|
||||||
|
|
||||||
# SCAMMER WARNING
|
# SCAMMER WARNING
|
||||||
|
|
||||||
@@ -133,6 +133,7 @@ nfqws takes the following parameters:
|
|||||||
|
|
||||||
--debug=0|1
|
--debug=0|1
|
||||||
--dry-run ; verify parameters and exit with code 0 if successful
|
--dry-run ; verify parameters and exit with code 0 if successful
|
||||||
|
--version ; print version and exit
|
||||||
--comment ; any text (ignored)
|
--comment ; any text (ignored)
|
||||||
--qnum=<nfqueue_number>
|
--qnum=<nfqueue_number>
|
||||||
--daemon ; daemonize
|
--daemon ; daemonize
|
||||||
@@ -173,7 +174,7 @@ nfqws takes the following parameters:
|
|||||||
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
||||||
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request
|
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request
|
||||||
--dpi-desync-fake-tls=<filename>|0xHEX ; file containing fake TLS ClientHello (for https)
|
--dpi-desync-fake-tls=<filename>|0xHEX ; file containing fake TLS ClientHello (for https)
|
||||||
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,padencap
|
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,dupsid,padencap
|
||||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
|
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
|
||||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
|
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
|
||||||
--dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial
|
--dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial
|
||||||
@@ -184,9 +185,9 @@ nfqws takes the following parameters:
|
|||||||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; udp tail fill pattern
|
--dpi-desync-udplen-pattern=<filename>|0xHEX ; udp tail fill pattern
|
||||||
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
||||||
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
||||||
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
|
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed)
|
||||||
--hostlist-domains=<domain_list> ; comma separated fixed domain list
|
--hostlist-domains=<domain_list> ; comma separated fixed domain list
|
||||||
--hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
|
--hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed)
|
||||||
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
|
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
|
||||||
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
|
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
|
||||||
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
|
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
|
||||||
@@ -218,7 +219,9 @@ There're attacks based on TCP sequence numbers. Methods can be combined in many
|
|||||||
|
|
||||||
Fakes are separate generated by nfqws packets carrying false information for DPI. They must either not reach the server or be rejected by it. Otherwise TCP connection or data stream would be broken. There're multiple ways to solve this task.
|
Fakes are separate generated by nfqws packets carrying false information for DPI. They must either not reach the server or be rejected by it. Otherwise TCP connection or data stream would be broken. There're multiple ways to solve this task.
|
||||||
|
|
||||||
* **md5sig** does not work on all servers
|
* **md5sig** does not work on all servers. It typically works only on Linux servers. MD5 tcp option requires additional space in TCP header
|
||||||
|
and can cause MTU overflow during fakedsplit/fakeddisorder on low positions when multisegment query (TLS kyber) is transmitted.
|
||||||
|
`nfqws` cannot redistribute data between original TCP segments. The error displayed is 'message too long'.
|
||||||
* **badsum** doesn't work if your device is behind NAT which does not pass invalid packets.
|
* **badsum** doesn't work if your device is behind NAT which does not pass invalid packets.
|
||||||
The most common Linux NAT router configuration does not pass them. Most home routers are Linux based.
|
The most common Linux NAT router configuration does not pass them. Most home routers are Linux based.
|
||||||
The default sysctl configuration `net.netfilter.nf_conntrack_checksum=1` causes contrack to verify tcp and udp checksums
|
The default sysctl configuration `net.netfilter.nf_conntrack_checksum=1` causes contrack to verify tcp and udp checksums
|
||||||
@@ -273,10 +276,11 @@ It's possible to use TLS Client Hello with any fingerprint and any SNI.
|
|||||||
* `none`. Do not do any mods.
|
* `none`. Do not do any mods.
|
||||||
* `rnd`. Randomize `random` and `session id` fields. Applied on every request.
|
* `rnd`. Randomize `random` and `session id` fields. Applied on every request.
|
||||||
* `rndsni`. Randomize SNI. If SNI >=7 symbols random SLD is applied with known TLD. Otherwise filled with random symbols. Applied only once at startup.
|
* `rndsni`. Randomize SNI. If SNI >=7 symbols random SLD is applied with known TLD. Otherwise filled with random symbols. Applied only once at startup.
|
||||||
|
* `dupsid`. Copy `session ID` from original TLS Client Hello. Takes precedence over `rnd`. Applied on every request.
|
||||||
* `padencap`. Padding extension is extended by original TLS Client Hello size (including multi packet variation with kyber). Padding extension is added to the end if not present, otherwise it must be the last extension. All lengths are increased. Fake size is not changed. Can be useful if DPI does not analyze sequence numbers properly. Applied on every request.
|
* `padencap`. Padding extension is extended by original TLS Client Hello size (including multi packet variation with kyber). Padding extension is added to the end if not present, otherwise it must be the last extension. All lengths are increased. Fake size is not changed. Can be useful if DPI does not analyze sequence numbers properly. Applied on every request.
|
||||||
|
|
||||||
By default if custom fake is not defined `rnd,rndsni` mods are applied. If defined - `none`.
|
By default if custom fake is not defined `rnd,rndsni,dupsid` mods are applied. If defined - `none`.
|
||||||
This behaviour is compatible with previous versions.
|
This behaviour is compatible with previous versions with addition of `dupsid`.
|
||||||
|
|
||||||
### TCP segmentation
|
### TCP segmentation
|
||||||
|
|
||||||
@@ -659,6 +663,7 @@ tpws is transparent proxy.
|
|||||||
--debug=0|1|2|syslog|@<filename> ; 1 and 2 means log to console and set debug level. for other targets use --debug-level.
|
--debug=0|1|2|syslog|@<filename> ; 1 and 2 means log to console and set debug level. for other targets use --debug-level.
|
||||||
--debug-level=0|1|2 ; specify debug level for syslog and @<filename>
|
--debug-level=0|1|2 ; specify debug level for syslog and @<filename>
|
||||||
--dry-run ; verify parameters and exit with code 0 if successful
|
--dry-run ; verify parameters and exit with code 0 if successful
|
||||||
|
--version ; print version and exit
|
||||||
--bind-addr=<v4_addr>|<v6_addr> ; for v6 link locals append %interface_name : fe80::1%br-lan
|
--bind-addr=<v4_addr>|<v6_addr> ; for v6 link locals append %interface_name : fe80::1%br-lan
|
||||||
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
|
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
|
||||||
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface
|
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface
|
||||||
@@ -700,9 +705,9 @@ tpws is transparent proxy.
|
|||||||
--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)
|
||||||
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
|
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
|
||||||
|
|
||||||
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
|
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply if not prefixed with '^', gzip supported, multiple hostlists allowed)
|
||||||
--hostlist-domains=<domain_list> ; comma separated fixed domain list
|
--hostlist-domains=<domain_list> ; comma separated fixed domain list
|
||||||
--hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
|
--hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply if not prefixed with '^', gzip supported, multiple hostlists allowed)
|
||||||
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
|
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
|
||||||
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
|
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
|
||||||
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
|
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
|
||||||
@@ -981,6 +986,7 @@ If all include lists are empty it works like no include lists exist at all.
|
|||||||
If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Just make it empty.
|
If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Just make it empty.
|
||||||
|
|
||||||
Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
|
Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
|
||||||
|
`^` prefix symbol disables subdomain match.
|
||||||
|
|
||||||
**tpws** and **nfqws** automatically reload lists if their modification time or file size is changed.
|
**tpws** and **nfqws** automatically reload lists if their modification time or file size is changed.
|
||||||
HUP signal forcibly reloads all lists.
|
HUP signal forcibly reloads all lists.
|
||||||
|
247
docs/readme.md
247
docs/readme.md
@@ -1,4 +1,4 @@
|
|||||||
# zapret v70
|
# zapret v70.4
|
||||||
|
|
||||||
# ВНИМАНИЕ, остерегайтесь мошенников
|
# ВНИМАНИЕ, остерегайтесь мошенников
|
||||||
|
|
||||||
@@ -47,9 +47,9 @@ zapret является свободным и open source.
|
|||||||
- [СЛУЖЕБНЫЕ ПАРАМЕТРЫ](#служебные-параметры)
|
- [СЛУЖЕБНЫЕ ПАРАМЕТРЫ](#служебные-параметры)
|
||||||
- [IPTABLES ДЛЯ TPWS](#iptables-для-tpws)
|
- [IPTABLES ДЛЯ TPWS](#iptables-для-tpws)
|
||||||
- [NFTABLES ДЛЯ TPWS](#nftables-для-tpws)
|
- [NFTABLES ДЛЯ TPWS](#nftables-для-tpws)
|
||||||
- [Способы получения списка заблокированных IP](#способы-получения-списка-заблокированных-ip)
|
|
||||||
- [ip2net](#ip2net)
|
- [ip2net](#ip2net)
|
||||||
- [mdig](#mdig)
|
- [mdig](#mdig)
|
||||||
|
- [Способы получения списка заблокированных IP](#способы-получения-списка-заблокированных-ip)
|
||||||
- [Фильтрация по именам доменов](#фильтрация-по-именам-доменов)
|
- [Фильтрация по именам доменов](#фильтрация-по-именам-доменов)
|
||||||
- [Режим фильтрации autohostlist](#режим-фильтрации-autohostlist)
|
- [Режим фильтрации autohostlist](#режим-фильтрации-autohostlist)
|
||||||
- [Проверка провайдера](#проверка-провайдера)
|
- [Проверка провайдера](#проверка-провайдера)
|
||||||
@@ -57,6 +57,7 @@ zapret является свободным и open source.
|
|||||||
- [Прикручивание к системе управления фаерволом или своей системе запуска](#прикручивание-к-системе-управления-фаерволом-или-своей-системе-запуска)
|
- [Прикручивание к системе управления фаерволом или своей системе запуска](#прикручивание-к-системе-управления-фаерволом-или-своей-системе-запуска)
|
||||||
- [Вариант custom](#вариант-custom)
|
- [Вариант custom](#вариант-custom)
|
||||||
- [Простая установка](#простая-установка)
|
- [Простая установка](#простая-установка)
|
||||||
|
- [Установка под systemd](#установка-под-systemd)
|
||||||
- [Простая установка на openwrt](#простая-установка-на-openwrt)
|
- [Простая установка на openwrt](#простая-установка-на-openwrt)
|
||||||
- [Установка на openwrt в режиме острой нехватки места на диске](#установка-на-openwrt-в-режиме-острой-нехватки-места-на-диске)
|
- [Установка на openwrt в режиме острой нехватки места на диске](#установка-на-openwrt-в-режиме-острой-нехватки-места-на-диске)
|
||||||
- [Android](#android)
|
- [Android](#android)
|
||||||
@@ -159,6 +160,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
|
|
||||||
--debug=0|1 ; 1=выводить отладочные сообщения
|
--debug=0|1 ; 1=выводить отладочные сообщения
|
||||||
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
|
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
|
||||||
|
--version ; вывести версию и выйти
|
||||||
--comment ; любой текст (игнорируется)
|
--comment ; любой текст (игнорируется)
|
||||||
--daemon ; демонизировать прогу
|
--daemon ; демонизировать прогу
|
||||||
--pidfile=<file> ; сохранить PID в файл
|
--pidfile=<file> ; сохранить PID в файл
|
||||||
@@ -194,7 +196,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||||||
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
||||||
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
|
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
|
||||||
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,padencap
|
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,dupsid,padencap
|
||||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
||||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
||||||
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
||||||
@@ -204,7 +206,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
--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> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются, если хост не начинается с '^'.
|
||||||
; в файле должен быть хост на каждой строке.
|
; в файле должен быть хост на каждой строке.
|
||||||
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||||||
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||||||
@@ -259,6 +261,10 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
Есть ряд методов для решения этой задачи.
|
Есть ряд методов для решения этой задачи.
|
||||||
|
|
||||||
* `md5sig` добавляет TCP опцию **MD5 signature**. Работает не на всех серверах. Пакеты с md5 обычно отбрасывают только linux.
|
* `md5sig` добавляет TCP опцию **MD5 signature**. Работает не на всех серверах. Пакеты с md5 обычно отбрасывают только linux.
|
||||||
|
Требуется значительное увеличение длины tcp пакета, чтобы вместить tcp option. При обработке многосегментных запросов (TLS Kyber)
|
||||||
|
первый пакет идет полный под MTU. При fakedsplit/fakeddisorder на небольших позициях отдельные tcp сегменты достаточно велики, чтобы внедрение
|
||||||
|
md5 tcp option вызвало переполнение MTU и ошибку отправки "message too long". `nfqws` не умеет перераспределять данные между tcp сегментами,
|
||||||
|
поэтому надо или отказываться от kyber, или увеличивать сплит-позицию, или отказываться от fakedsplit/fakeddisorder.
|
||||||
* `badsum` портит контрольную сумму TCP. Не сработает, если ваше устройство за NAT, который не пропускает пакеты с инвалидной суммой. Наиболее
|
* `badsum` портит контрольную сумму TCP. Не сработает, если ваше устройство за NAT, который не пропускает пакеты с инвалидной суммой. Наиболее
|
||||||
распространенная настройка NAT роутера в Linux их не пропускает. На Linux построено большинство домашних роутеров.
|
распространенная настройка NAT роутера в Linux их не пропускает. На Linux построено большинство домашних роутеров.
|
||||||
Непропускание обеспечивается так : настройка ядра sysctl по умолчанию
|
Непропускание обеспечивается так : настройка ядра sysctl по умолчанию
|
||||||
@@ -279,7 +285,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
Такие пакеты будут наверняка отброшены принимающим узлом, но так же и DPI, если он ориентируется на sequence
|
Такие пакеты будут наверняка отброшены принимающим узлом, но так же и DPI, если он ориентируется на sequence
|
||||||
numbers. По умолчанию смещение seq выбирается -10000. Практика показала, что некоторые DPI не пропускают seq вне
|
numbers. По умолчанию смещение seq выбирается -10000. Практика показала, что некоторые DPI не пропускают seq вне
|
||||||
определенного окна. Однако, такое небольшое смещение может вызвать проблемы при существенной потоковой передаче и
|
определенного окна. Однако, такое небольшое смещение может вызвать проблемы при существенной потоковой передаче и
|
||||||
потере пакетов. Если вы используете `--dpi-desync-any-protocol`, может понадобится установить badseq increment
|
потере пакетов. Если вы используете `--dpi-desync-any-protocol`, может понадобиться установить badseq increment
|
||||||
0x80000000. Это обеспечит надежную гарантию, что поддельный пакет не вклинится в tcp window на сервере. Так же было
|
0x80000000. Это обеспечит надежную гарантию, что поддельный пакет не вклинится в tcp window на сервере. Так же было
|
||||||
замечено, что badseq ломает логику некоторых DPI при анализе http, вызывая зависание соединения. Причем на тех же DPI
|
замечено, что badseq ломает логику некоторых DPI при анализе http, вызывая зависание соединения. Причем на тех же DPI
|
||||||
TLS с badseq работает нормально.
|
TLS с badseq работает нормально.
|
||||||
@@ -294,7 +300,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
* `hopbyhop` относится только к ipv6. Добавляется ipv6 extenstion header `hop-by-hop options`. В варианте `hopbyhop2`
|
* `hopbyhop` относится только к ipv6. Добавляется ipv6 extenstion header `hop-by-hop options`. В варианте `hopbyhop2`
|
||||||
добавляются 2 хедера, что является нарушением стандарта и гарантированно отбрасывается стеком протоколов во всех ОС.
|
добавляются 2 хедера, что является нарушением стандарта и гарантированно отбрасывается стеком протоколов во всех ОС.
|
||||||
Один хедер hop-by-hop принимается всеми ОС, однако на некоторых каналах/провайдерах такие пакеты могут фильтроваться и
|
Один хедер hop-by-hop принимается всеми ОС, однако на некоторых каналах/провайдерах такие пакеты могут фильтроваться и
|
||||||
не доходить. Расчет идет на то, что DPI проанализирует пакет с hop-by-hop, но он либо не дойдет до адресата всилу
|
не доходить. Расчет идет на то, что DPI проанализирует пакет с hop-by-hop, но он либо не дойдет до адресата в силу
|
||||||
фильтров провайдера, либо будет отброшен сервером, потому что хедера два.
|
фильтров провайдера, либо будет отброшен сервером, потому что хедера два.
|
||||||
* `datanoack` высылает фейки со снятым tcp флагом ACK. Сервера такое не принимают, а DPI может принять. Эта техника
|
* `datanoack` высылает фейки со снятым tcp флагом ACK. Сервера такое не принимают, а DPI может принять. Эта техника
|
||||||
может ломать NAT и не всегда работает с iptables, если используется masquerade, даже с локальной системы (почти всегда
|
может ломать NAT и не всегда работает с iptables, если используется masquerade, даже с локальной системы (почти всегда
|
||||||
@@ -326,11 +332,12 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
|
|
||||||
* `none`. Не применять никакие модификации.
|
* `none`. Не применять никакие модификации.
|
||||||
* `rnd`. Рандомизировать поля `random` и `session id`. Выполняется на каждый запрос.
|
* `rnd`. Рандомизировать поля `random` и `session id`. Выполняется на каждый запрос.
|
||||||
|
* `dupsid`. Копировать `session ID` из передаваемого TLS Client Hello. Имеет приоритет над `rnd`. Выполняется на каждый запрос.
|
||||||
* `rndsni`. Рандомизировать SNI. Если SNI >=7 символов, применяется случайный домен 2 уровня с известным TLD, иначе заполняется случайными символами без точки. Выполняется один раз при старте.
|
* `rndsni`. Рандомизировать SNI. Если SNI >=7 символов, применяется случайный домен 2 уровня с известным TLD, иначе заполняется случайными символами без точки. Выполняется один раз при старте.
|
||||||
* `padencap`. Расширяется padding extension на размер передаваемого TLS Client Hello (включая многопакетный вариант с kyber). Если padding отсутствует, он добавляется в конец. Если присутствует - требуется, чтобы padding шел последним extension. Правятся все длины, чтобы создать видимость включения передаваемого TLS Client Hello в padding extension. Размер фейка не изменяется. Расчет идет на DPI, который не анализирует sequence numbers должным образом. Выполняется на каждый запрос.
|
* `padencap`. Расширяется padding extension на размер передаваемого TLS Client Hello (включая многопакетный вариант с kyber). Если padding отсутствует, он добавляется в конец. Если присутствует - требуется, чтобы padding шел последним extension. Правятся все длины, чтобы создать видимость включения передаваемого TLS Client Hello в padding extension. Размер фейка не изменяется. Расчет идет на DPI, который не анализирует sequence numbers должным образом. Выполняется на каждый запрос.
|
||||||
|
|
||||||
По умолчанию если не задан собственный фейк для TLS используются модификации `rnd,rndsni`. Если фейк задан, используется `none`.
|
По умолчанию если не задан собственный фейк для TLS используются модификации `rnd,rndsni,dupsid`. Если фейк задан, используется `none`.
|
||||||
Это соответствует поведению программы более старых версий.
|
Это соответствует поведению программы более старых версий с добавлением функции `dupsid`.
|
||||||
|
|
||||||
### TCP СЕГМЕНТАЦИЯ
|
### TCP СЕГМЕНТАЦИЯ
|
||||||
|
|
||||||
@@ -344,6 +351,9 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
Размеры фейков соответствуют длинам отсылаемых частей.
|
Размеры фейков соответствуют длинам отсылаемых частей.
|
||||||
Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков.
|
Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков.
|
||||||
|
|
||||||
|
Использование `fakedsplit` или `fakeddisorder` на TLS kyber с md5sig fooling может привести к ошибкам "message too long", если позиция сплита мала,
|
||||||
|
поскольку будет превышение MTU из-за md5 tcp option.
|
||||||
|
|
||||||
Для определения позиций нарезки используются маркеры.
|
Для определения позиций нарезки используются маркеры.
|
||||||
|
|
||||||
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
|
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
|
||||||
@@ -528,8 +538,8 @@ window size итоговый размер окна стал максимальн
|
|||||||
### РЕАССЕМБЛИНГ
|
### РЕАССЕМБЛИНГ
|
||||||
|
|
||||||
nfqws поддерживает реассемблинг некоторых видов запросов.
|
nfqws поддерживает реассемблинг некоторых видов запросов.
|
||||||
На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в chrome включить пост-квантовую
|
На текущий момент это TLS и QUIC ClientHello. Они бывают длинными, если в chrome включить пост-квантовую
|
||||||
криптографию tls-kyber, и занимают как правило 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124.
|
криптографию tls-kyber, и занимают, как правило, 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124.
|
||||||
chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть
|
chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть
|
||||||
попасть в любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом
|
попасть в любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом
|
||||||
принимает решение о блокировке.
|
принимает решение о блокировке.
|
||||||
@@ -618,7 +628,7 @@ options ip6table_raw raw_before_defrag=1
|
|||||||
|
|
||||||
При использовании iptables и NAT, похоже, что нет способа прицепить обработчик очереди после NAT.
|
При использовании iptables и NAT, похоже, что нет способа прицепить обработчик очереди после NAT.
|
||||||
Пакет попадает в nfqws с source адресом внутренней сети, затем фрагментируется и уже не обрабатывается NAT.
|
Пакет попадает в nfqws с source адресом внутренней сети, затем фрагментируется и уже не обрабатывается NAT.
|
||||||
Так и уходит во внешюю сеть с src ip 192.168.x.x. Следовательно, метод не срабатывает.
|
Так и уходит во внешнюю сеть с src ip 192.168.x.x. Следовательно, метод не срабатывает.
|
||||||
Видимо единственный рабочий метод - отказаться от iptables и использовать nftables.
|
Видимо единственный рабочий метод - отказаться от iptables и использовать nftables.
|
||||||
Хук должен быть с приоритетом 101 или выше.
|
Хук должен быть с приоритетом 101 или выше.
|
||||||
|
|
||||||
@@ -642,7 +652,7 @@ L7 протокол становится известен обычно посл
|
|||||||
Если имя хоста удовлетворяет листам, выбирается этот профиль. Иначе идет переход к следующему.
|
Если имя хоста удовлетворяет листам, выбирается этот профиль. Иначе идет переход к следующему.
|
||||||
Может так случиться, что до получения имени хоста или узнавания L7 протокола соединение идет по одному профилю,
|
Может так случиться, что до получения имени хоста или узнавания L7 протокола соединение идет по одному профилю,
|
||||||
а при выяснении этих параметров профиль меняется на лету. Это может произойти даже дважды - при выяснении L7
|
а при выяснении этих параметров профиль меняется на лету. Это может произойти даже дважды - при выяснении L7
|
||||||
и имени хоста. Чаще всего это выяснение совмещается в одно действие, поскольку по одному пакету как правило узнается и L7, и хост.
|
и имени хоста. Чаще всего это выяснение совмещается в одно действие, поскольку по одному пакету, как правило, узнается и L7, и хост.
|
||||||
Поэтому если у вас есть параметры дурения нулевой фазы, тщательно продумывайте что может произойти при переключении стратегии.
|
Поэтому если у вас есть параметры дурения нулевой фазы, тщательно продумывайте что может произойти при переключении стратегии.
|
||||||
Смотрите debug log, чтобы лучше понять что делает nfqws.
|
Смотрите debug log, чтобы лучше понять что делает nfqws.
|
||||||
Нумерация профилей идет с 1 до N. Последним в цепочке создается пустой профиль с номером 0.
|
Нумерация профилей идет с 1 до N. Последним в цепочке создается пустой профиль с номером 0.
|
||||||
@@ -656,7 +666,7 @@ L7 протокол становится известен обычно посл
|
|||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> user-mode реализация ipset создавалась не как удобная замена *nix версии, реализованной в ядре.
|
> user-mode реализация ipset создавалась не как удобная замена *nix версии, реализованной в ядре.
|
||||||
> Вариант в ядре работает гораздо эффективнее. Это создавалось для систем без подержки ipset в ядре.
|
> Вариант в ядре работает гораздо эффективнее. Это создавалось для систем без подд3ержки ipset в ядре.
|
||||||
> Конкретно - Windows и ядра Linux, собранные без nftables и ipset модулей ядра. Например, в android нет ipset.
|
> Конкретно - Windows и ядра Linux, собранные без nftables и ipset модулей ядра. Например, в android нет ipset.
|
||||||
|
|
||||||
### IPTABLES ДЛЯ NFQWS
|
### IPTABLES ДЛЯ NFQWS
|
||||||
@@ -676,7 +686,7 @@ iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp
|
|||||||
```
|
```
|
||||||
|
|
||||||
mark нужен, чтобы сгенерированный поддельный пакет не попал опять к нам на обработку. nfqws выставляет fwmark при его отсылке.
|
mark нужен, чтобы сгенерированный поддельный пакет не попал опять к нам на обработку. nfqws выставляет fwmark при его отсылке.
|
||||||
хотя nfqws способен самостоятельно различать помеченные пакеты, фильтр в iptables по mark нужен при использовании connbytes,
|
Хотя nfqws способен самостоятельно различать помеченные пакеты, фильтр в iptables по mark нужен при использовании connbytes,
|
||||||
чтобы не допустить изменения порядка следования пакетов. Процессинг очереди - процесс отложенный.
|
чтобы не допустить изменения порядка следования пакетов. Процессинг очереди - процесс отложенный.
|
||||||
Если ядро имеет пакеты на отсылку вне очереди - оно их отправляет незамедлительно.
|
Если ядро имеет пакеты на отсылку вне очереди - оно их отправляет незамедлительно.
|
||||||
Изменение правильного порядка следования пакетов при десинхронизации ломает всю идею.
|
Изменение правильного порядка следования пакетов при десинхронизации ломает всю идею.
|
||||||
@@ -689,7 +699,7 @@ mark нужен, чтобы сгенерированный поддельный
|
|||||||
* 3 - стандартная ситуация приема одного пакета запроса
|
* 3 - стандартная ситуация приема одного пакета запроса
|
||||||
* 4-6 - на случай ретрансмиссии или запроса длиной в несколько пакетов (TLSClientHello с kyber, например)
|
* 4-6 - на случай ретрансмиссии или запроса длиной в несколько пакетов (TLSClientHello с kyber, например)
|
||||||
|
|
||||||
Для режима autottl необходимо перенаправление входящего `SYN,ACK` пакета или первого пакета соединения (что обычно есть тоже самое).
|
Для режима autottl необходимо перенаправление входящего `SYN,ACK` пакета или первого пакета соединения (что обычно есть то же самое).
|
||||||
Для режима autohostlist необходимы входящие RST и http redirect.
|
Для режима autohostlist необходимы входящие RST и http redirect.
|
||||||
Можно построить фильтр на tcp flags для выделения `SYN,ACK` и модуле u32 для поиска характерных паттернов http redirect,
|
Можно построить фильтр на tcp flags для выделения `SYN,ACK` и модуле u32 для поиска характерных паттернов http redirect,
|
||||||
но проще использовать connbytes для выделения нескольких начальных входящих пакетов.
|
но проще использовать connbytes для выделения нескольких начальных входящих пакетов.
|
||||||
@@ -759,12 +769,21 @@ iptables могут не работать. При включенном offloadin
|
|||||||
Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов iptables. При включенном SFO работает
|
Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов iptables. При включенном SFO работает
|
||||||
DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading. Однако, остальные соединения идут через SFO, потому
|
DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading. Однако, остальные соединения идут через SFO, потому
|
||||||
NFQUEUE будет срабатывать только до помещения соединения в flowtable. Практически это означает, что почти весь функционал nfqws работать не будет.
|
NFQUEUE будет срабатывать только до помещения соединения в flowtable. Практически это означает, что почти весь функционал nfqws работать не будет.
|
||||||
Offload включается через специальный target в iptables `FLOWOFFLOAD`. Не обязательно пропускать весь трафик через offload. Можно исключить из
|
Offload включается через специальный target в iptables `FLOWOFFLOAD` или через flowtable в nftables.
|
||||||
offload соединения, которые должны попасть на tpws или nfqws. OpenWrt не предусматривает выборочного управления offload.
|
|
||||||
Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в OpenWrt.
|
Не обязательно пропускать весь трафик через offload.
|
||||||
|
tpws и так обходит offload "by design", а для отработки nfqws достаточно первых нескольких пакетов в tcp соединении или udp сеансе.
|
||||||
|
Пока сеанс не направлен на offload, он процессится обычным образом через полноценный netfilter.
|
||||||
|
Как только срабатывает правило offload по любому входящему или исходящему пакету, весь сеанс окончательно уходит из netfilter в offload.
|
||||||
|
Поэтому скрипты zapret берут правила для NFQUEUE, что они создали, и из них создают exemption правила, которые не дают раньше времени попасть сеансу в offload, а потом его "отпускают".
|
||||||
|
При этом входящим пакетам не дают начать offload, триггером выступают только исходящие пакеты.
|
||||||
|
Эта схема обеспечивает практически нулевой негативный эффект на скорость, одновременно покрывая нужды nfqws и упрощая правила таблиц.
|
||||||
|
|
||||||
|
OpenWrt не предусматривает выборочного управления offload, поэтому скрипты zapret поддерживают свою систему выборочного управления.
|
||||||
|
|
||||||
iptables target `FLOWOFFLOAD` - это проприетарное изобретение OpenWrt.
|
iptables target `FLOWOFFLOAD` - это проприетарное изобретение OpenWrt.
|
||||||
Управление offload в nftables реализовано в базовом ядре linux без патчей.
|
Управление offload в nftables реализовано в базовом ядре linux без патчей.
|
||||||
|
nftables - единственный способ включения offload на классическом Linux.
|
||||||
|
|
||||||
|
|
||||||
## tpws
|
## tpws
|
||||||
@@ -776,6 +795,7 @@ tpws - это transparent proxy.
|
|||||||
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
|
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
|
||||||
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
|
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
|
||||||
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
|
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
|
||||||
|
--version ; вывести версию и выйти
|
||||||
|
|
||||||
--daemon ; демонизировать прогу
|
--daemon ; демонизировать прогу
|
||||||
--pidfile=<file> ; сохранить PID в файл
|
--pidfile=<file> ; сохранить PID в файл
|
||||||
@@ -843,7 +863,7 @@ tpws - это transparent proxy.
|
|||||||
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
|
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
|
||||||
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
|
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
|
||||||
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
|
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
|
||||||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются, если хост не начинается с '^'.
|
||||||
; в файле должен быть хост на каждой строке.
|
; в файле должен быть хост на каждой строке.
|
||||||
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||||||
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||||||
@@ -880,7 +900,7 @@ tpws, как и nfqws, поддерживает множественную се
|
|||||||
Однако, если в момент send уже имеется неотосланный буфер, то ОС присоединит данные к нему,
|
Однако, если в момент send уже имеется неотосланный буфер, то ОС присоединит данные к нему,
|
||||||
никакой отсылки отдельным пакетом не будет. Но в этом случае и так нет никакой гарантии,
|
никакой отсылки отдельным пакетом не будет. Но в этом случае и так нет никакой гарантии,
|
||||||
что какой-то блок сообщения пойдет в начале пакета, на что собственно и заточены DPI.
|
что какой-то блок сообщения пойдет в начале пакета, на что собственно и заточены DPI.
|
||||||
Разбиение будет производится согласно MSS, который зависит от MTU исходящего интерфейса.
|
Разбиение будет производиться согласно MSS, который зависит от MTU исходящего интерфейса.
|
||||||
Таким образом DPI, смотрящие в начало поля данных TCP пакета, будут поломаны в любом случае.
|
Таким образом DPI, смотрящие в начало поля данных TCP пакета, будут поломаны в любом случае.
|
||||||
Протокол http относится к запрос-ответным протоколам. Новое сообщение посылается только тогда,
|
Протокол http относится к запрос-ответным протоколам. Новое сообщение посылается только тогда,
|
||||||
когда сервер получил запрос и полностью вернул ответ. Значит запрос фактически был не только отослан,
|
когда сервер получил запрос и полностью вернул ответ. Значит запрос фактически был не только отослан,
|
||||||
@@ -893,13 +913,15 @@ tpws, как и nfqws, поддерживает множественную се
|
|||||||
указанным сплит позициям. Другие ОС в этом вопросе ведут себя более предсказуемо. Спонтанного обьединения замечено не было.
|
указанным сплит позициям. Другие ОС в этом вопросе ведут себя более предсказуемо. Спонтанного обьединения замечено не было.
|
||||||
Поэтому не стоит злоупотреблять сплитами и в особенности мелкими соседними пакетами.
|
Поэтому не стоит злоупотреблять сплитами и в особенности мелкими соседними пакетами.
|
||||||
|
|
||||||
Как показывается практика, проблемы могут начаться , если количество сплит позиций превышает 8.
|
Как показывается практика, проблемы могут начаться , если количество сплитов более одного.
|
||||||
|
На каких-то системах наблюдался стабильный результат до 8 сплитов, на других проблемы уже начинались после 2 сплитов.
|
||||||
|
Один сплит работает стабильно, если не является частью массивной потоковой передачи.
|
||||||
При неудаче сегментации будет выводиться сообщение `WARNING ! segmentation failed`.
|
При неудаче сегментации будет выводиться сообщение `WARNING ! segmentation failed`.
|
||||||
Если вы его видите, это повод снизить количество сплит позиций.
|
Если вы его видите, это повод снизить количество сплит позиций.
|
||||||
Если это не вариант, для ядер Linux >=4.6 есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части.
|
Если это не вариант, для ядер Linux >=4.6 есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части.
|
||||||
Но этот вариант ломает модель асинхронной обработки событий. Пока идет ожидание, все остальные соединения не обрабатываются
|
Но этот вариант ломает модель асинхронной обработки событий. Пока идет ожидание, все остальные соединения не обрабатываются
|
||||||
и кратковременно подвисают. На практике это может быть совсем небольшое ожидание - менее 10 мс.
|
и кратковременно подвисают. На практике это может быть совсем небольшое ожидание - менее 10 мс.
|
||||||
И производится оно только , если происходит split, и в ожидании есть реальная необходимость.
|
Выполняется оно только , если происходит split, и в ожидании есть реальная необходимость.
|
||||||
В высоконагруженных системах данный вариант не рекомендуется. Но для домашнего использования может подойти, и вы эти задержки даже не заметите.
|
В высоконагруженных системах данный вариант не рекомендуется. Но для домашнего использования может подойти, и вы эти задержки даже не заметите.
|
||||||
|
|
||||||
Если вы пытаетесь сплитнуть массивную передачу с `--split-any-protocol`, когда информация поступает быстрее отсылки,
|
Если вы пытаетесь сплитнуть массивную передачу с `--split-any-protocol`, когда информация поступает быстрее отсылки,
|
||||||
@@ -1066,7 +1088,7 @@ route_localnet :
|
|||||||
динамически вписывать в команду. В любом случае требуются дополнительные усилия. Использование route_localnet тоже имеет
|
динамически вписывать в команду. В любом случае требуются дополнительные усилия. Использование route_localnet тоже имеет
|
||||||
потенциальные проблемы с безопасностью. Вы делаете доступным все, что висит на `127.0.0.0/8` для локальной подсети <
|
потенциальные проблемы с безопасностью. Вы делаете доступным все, что висит на `127.0.0.0/8` для локальной подсети <
|
||||||
внутренний_интерфейс>. Службы обычно привязываются к `127.0.0.1`, поэтому можно средствами iptables запретить входящие
|
внутренний_интерфейс>. Службы обычно привязываются к `127.0.0.1`, поэтому можно средствами iptables запретить входящие
|
||||||
на `127.0.0.1` не с интерфейса lo, либо повесить tpws на любой другой IP из из `127.0.0.0/8`, например на `127.0.0.127`,
|
на `127.0.0.1` не с интерфейса lo, либо повесить tpws на любой другой IP из `127.0.0.0/8`, например на `127.0.0.127`,
|
||||||
и разрешить входящие не с lo только на этот IP.
|
и разрешить входящие не с lo только на этот IP.
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -1115,6 +1137,78 @@ nft add rule inet ztest dnat_pre meta iifname $IFACE_LAN tcp dport { 80, 443 } d
|
|||||||
nft delete table inet ztest
|
nft delete table inet ztest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## ip2net
|
||||||
|
|
||||||
|
Утилита ip2net предназначена для преобразования ipv4 или ipv6 списка ip в список подсетей
|
||||||
|
с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в `stdout`.
|
||||||
|
|
||||||
|
```
|
||||||
|
-4 ; лист - ipv4 (по умолчанию)
|
||||||
|
-6 ; лист - ipv6
|
||||||
|
--prefix-length=min[-max] ; диапазон рассматриваемых длин префиксов. например : 22-30 (ipv4), 56-64 (ipv6)
|
||||||
|
--v4-threshold=mul/div ; ipv4 : включать подсети, в которых заполнено по крайней мере mul/div адресов. например : 3/4
|
||||||
|
--v6-threshold=N ; ipv6 : минимальное количество ip для создания подсети
|
||||||
|
```
|
||||||
|
В списке могут присутствовать записи вида ip/prefix и ip1-ip2. Такие записи выкидываются в stdout без изменений.
|
||||||
|
Они принимаются командой ipset. ipset умеет для листов hash:net из ip1-ip2 делать оптимальное покрытие ip/prefix.
|
||||||
|
ipfw из FreeBSD понимает ip/prefix, но не понимает ip1-ip2.
|
||||||
|
ip2net фильтрует входные данные, выкидывая неправильные IP адреса.
|
||||||
|
|
||||||
|
Выбирается подсеть, в которой присутствует указанный минимум адресов.
|
||||||
|
Для ipv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для ipv6 минимум задается напрямую.
|
||||||
|
|
||||||
|
Размер подсети выбирается следующим алгоритмом:
|
||||||
|
Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально.
|
||||||
|
Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше).
|
||||||
|
Например, заданы параметры v6_threshold=2 prefix_length=32-64, имеются следующие ipv6 :
|
||||||
|
```
|
||||||
|
1234:5678:aaaa::5
|
||||||
|
1234:5678:aaaa::6
|
||||||
|
1234:5678:aaac::5
|
||||||
|
Результат будет :
|
||||||
|
1234:5678:aaa8::/45
|
||||||
|
```
|
||||||
|
Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой,
|
||||||
|
когда те же самые адреса вполне влезают в /45 и их ровно столько же.
|
||||||
|
Если изменить v6_threshold=4, то результат будет:
|
||||||
|
```
|
||||||
|
1234:5678:aaaa::5
|
||||||
|
1234:5678:aaaa::6
|
||||||
|
1234:5678:aaac::5
|
||||||
|
```
|
||||||
|
То есть ip не объединятся в подсеть, потому что их слишком мало.
|
||||||
|
Если изменить `prefix_length=56-64`, результат будет:
|
||||||
|
```
|
||||||
|
1234:5678:aaaa::/64
|
||||||
|
1234:5678:aaac::5
|
||||||
|
```
|
||||||
|
|
||||||
|
Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа.
|
||||||
|
Если ip2net думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов.
|
||||||
|
Учтите, что арифметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем.
|
||||||
|
Не надо делать такое: 5000000/10000000. 1/2 - гораздо лучше.
|
||||||
|
|
||||||
|
## mdig
|
||||||
|
|
||||||
|
Программа предназначена для многопоточного ресолвинга больших листов через системный DNS.
|
||||||
|
Она берет из stdin список доменов и выводит в stdout результат ресолвинга. Ошибки выводятся в stderr.
|
||||||
|
|
||||||
|
```
|
||||||
|
--threads=<threads_number> ; количество потоков. по умолчанию 1.
|
||||||
|
--family=<4|6|46> ; выбор семейства IP адресов : ipv4, ipv6, ipv4+ipv6
|
||||||
|
--verbose ; дебаг-лог на консоль
|
||||||
|
--stats=N ; выводить статистику каждые N доменов
|
||||||
|
--log-resolved=<file> ; сохранять успешно отресолвленные домены в файл
|
||||||
|
--log-failed=<file> ; сохранять неудачно отресолвленные домены в файл
|
||||||
|
--dns-make-query=<domain> ; вывести в stdout бинарный DNS запрос по домену. если --family=6, запрос будет AAAA, иначе A.
|
||||||
|
--dns-parse-query ; распарсить бинарный DNS ответ и выдать все ivp4 и ipv6 адреса из него в stdout
|
||||||
|
```
|
||||||
|
|
||||||
|
Параметры `--dns-make-query` и `--dns-parse-query` позволяют провести ресолвинг одного домена через произвольный канал.
|
||||||
|
Например, следующим образом можно выполнить DoH запрос, используя лишь mdig и curl :
|
||||||
|
```
|
||||||
|
mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Content-Type: application/dns-message" https://cloudflare-dns.com/dns-query | mdig --dns-parse-query
|
||||||
|
```
|
||||||
|
|
||||||
## Способы получения списка заблокированных IP
|
## Способы получения списка заблокированных IP
|
||||||
|
|
||||||
@@ -1213,79 +1307,6 @@ ipfw таблицы в отличие от ipset могут содержать
|
|||||||
Это особенно полезно на BSD системах с PF.
|
Это особенно полезно на BSD системах с PF.
|
||||||
LISTS_RELOAD=- отключает перезагрузку листов.
|
LISTS_RELOAD=- отключает перезагрузку листов.
|
||||||
|
|
||||||
## ip2net
|
|
||||||
|
|
||||||
Утилита ip2net предназначена для преобразования ipv4 или ipv6 списка ip в список подсетей
|
|
||||||
с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в `stdout`.
|
|
||||||
|
|
||||||
```
|
|
||||||
-4 ; лист - ipv4 (по умолчанию)
|
|
||||||
-6 ; лист - ipv6
|
|
||||||
--prefix-length=min[-max] ; диапазон рассматриваемых длин префиксов. например : 22-30 (ipv4), 56-64 (ipv6)
|
|
||||||
--v4-threshold=mul/div ; ipv4 : включать подсети, в которых заполнено по крайней мере mul/div адресов. например : 3/4
|
|
||||||
--v6-threshold=N ; ipv6 : минимальное количество ip для создания подсети
|
|
||||||
```
|
|
||||||
В списке могут присутствовать записи вида ip/prefix и ip1-ip2. Такие записи выкидываются в stdout без изменений.
|
|
||||||
Они принимаются командой ipset. ipset умеет для листов hash:net из ip1-ip2 делать оптимальное покрытие ip/prefix.
|
|
||||||
ipfw из FreeBSD понимает ip/prefix, но не понимает ip1-ip2.
|
|
||||||
ip2net фильтрует входные данные, выкидывая неправильные IP адреса.
|
|
||||||
|
|
||||||
Выбирается подсеть, в которой присутствует указанный минимум адресов.
|
|
||||||
Для ipv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для ipv6 минимум задается напрямую.
|
|
||||||
|
|
||||||
Размер подсети выбирается следующим алгоритмом:
|
|
||||||
Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально.
|
|
||||||
Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше).
|
|
||||||
Например, заданы параметры v6_threshold=2 prefix_length=32-64, имеются следующие ipv6 :
|
|
||||||
```
|
|
||||||
1234:5678:aaaa::5
|
|
||||||
1234:5678:aaaa::6
|
|
||||||
1234:5678:aaac::5
|
|
||||||
Результат будет :
|
|
||||||
1234:5678:aaa8::/45
|
|
||||||
```
|
|
||||||
Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой,
|
|
||||||
когда те же самые адреса вполне влезают в /45 и их ровно столько же.
|
|
||||||
Если изменить v6_threshold=4, то результат будет:
|
|
||||||
```
|
|
||||||
1234:5678:aaaa::5
|
|
||||||
1234:5678:aaaa::6
|
|
||||||
1234:5678:aaac::5
|
|
||||||
```
|
|
||||||
То есть ip не объединятся в подсеть, потому что их слишком мало.
|
|
||||||
Если изменить `prefix_length=56-64`, результат будет:
|
|
||||||
```
|
|
||||||
1234:5678:aaaa::/64
|
|
||||||
1234:5678:aaac::5
|
|
||||||
```
|
|
||||||
|
|
||||||
Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа.
|
|
||||||
Если ip2net думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов.
|
|
||||||
Учтите, что арифметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем.
|
|
||||||
Не надо делать такое: 5000000/10000000. 1/2 - гораздо лучше.
|
|
||||||
|
|
||||||
## mdig
|
|
||||||
|
|
||||||
Программа предназначена для многопоточного ресолвинга больших листов через системный DNS.
|
|
||||||
Она берет из stdin список доменов и выводит в stdout результат ресолвинга. Ошибки выводятся в stderr.
|
|
||||||
|
|
||||||
```
|
|
||||||
--threads=<threads_number> ; количество потоков. по умолчанию 1.
|
|
||||||
--family=<4|6|46> ; выбор семейства IP адресов : ipv4, ipv6, ipv4+ipv6
|
|
||||||
--verbose ; дебаг-лог на консоль
|
|
||||||
--stats=N ; выводить статистику каждые N доменов
|
|
||||||
--log-resolved=<file> ; сохранять успешно отресолвленные домены в файл
|
|
||||||
--log-failed=<file> ; сохранять неудачно отресолвленные домены в файл
|
|
||||||
--dns-make-query=<domain> ; вывести в stdout бинарный DNS запрос по домену. если --family=6, запрос будет AAAA, иначе A.
|
|
||||||
--dns-parse-query ; распарсить бинарный DNS ответ и выдать все ivp4 и ipv6 адреса из него в stdout
|
|
||||||
```
|
|
||||||
|
|
||||||
Параметры `--dns-make-query` и `--dns-parse-query` позволяют провести ресолвинг одного домена через произвольный канал.
|
|
||||||
Например, следующим образом можно выполнить DoH запрос, используя лишь mdig и curl :
|
|
||||||
```
|
|
||||||
mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Content-Type: application/dns-message" https://cloudflare-dns.com/dns-query | mdig --dns-parse-query
|
|
||||||
```
|
|
||||||
|
|
||||||
## Фильтрация по именам доменов
|
## Фильтрация по именам доменов
|
||||||
|
|
||||||
Альтернативой ipset является использование tpws или nfqws со списком доменов.
|
Альтернативой ipset является использование tpws или nfqws со списком доменов.
|
||||||
@@ -1309,10 +1330,11 @@ mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Conte
|
|||||||
При режимах фильтрации `MODE_FILTER=hostlist` или `MODE_FILTER=autohostlist` система запуска передает **nfqws** или **tpws** все листы, файлы которых присутствуют.
|
При режимах фильтрации `MODE_FILTER=hostlist` или `MODE_FILTER=autohostlist` система запуска передает **nfqws** или **tpws** все листы, файлы которых присутствуют.
|
||||||
Передача происходит через замену маркеров `<HOSTLIST>` и `<HOSTLIST_NOAUTO>` на реальные параметры `--hostlist`, `--hostlist-exclude`, `--hostlist-auto`.
|
Передача происходит через замену маркеров `<HOSTLIST>` и `<HOSTLIST_NOAUTO>` на реальные параметры `--hostlist`, `--hostlist-exclude`, `--hostlist-auto`.
|
||||||
Если вдруг листы include присутствуют, но все они пустые, то работа аналогична отсутствию include листа.
|
Если вдруг листы include присутствуют, но все они пустые, то работа аналогична отсутствию include листа.
|
||||||
Файл есть, но не смотря на это дурится все, кроме exclude.
|
Файл есть, но несмотря на это дурится все, кроме exclude.
|
||||||
Если вам нужен именно такой режим - не обязательно удалять `zapret-hosts-users.txt`. Достаточно сделать его пустым.
|
Если вам нужен именно такой режим - не обязательно удалять `zapret-hosts-users.txt`. Достаточно сделать его пустым.
|
||||||
|
|
||||||
Поддомены учитываются автоматически. Например, строчка "ru" вносит в список "*.ru". Строчка "*.ru" в списке не сработает.
|
Поддомены учитываются автоматически. Например, строчка "ru" вносит в список "*.ru". Строчка "*.ru" в списке не сработает.
|
||||||
|
Можно использовать символ `^` в начале хоста, чтобы отказаться от автоматического учета поддоменов.
|
||||||
|
|
||||||
Список доменов РКН может быть получен скриптами
|
Список доменов РКН может быть получен скриптами
|
||||||
```
|
```
|
||||||
@@ -1346,7 +1368,7 @@ tpws и nfqws решают нужно ли применять дурение в
|
|||||||
Крайне рекомендовано использовать ограничитель `connbytes`, чтобы **nfqws** не обрабатывал гигабайты.
|
Крайне рекомендовано использовать ограничитель `connbytes`, чтобы **nfqws** не обрабатывал гигабайты.
|
||||||
По этой же причине не рекомендуется использование режима на BSD системах. Там нет фильтра `connbytes`.
|
По этой же причине не рекомендуется использование режима на BSD системах. Там нет фильтра `connbytes`.
|
||||||
|
|
||||||
На linux системах при использовании nfqws и фильтра connbytes может понадобится :
|
На linux системах при использовании nfqws и фильтра connbytes может понадобиться :
|
||||||
`sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1`
|
`sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1`
|
||||||
Было замечено, что некоторые DPI в России возвращают RST с неверным ACK. Это принимается tcp/ip стеком
|
Было замечено, что некоторые DPI в России возвращают RST с неверным ACK. Это принимается tcp/ip стеком
|
||||||
linux, но через раз приобретает статус INVALID в conntrack. Поэтому правила с `connbytes` срабатывают
|
linux, но через раз приобретает статус INVALID в conntrack. Поэтому правила с `connbytes` срабатывают
|
||||||
@@ -1361,7 +1383,7 @@ linux, но через раз приобретает статус INVALID в con
|
|||||||
свое клиенту. Применяется нечасто, поскольку броузеры на такое ругаются.
|
свое клиенту. Применяется нечасто, поскольку броузеры на такое ругаются.
|
||||||
|
|
||||||
**nfqws** и **tpws** могут сечь варианты 1-3, 4 они не распознают.
|
**nfqws** и **tpws** могут сечь варианты 1-3, 4 они не распознают.
|
||||||
Всилу специфики работы с отдельными пакетами или с TCP каналом tpws и nfqws распознают эти ситуации
|
В силу специфики работы с отдельными пакетами или с TCP каналом tpws и nfqws распознают эти ситуации
|
||||||
по-разному.
|
по-разному.
|
||||||
Что считается ситуацией, похожей на блокировку :
|
Что считается ситуацией, похожей на блокировку :
|
||||||
1) **nfqws** Несколько ретрансмиссий первого запроса в TCP сеансе, в котором имеется host.
|
1) **nfqws** Несколько ретрансмиссий первого запроса в TCP сеансе, в котором имеется host.
|
||||||
@@ -1387,7 +1409,7 @@ linux, но через раз приобретает статус INVALID в con
|
|||||||
Если сайт не ведет себя как заблокированный, значит обход применен не будет.
|
Если сайт не ведет себя как заблокированный, значит обход применен не будет.
|
||||||
В противном случае терять все равно нечего.
|
В противном случае терять все равно нечего.
|
||||||
Однако, могут быть временные сбои сервера, приводящие к ситуации, аналогичной блокировке.
|
Однако, могут быть временные сбои сервера, приводящие к ситуации, аналогичной блокировке.
|
||||||
Могут происходит ложные срабатывания. Если такое произошло, стратегия может начать ломать
|
Могут происходить ложные срабатывания. Если такое произошло, стратегия может начать ломать
|
||||||
незаблокированный сайт. Эту ситуацию, увы, придется вам контролировать вручную.
|
незаблокированный сайт. Эту ситуацию, увы, придется вам контролировать вручную.
|
||||||
Заносите такие домены в `ipset/zapret-hosts-user-exclude.txt`, чтобы избежать повторения.
|
Заносите такие домены в `ipset/zapret-hosts-user-exclude.txt`, чтобы избежать повторения.
|
||||||
Чтобы впоследствии разобраться почему домен был занесен в лист, можно включить `autohostlist debug log`.
|
Чтобы впоследствии разобраться почему домен был занесен в лист, можно включить `autohostlist debug log`.
|
||||||
@@ -1734,7 +1756,7 @@ DISABLE_IPV6=1
|
|||||||
```
|
```
|
||||||
|
|
||||||
Количество потоков для многопоточного DNS ресолвера mdig (1..100).
|
Количество потоков для многопоточного DNS ресолвера mdig (1..100).
|
||||||
Чем их больше, тем быстрее, но не обидется ли на долбежку ваш DNS сервер?\
|
Чем их больше, тем быстрее, но не обидится ли на долбежку ваш DNS сервер?\
|
||||||
`MDIG_THREADS=30`
|
`MDIG_THREADS=30`
|
||||||
|
|
||||||
Место для хранения временных файлов. При скачивании огромных реестров в `/tmp` места может не хватить.
|
Место для хранения временных файлов. При скачивании огромных реестров в `/tmp` места может не хватить.
|
||||||
@@ -1888,7 +1910,7 @@ nfset-ы принадлежат только одной таблице, след
|
|||||||
|
|
||||||
custom скрипты - это маленькие shell программы, управляющие нестандартными режимами применения zapret
|
custom скрипты - это маленькие shell программы, управляющие нестандартными режимами применения zapret
|
||||||
или частными случаями, которые не могут быть интегрированы в основную часть без загромождения и замусоривания кода.
|
или частными случаями, которые не могут быть интегрированы в основную часть без загромождения и замусоривания кода.
|
||||||
Для применеия custom следует помещать файлы в следующие директории в зависимости от вашей системы:
|
Для применения custom следует помещать файлы в следующие директории в зависимости от вашей системы:
|
||||||
```
|
```
|
||||||
/opt/zapret/init.d/sysv/custom.d
|
/opt/zapret/init.d/sysv/custom.d
|
||||||
/opt/zapret/init.d/openwrt/custom.d
|
/opt/zapret/init.d/openwrt/custom.d
|
||||||
@@ -1978,7 +2000,7 @@ zapret_custom_firewall_nft поднимает правила nftables.
|
|||||||
Под OpenWrt все уже сразу готово для использования системы в качестве роутера.
|
Под OpenWrt все уже сразу готово для использования системы в качестве роутера.
|
||||||
Имена интерфейсов WAN и LAN известны из настроек системы.
|
Имена интерфейсов WAN и LAN известны из настроек системы.
|
||||||
Под другими системами роутер вы настраиваете самостоятельно. Инсталлятор в это не вмешивается.
|
Под другими системами роутер вы настраиваете самостоятельно. Инсталлятор в это не вмешивается.
|
||||||
инсталлятор в зависимости от выбранного режима может спросить LAN и WAN интерфейсы.
|
Инсталлятор в зависимости от выбранного режима может спросить LAN и WAN интерфейсы.
|
||||||
Нужно понимать, что заворот проходящего трафика на **tpws** в прозрачном режиме происходит до выполнения маршрутизации,
|
Нужно понимать, что заворот проходящего трафика на **tpws** в прозрачном режиме происходит до выполнения маршрутизации,
|
||||||
следовательно возможна фильтрация по LAN и невозможна по WAN.
|
следовательно возможна фильтрация по LAN и невозможна по WAN.
|
||||||
Решение о завороте на **tpws** локального исходящего трафика принимается после выполнения маршрутизации,
|
Решение о завороте на **tpws** локального исходящего трафика принимается после выполнения маршрутизации,
|
||||||
@@ -1988,6 +2010,15 @@ zapret_custom_firewall_nft поднимает правила nftables.
|
|||||||
|
|
||||||
Деинсталляция выполняется через `uninstall_easy.sh`. После выполнения деинсталляции можно удалить каталог `/opt/zapret`.
|
Деинсталляция выполняется через `uninstall_easy.sh`. После выполнения деинсталляции можно удалить каталог `/opt/zapret`.
|
||||||
|
|
||||||
|
## Установка под systemd
|
||||||
|
|
||||||
|
Если вам нравится systemd и хочется максимально под него заточиться, можно отказаться от скриптов запуска zapret
|
||||||
|
и поднимать инстансы `tpws` и `nfqws` как отдельные юниты systemd. При этом вам придется вручную написать правила iptables/nftables
|
||||||
|
и каким-то образом их поднимать. Например, написать дополнительный systemd unit для этого.
|
||||||
|
Так же требуется собрать бинарники особым образом через `make systemd`.
|
||||||
|
|
||||||
|
В комплекте zapret есть шаблоны `init.d/systemd/{nfqws@.service,tpws@.service}`.
|
||||||
|
Краткий перечень команд для их использования приведен в комментариях в этих файлах.
|
||||||
|
|
||||||
## Простая установка на openwrt
|
## Простая установка на openwrt
|
||||||
|
|
||||||
@@ -2159,7 +2190,7 @@ Wifi сеть - обычно `wlan0`.
|
|||||||
|
|
||||||
tpws работает обычным образом.
|
tpws работает обычным образом.
|
||||||
|
|
||||||
`nfqueue` поломан, можно собрать фиксящий модуль https://github.com/im-0/unfuck-nfqueue-on-e3372h,
|
`nfqueue` поломан, можно собрать фиксящий модуль https://github.com/im-0/unfuck-nfqueue-on-e3372h,
|
||||||
используя исходники с huawei open source. Исходники содержат тулчейн и полусобирающееся,
|
используя исходники с huawei open source. Исходники содержат тулчейн и полусобирающееся,
|
||||||
неактуальное ядро. Конфиг можно взять с рабочего модема из `/proc/config.gz`.
|
неактуальное ядро. Конфиг можно взять с рабочего модема из `/proc/config.gz`.
|
||||||
С помощью этих исходников умельцы могут собрать модуль `unfuck_nfqueue.ko`.
|
С помощью этих исходников умельцы могут собрать модуль `unfuck_nfqueue.ko`.
|
||||||
@@ -2212,10 +2243,10 @@ curl: (7) Failed to connect to www.ru port 80: Host is unreachable
|
|||||||
|
|
||||||
## Другие прошивки
|
## Другие прошивки
|
||||||
|
|
||||||
Для статических бинариков не имеет значения на чем они запущены: PC, android, приставка, роутер, любой другой девайс.
|
Для статических бинарников не имеет значения на чем они запущены: PC, android, приставка, роутер, любой другой девайс.
|
||||||
Подойдет любая прошивка, дистрибутив linux. Статические бинарники запустятся на всем.
|
Подойдет любая прошивка, дистрибутив linux. Статические бинарники запустятся на всем.
|
||||||
Им нужно только ядро с необходимыми опциями сборки или модулями.
|
Им нужно только ядро с необходимыми опциями сборки или модулями.
|
||||||
Но кроме бинариков в проекте используются еще и скрипты, в которых задействуются некоторые
|
Но кроме бинарников в проекте используются еще и скрипты, в которых задействуются некоторые
|
||||||
стандартные программы.
|
стандартные программы.
|
||||||
|
|
||||||
Основные причины почему нельзя просто так взять и установить эту систему на что угодно:
|
Основные причины почему нельзя просто так взять и установить эту систему на что угодно:
|
||||||
@@ -2253,14 +2284,14 @@ entware содержит репозиторий user-mode компонент, к
|
|||||||
_Подробное описание настроек для других прошивок выходит за рамки данного проекта._
|
_Подробное описание настроек для других прошивок выходит за рамки данного проекта._
|
||||||
|
|
||||||
OpenWrt является одной из немногих относительно полноценных linux систем для embedded devices.
|
OpenWrt является одной из немногих относительно полноценных linux систем для embedded devices.
|
||||||
Она характеризуется следующими вещами, которые и послужили основой выбора именно этой прошивк:
|
Она характеризуется следующими вещами, которые и послужили основой выбора именно этой прошивки:
|
||||||
* полный root доступ к девайсу через shell. на заводских прошивках чаще всего отсутствует, на многих альтернативных есть
|
* полный root доступ к девайсу через shell. на заводских прошивках чаще всего отсутствует, на многих альтернативных есть
|
||||||
* корень r/w. это практически уникальная особенность OpenWrt. заводские и большинство альтернативных прошивок
|
* корень r/w. это практически уникальная особенность OpenWrt. заводские и большинство альтернативных прошивок
|
||||||
построены на базе squashfs root (r/o), а конфигурация хранится в специально отформатированной области
|
построены на базе squashfs root (r/o), а конфигурация хранится в специально отформатированной области
|
||||||
встроенной памяти, называемой nvram. не имеющие r/w корня системы сильно кастрированы. они не имеют
|
встроенной памяти, называемой nvram. не имеющие r/w корня системы сильно кастрированы. они не имеют
|
||||||
возможности доустановки ПО из репозитория без специальных вывертов и заточены в основном
|
возможности доустановки ПО из репозитория без специальных вывертов и заточены в основном
|
||||||
на чуть более продвинутого, чем обычно, пользователя и управление имеющимся функционалом через веб интерфейс,
|
на чуть более продвинутого, чем обычно, пользователя и управление имеющимся функционалом через веб интерфейс,
|
||||||
но функционал фиксированно ограничен. альтернативные прошивки как правило могут монтировать r/w раздел
|
но функционал фиксированно ограничен. альтернативные прошивки, как правило, могут монтировать r/w раздел
|
||||||
в какую-то область файловой системы, заводские обычно могут монтировать лишь флэшки, подключенные к USB,
|
в какую-то область файловой системы, заводские обычно могут монтировать лишь флэшки, подключенные к USB,
|
||||||
и не факт, что есть поддержка unix файловых системы. может быть поддержка только fat и ntfs.
|
и не факт, что есть поддержка unix файловых системы. может быть поддержка только fat и ntfs.
|
||||||
* возможность выноса корневой файловой системы на внешний носитель (extroot) или создания на нем оверлея (overlay)
|
* возможность выноса корневой файловой системы на внешний носитель (extroot) или создания на нем оверлея (overlay)
|
||||||
|
65
init.d/systemd/nfqws@.service
Normal file
65
init.d/systemd/nfqws@.service
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# Example systemd service unit for nfqws. Adjust for your installation.
|
||||||
|
|
||||||
|
# WARNING ! This unit requires to compile nfqws using `make systemd`
|
||||||
|
# WARNING ! This makefile target enabled special systemd notify support.
|
||||||
|
|
||||||
|
# PREPARE
|
||||||
|
# install build depends
|
||||||
|
# make -C /opt/zapret systemd
|
||||||
|
# cp nfqws@service /lib/systemd/system
|
||||||
|
# systemctl daemon-reload
|
||||||
|
|
||||||
|
# MANAGE INSTANCE
|
||||||
|
# prepare /etc/zapret/nfqws1.conf with nfqws parameters
|
||||||
|
# systemctl start nfqws@nfqws1
|
||||||
|
# systemctl status nfqws@nfqws1
|
||||||
|
# systemctl restart nfqws@nfqws1
|
||||||
|
# systemctl enable nfqws@nfqws1
|
||||||
|
# systemctl disable nfqws@nfqws1
|
||||||
|
# systemctl stop nfqws@nfqws1
|
||||||
|
|
||||||
|
# DELETE
|
||||||
|
# rm /lib/systemd/system/nfqws@.service
|
||||||
|
# systemctl daemon-reload
|
||||||
|
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
ExecSearchPath=/opt/zapret/binaries/my
|
||||||
|
ExecStart=nfqws @${CONFIG_DIR}/${INSTANCE}.conf
|
||||||
|
Environment=CONFIG_DIR=/etc/zapret
|
||||||
|
Environment=INSTANCE=%i
|
||||||
|
|
||||||
|
RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET
|
||||||
|
|
||||||
|
LockPersonality=true
|
||||||
|
MemoryDenyWriteExecute=true
|
||||||
|
PrivateDevices=true
|
||||||
|
PrivateMounts=true
|
||||||
|
PrivateTmp=true
|
||||||
|
ProcSubset=pid
|
||||||
|
ProtectClock=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
ProtectHome=true
|
||||||
|
ProtectHostname=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectProc=invisible
|
||||||
|
ProtectSystem=full
|
||||||
|
RemoveIPC=true
|
||||||
|
RestrictNamespaces=true
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
SystemCallArchitectures=native
|
||||||
|
SystemCallFilter=@system-service
|
||||||
|
SystemCallFilter=~@resources
|
||||||
|
UMask=0077
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
63
init.d/systemd/tpws@.service
Normal file
63
init.d/systemd/tpws@.service
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# Example systemd service unit for tpws. Adjust for your installation.
|
||||||
|
|
||||||
|
# WARNING ! This unit requires to compile tpws using `make systemd`
|
||||||
|
# WARNING ! This makefile target enabled special systemd notify support.
|
||||||
|
|
||||||
|
# PREPARE
|
||||||
|
# install build depends
|
||||||
|
# make -C /opt/zapret systemd
|
||||||
|
# cp tpws@service /lib/systemd/system
|
||||||
|
# systemctl daemon-reload
|
||||||
|
|
||||||
|
# MANAGE INSTANCE
|
||||||
|
# prepare /etc/zapret/tpws1.conf with tpws parameters
|
||||||
|
# systemctl start tpws@tpws1
|
||||||
|
# systemctl status tpws@tpws1
|
||||||
|
# systemctl restart tpws@tpws1
|
||||||
|
# systemctl enable tpws@tpws1
|
||||||
|
# systemctl disable tpws@tpws1
|
||||||
|
# systemctl stop tpws@tpws1
|
||||||
|
|
||||||
|
# DELETE
|
||||||
|
# rm /lib/systemd/system/tpws@.service
|
||||||
|
# systemctl daemon-reload
|
||||||
|
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
ExecSearchPath=/opt/zapret/binaries/my
|
||||||
|
ExecStart=tpws @${CONFIG_DIR}/${INSTANCE}.conf
|
||||||
|
Environment=CONFIG_DIR=/etc/zapret
|
||||||
|
Environment=INSTANCE=%i
|
||||||
|
|
||||||
|
RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET
|
||||||
|
|
||||||
|
LockPersonality=true
|
||||||
|
MemoryDenyWriteExecute=true
|
||||||
|
PrivateDevices=true
|
||||||
|
PrivateMounts=true
|
||||||
|
PrivateTmp=true
|
||||||
|
ProcSubset=pid
|
||||||
|
ProtectClock=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
ProtectHome=true
|
||||||
|
ProtectHostname=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectProc=invisible
|
||||||
|
ProtectSystem=full
|
||||||
|
RemoveIPC=true
|
||||||
|
RestrictNamespaces=true
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
SystemCallArchitectures=native
|
||||||
|
SystemCallFilter=@system-service
|
||||||
|
UMask=0077
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@@ -69,7 +69,14 @@ check_bins()
|
|||||||
echo found architecture "\"$arch\""
|
echo found architecture "\"$arch\""
|
||||||
elif [ -f "$EXEDIR/Makefile" ] && exists make; then
|
elif [ -f "$EXEDIR/Makefile" ] && exists make; then
|
||||||
echo trying to compile
|
echo trying to compile
|
||||||
[ "$SYSTEM" = "macos" ] && make_target=mac
|
case $SYSTEM in
|
||||||
|
macos)
|
||||||
|
make_target=mac
|
||||||
|
;;
|
||||||
|
systemd)
|
||||||
|
make_target=systemd
|
||||||
|
;;
|
||||||
|
esac
|
||||||
CFLAGS="-march=native ${CFLAGS}" make -C "$EXEDIR" $make_target || {
|
CFLAGS="-march=native ${CFLAGS}" make -C "$EXEDIR" $make_target || {
|
||||||
echo could not compile
|
echo could not compile
|
||||||
make -C "$EXEDIR" clean
|
make -C "$EXEDIR" clean
|
||||||
|
@@ -11,6 +11,8 @@ all: ip2net
|
|||||||
ip2net: $(SRC_FILES)
|
ip2net: $(SRC_FILES)
|
||||||
$(CC) -s $(CFLAGS) -o ip2net $(SRC_FILES) $(LIBS) $(LDFLAGS)
|
$(CC) -s $(CFLAGS) -o ip2net $(SRC_FILES) $(LIBS) $(LDFLAGS)
|
||||||
|
|
||||||
|
systemd: ip2net
|
||||||
|
|
||||||
android: ip2net
|
android: ip2net
|
||||||
|
|
||||||
bsd: $(SRC_FILES)
|
bsd: $(SRC_FILES)
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
|
127.0.0.0/8
|
||||||
10.0.0.0/8
|
10.0.0.0/8
|
||||||
172.16.0.0/12
|
172.16.0.0/12
|
||||||
192.168.0.0/16
|
192.168.0.0/16
|
||||||
169.254.0.0/16
|
169.254.0.0/16
|
||||||
|
::1
|
||||||
fc00::/7
|
fc00::/7
|
||||||
fe80::/10
|
fe80::/10
|
||||||
|
@@ -12,6 +12,8 @@ all: mdig
|
|||||||
mdig: $(SRC_FILES)
|
mdig: $(SRC_FILES)
|
||||||
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS) $(LDFLAGS)
|
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS) $(LDFLAGS)
|
||||||
|
|
||||||
|
systemd: mdig
|
||||||
|
|
||||||
android: $(SRC_FILES)
|
android: $(SRC_FILES)
|
||||||
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS_ANDROID) $(LDFLAGS)
|
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS_ANDROID) $(LDFLAGS)
|
||||||
|
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS += -std=gnu99 -Os -flto=auto
|
CFLAGS += -std=gnu99 -Os -flto=auto
|
||||||
|
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||||
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
||||||
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
|
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
|
||||||
|
LIBS_SYSTEMD = -lsystemd
|
||||||
LIBS_BSD = -lz
|
LIBS_BSD = -lz
|
||||||
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
|
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
|
||||||
LIBS_CYGWIN32 = -lwindivert32
|
LIBS_CYGWIN32 = -lwindivert32
|
||||||
@@ -16,6 +18,9 @@ all: nfqws
|
|||||||
nfqws: $(SRC_FILES)
|
nfqws: $(SRC_FILES)
|
||||||
$(CC) -s $(CFLAGS) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LDFLAGS)
|
$(CC) -s $(CFLAGS) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LDFLAGS)
|
||||||
|
|
||||||
|
systemd: $(SRC_FILES)
|
||||||
|
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||||
|
|
||||||
android: nfqws
|
android: nfqws
|
||||||
|
|
||||||
bsd: $(SRC_FILES)
|
bsd: $(SRC_FILES)
|
||||||
|
BIN
nfq/WinDivert.dll
Normal file
BIN
nfq/WinDivert.dll
Normal file
Binary file not shown.
BIN
nfq/WinDivert64.sys
Normal file
BIN
nfq/WinDivert64.sys
Normal file
Binary file not shown.
@@ -1747,7 +1747,9 @@ nofix:
|
|||||||
bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
|
bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
|
||||||
if (bytes==-1)
|
if (bytes==-1)
|
||||||
{
|
{
|
||||||
DLOG_PERROR("rawsend: sendto");
|
char s[40];
|
||||||
|
snprintf(s,sizeof(s),"rawsend: sendto (%zu)",len);
|
||||||
|
DLOG_PERROR(s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
31
nfq/desync.c
31
nfq/desync.c
@@ -347,14 +347,14 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
|||||||
{
|
{
|
||||||
DLOG("auto hostlist (profile %d) : adding %s to %s\n", dp->n, hostname, dp->hostlist_auto->filename);
|
DLOG("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_auto->hostlist, hostname))
|
if (!HostlistPoolAddStr(&dp->hostlist_auto->hostlist, hostname, 0))
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
if (!file_mod_signature(dp->hostlist_auto->filename, &dp->hostlist_auto->mod_sig))
|
if (!file_mod_signature(dp->hostlist_auto->filename, &dp->hostlist_auto->mod_sig))
|
||||||
@@ -606,17 +606,17 @@ static uint16_t IP4_IP_ID_FIX(const struct ip *ip)
|
|||||||
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
|
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
|
||||||
// size does not change
|
// size does not change
|
||||||
// return : true - altered, false - not altered
|
// return : true - altered, false - not altered
|
||||||
static bool runtime_tls_mod(const struct desync_profile *dp, size_t encap_len, uint8_t *fake_mod)
|
static bool runtime_tls_mod(const struct desync_profile *dp, uint8_t *fake_mod, const uint8_t *payload, size_t payload_len)
|
||||||
{
|
{
|
||||||
bool b=false;
|
bool b=false;
|
||||||
if (dp->fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
|
if (dp->fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
|
||||||
{
|
{
|
||||||
size_t sz_rec = pntoh16(dp->fake_tls+3) + encap_len;
|
size_t sz_rec = pntoh16(dp->fake_tls+3) + payload_len;
|
||||||
size_t sz_handshake = pntoh24(dp->fake_tls+6) + encap_len;
|
size_t sz_handshake = pntoh24(dp->fake_tls+6) + payload_len;
|
||||||
size_t sz_ext = pntoh16(dp->fake_tls+dp->fake_tls_extlen_offset) + encap_len;
|
size_t sz_ext = pntoh16(dp->fake_tls+dp->fake_tls_extlen_offset) + payload_len;
|
||||||
size_t sz_pad = pntoh16(dp->fake_tls+dp->fake_tls_padlen_offset) + encap_len;
|
size_t sz_pad = pntoh16(dp->fake_tls+dp->fake_tls_padlen_offset) + payload_len;
|
||||||
if ((sz_rec & ~0xFFFF) || (sz_handshake & ~0xFFFFFF) || (sz_ext & ~0xFFFF) || (sz_pad & ~0xFFFF))
|
if ((sz_rec & ~0xFFFF) || (sz_handshake & ~0xFFFFFF) || (sz_ext & ~0xFFFF) || (sz_pad & ~0xFFFF))
|
||||||
DLOG("cannot apply tls mod. length overflow.\n");
|
DLOG("cannot apply padencap tls mod. length overflow.\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size);
|
memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size);
|
||||||
@@ -634,6 +634,19 @@ static bool runtime_tls_mod(const struct desync_profile *dp, size_t encap_len, u
|
|||||||
fill_random_bytes(fake_mod+44,fake_mod[43]); // session id
|
fill_random_bytes(fake_mod+44,fake_mod[43]); // session id
|
||||||
b=true;
|
b=true;
|
||||||
}
|
}
|
||||||
|
if (dp->fake_tls_mod & FAKE_TLS_MOD_DUP_SID)
|
||||||
|
{
|
||||||
|
if (dp->fake_tls[43]!=payload[43])
|
||||||
|
DLOG("cannot apply dupsid tls mod. fake and orig session id length mismatch.\n");
|
||||||
|
else if (payload_len<(44+payload[43]))
|
||||||
|
DLOG("cannot apply dupsid tls mod. data payload is not valid.\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!b) memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size);
|
||||||
|
memcpy(fake_mod+44,payload+44,fake_mod[43]); // session id
|
||||||
|
b=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1174,7 +1187,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
fake_size = dp->fake_http_size;
|
fake_size = dp->fake_http_size;
|
||||||
break;
|
break;
|
||||||
case TLS:
|
case TLS:
|
||||||
fake = runtime_tls_mod(dp,rlen_payload,fake_mod) ? fake_mod : dp->fake_tls;
|
fake = runtime_tls_mod(dp,fake_mod,rdata_payload,rlen_payload) ? fake_mod : dp->fake_tls;
|
||||||
fake_size = dp->fake_tls_size;
|
fake_size = dp->fake_tls_size;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
int unique_size_t(size_t *pu, int ct)
|
int unique_size_t(size_t *pu, int ct)
|
||||||
{
|
{
|
||||||
@@ -313,6 +314,17 @@ bool file_mod_signature(const char *filename, file_mod_sig *ms)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool file_open_test(const char *filename, int flags)
|
||||||
|
{
|
||||||
|
int fd = open(filename,flags);
|
||||||
|
if (fd>=0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool pf_in_range(uint16_t port, const port_filter *pf)
|
bool pf_in_range(uint16_t port, const port_filter *pf)
|
||||||
{
|
{
|
||||||
return port && (((!pf->from && !pf->to) || (port>=pf->from && port<=pf->to)) ^ pf->neg);
|
return port && (((!pf->from && !pf->to) || (port>=pf->from && port<=pf->to)) ^ pf->neg);
|
||||||
@@ -379,6 +391,12 @@ void fill_random_az09(uint8_t *p,size_t sz)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_console_io_buffering(void)
|
||||||
|
{
|
||||||
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
setvbuf(stderr, NULL, _IOLBF, 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool set_env_exedir(const char *argv0)
|
bool set_env_exedir(const char *argv0)
|
||||||
{
|
{
|
||||||
char *s,*d;
|
char *s,*d;
|
||||||
|
@@ -77,6 +77,7 @@ typedef struct
|
|||||||
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
|
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
|
||||||
bool file_mod_signature(const char *filename, file_mod_sig *ms);
|
bool file_mod_signature(const char *filename, file_mod_sig *ms);
|
||||||
time_t file_mod_time(const char *filename);
|
time_t file_mod_time(const char *filename);
|
||||||
|
bool file_open_test(const char *filename, int flags);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -91,6 +92,7 @@ void fill_random_bytes(uint8_t *p,size_t sz);
|
|||||||
void fill_random_az(uint8_t *p,size_t sz);
|
void fill_random_az(uint8_t *p,size_t sz);
|
||||||
void fill_random_az09(uint8_t *p,size_t sz);
|
void fill_random_az09(uint8_t *p,size_t sz);
|
||||||
|
|
||||||
|
void set_console_io_buffering(void);
|
||||||
bool set_env_exedir(const char *argv0);
|
bool set_env_exedir(const char *argv0);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
// inplace tolower() and add to pool
|
// inplace tolower() and add to pool
|
||||||
static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct)
|
||||||
{
|
{
|
||||||
char *p=*s;
|
char *p=*s;
|
||||||
|
|
||||||
@@ -17,10 +17,16 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// advance until eol lowering all chars
|
// advance until eol lowering all chars
|
||||||
for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
|
uint32_t flags = 0;
|
||||||
if (!StrPoolAddStrLen(hostlist, *s, p-*s))
|
if (*p=='^')
|
||||||
{
|
{
|
||||||
StrPoolDestroy(hostlist);
|
p = ++(*s);
|
||||||
|
flags |= HOSTLIST_POOL_FLAG_STRICT_MATCH;
|
||||||
|
}
|
||||||
|
for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
|
||||||
|
if (!HostlistPoolAddStrLen(hostlist, *s, p-*s, flags))
|
||||||
|
{
|
||||||
|
HostlistPoolDestroy(hostlist);
|
||||||
*hostlist = NULL;
|
*hostlist = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -32,12 +38,12 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppendHostlistItem(strpool **hostlist, char *s)
|
bool AppendHostlistItem(hostlist_pool **hostlist, char *s)
|
||||||
{
|
{
|
||||||
return addpool(hostlist,&s,s+strlen(s),NULL);
|
return addpool(hostlist,&s,s+strlen(s),NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppendHostList(strpool **hostlist, const char *filename)
|
bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||||
{
|
{
|
||||||
char *p, *e, s[256], *zbuf;
|
char *p, *e, s[256], *zbuf;
|
||||||
size_t zsize;
|
size_t zsize;
|
||||||
@@ -109,14 +115,15 @@ static bool LoadHostList(struct hostlist_file *hfile)
|
|||||||
if (!file_mod_signature(hfile->filename, &fsig))
|
if (!file_mod_signature(hfile->filename, &fsig))
|
||||||
{
|
{
|
||||||
// stat() error
|
// stat() error
|
||||||
|
DLOG_PERROR("file_mod_signature");
|
||||||
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
|
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
|
||||||
StrPoolDestroy(&hfile->hostlist);
|
HostlistPoolDestroy(&hfile->hostlist);
|
||||||
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
||||||
{
|
{
|
||||||
StrPoolDestroy(&hfile->hostlist);
|
HostlistPoolDestroy(&hfile->hostlist);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
hfile->mod_sig=fsig;
|
hfile->mod_sig=fsig;
|
||||||
@@ -137,10 +144,10 @@ static bool LoadHostLists(struct hostlist_files_head *list)
|
|||||||
return bres;
|
return bres;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NonEmptyHostlist(strpool **hostlist)
|
bool NonEmptyHostlist(hostlist_pool **hostlist)
|
||||||
{
|
{
|
||||||
// add impossible hostname if the list is empty
|
// add impossible hostname if the list is empty
|
||||||
return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4);
|
return *hostlist ? true : HostlistPoolAddStrLen(hostlist, "@&()", 4, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MakeAutolistsNonEmpty()
|
static void MakeAutolistsNonEmpty()
|
||||||
@@ -163,19 +170,34 @@ bool LoadAllHostLists()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool SearchHostList(strpool *hostlist, const char *host)
|
static bool SearchHostList(hostlist_pool *hostlist, const char *host)
|
||||||
{
|
{
|
||||||
if (hostlist)
|
if (hostlist)
|
||||||
{
|
{
|
||||||
const char *p = host;
|
const char *p = host;
|
||||||
bool bInHostList;
|
const struct hostlist_pool *hp;
|
||||||
|
bool bHostFull=true;
|
||||||
while (p)
|
while (p)
|
||||||
{
|
{
|
||||||
bInHostList = StrPoolCheckStr(hostlist, p);
|
DLOG("hostlist check for %s : ", p);
|
||||||
DLOG("hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
|
hp = HostlistPoolGetStr(hostlist, p);
|
||||||
if (bInHostList) return true;
|
if (hp)
|
||||||
|
{
|
||||||
|
if ((hp->flags & HOSTLIST_POOL_FLAG_STRICT_MATCH) && !bHostFull)
|
||||||
|
{
|
||||||
|
DLOG("negative : strict_mismatch : %s != %s\n", p, host);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DLOG("positive\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DLOG("negative\n");
|
||||||
p = strchr(p, '.');
|
p = strchr(p, '.');
|
||||||
if (p) p++;
|
if (p) p++;
|
||||||
|
bHostFull = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@@ -4,10 +4,10 @@
|
|||||||
#include "pools.h"
|
#include "pools.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
|
||||||
bool AppendHostlistItem(strpool **hostlist, char *s);
|
bool AppendHostlistItem(hostlist_pool **hostlist, char *s);
|
||||||
bool AppendHostList(strpool **hostlist, const char *filename);
|
bool AppendHostList(hostlist_pool **hostlist, const char *filename);
|
||||||
bool LoadAllHostLists();
|
bool LoadAllHostLists();
|
||||||
bool NonEmptyHostlist(strpool **hostlist);
|
bool NonEmptyHostlist(hostlist_pool **hostlist);
|
||||||
// return : true = apply fooling, false = do not apply
|
// return : true = apply fooling, false = do not apply
|
||||||
bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *excluded, bool bSkipReloadCheck);
|
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);
|
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||||
|
@@ -130,6 +130,7 @@ static bool LoadIpset(struct ipset_file *hfile)
|
|||||||
if (!file_mod_signature(hfile->filename, &fsig))
|
if (!file_mod_signature(hfile->filename, &fsig))
|
||||||
{
|
{
|
||||||
// stat() error
|
// stat() error
|
||||||
|
DLOG_PERROR("file_mod_signature");
|
||||||
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
388
nfq/nfqws.c
388
nfq/nfqws.c
@@ -35,6 +35,10 @@
|
|||||||
#include "win.h"
|
#include "win.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_SYSTEMD
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <libnetfilter_queue/libnetfilter_queue.h>
|
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
#define NF_DROP 0
|
#define NF_DROP 0
|
||||||
@@ -120,6 +124,29 @@ static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool test_list_files()
|
||||||
|
{
|
||||||
|
struct hostlist_file *hfile;
|
||||||
|
struct ipset_file *ifile;
|
||||||
|
|
||||||
|
LIST_FOREACH(hfile, ¶ms.hostlists, next)
|
||||||
|
if (hfile->filename && !file_open_test(hfile->filename, O_RDONLY))
|
||||||
|
{
|
||||||
|
DLOG_PERROR("file_open_test");
|
||||||
|
DLOG_ERR("cannot access hostlist file '%s'\n",hfile->filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LIST_FOREACH(ifile, ¶ms.ipsets, next)
|
||||||
|
if (ifile->filename && !file_open_test(ifile->filename, O_RDONLY))
|
||||||
|
{
|
||||||
|
DLOG_PERROR("file_open_test");
|
||||||
|
DLOG_ERR("cannot access ipset file '%s'\n",ifile->filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
|
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
|
||||||
{
|
{
|
||||||
@@ -248,6 +275,15 @@ exiterr:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void notify_ready(void)
|
||||||
|
{
|
||||||
|
#ifdef USE_SYSTEMD
|
||||||
|
int r = sd_notify(0, "READY=1");
|
||||||
|
if (r < 0)
|
||||||
|
DLOG_ERR("sd_notify: %s\n", strerror(-r));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int nfq_main(void)
|
static int nfq_main(void)
|
||||||
{
|
{
|
||||||
uint8_t buf[16384] __attribute__((aligned));
|
uint8_t buf[16384] __attribute__((aligned));
|
||||||
@@ -257,15 +293,19 @@ static int nfq_main(void)
|
|||||||
ssize_t rd;
|
ssize_t rd;
|
||||||
|
|
||||||
sec_harden();
|
sec_harden();
|
||||||
if (params.droproot && !droproot(params.uid, params.gid))
|
if (params.droproot && !droproot(params.uid, params.gid) || !dropcaps())
|
||||||
return 1;
|
return 1;
|
||||||
print_id();
|
print_id();
|
||||||
|
if (params.droproot && !test_list_files())
|
||||||
|
return 1;
|
||||||
|
|
||||||
pre_desync();
|
pre_desync();
|
||||||
|
|
||||||
if (!nfq_init(&h,&qh))
|
if (!nfq_init(&h,&qh))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
notify_ready();
|
||||||
|
|
||||||
fd = nfq_fd(h);
|
fd = nfq_fd(h);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -357,6 +397,8 @@ static int dvt_main(void)
|
|||||||
if (params.droproot && !droproot(params.uid, params.gid))
|
if (params.droproot && !droproot(params.uid, params.gid))
|
||||||
goto exiterr;
|
goto exiterr;
|
||||||
print_id();
|
print_id();
|
||||||
|
if (params.droproot && !test_list_files())
|
||||||
|
goto exiterr;
|
||||||
|
|
||||||
pre_desync();
|
pre_desync();
|
||||||
|
|
||||||
@@ -457,7 +499,6 @@ static int win_main(const char *windivert_filter)
|
|||||||
if (!logical_net_filter_match())
|
if (!logical_net_filter_match())
|
||||||
{
|
{
|
||||||
DLOG_CONDUP("logical network is not present. waiting it to appear.\n");
|
DLOG_CONDUP("logical network is not present. waiting it to appear.\n");
|
||||||
fflush(stdout);
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (bQuit)
|
if (bQuit)
|
||||||
@@ -470,7 +511,6 @@ static int win_main(const char *windivert_filter)
|
|||||||
}
|
}
|
||||||
while (!logical_net_filter_match());
|
while (!logical_net_filter_match());
|
||||||
DLOG_CONDUP("logical network now present\n");
|
DLOG_CONDUP("logical network now present\n");
|
||||||
fflush(stdout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!windivert_init(windivert_filter))
|
if (!windivert_init(windivert_filter))
|
||||||
@@ -481,10 +521,6 @@ static int win_main(const char *windivert_filter)
|
|||||||
|
|
||||||
DLOG_CONDUP("windivert initialized. capture is started.\n");
|
DLOG_CONDUP("windivert initialized. capture is started.\n");
|
||||||
|
|
||||||
// cygwin auto flush fails when piping
|
|
||||||
fflush(stdout);
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
for (id=0;;id++)
|
for (id=0;;id++)
|
||||||
{
|
{
|
||||||
len = sizeof(packet);
|
len = sizeof(packet);
|
||||||
@@ -547,10 +583,6 @@ static int win_main(const char *windivert_filter)
|
|||||||
default:
|
default:
|
||||||
DLOG("packet: id=%u drop\n", id);
|
DLOG("packet: id=%u drop\n", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cygwin auto flush fails when piping
|
|
||||||
fflush(stdout);
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
win_dark_deinit();
|
win_dark_deinit();
|
||||||
@@ -874,7 +906,7 @@ static bool parse_split_pos_list(char *opt, struct proto_pos *splits, int splits
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_domain_list(char *opt, strpool **pp)
|
static bool parse_domain_list(char *opt, hostlist_pool **pp)
|
||||||
{
|
{
|
||||||
char *e,*p,c;
|
char *e,*p,c;
|
||||||
|
|
||||||
@@ -934,6 +966,8 @@ static bool parse_tlsmod_list(char *opt, uint8_t *mod)
|
|||||||
*mod |= FAKE_TLS_MOD_RND_SNI;
|
*mod |= FAKE_TLS_MOD_RND_SNI;
|
||||||
else if (!strcmp(p,"padencap"))
|
else if (!strcmp(p,"padencap"))
|
||||||
*mod |= FAKE_TLS_MOD_PADENCAP;
|
*mod |= FAKE_TLS_MOD_PADENCAP;
|
||||||
|
else if (!strcmp(p,"dupsid"))
|
||||||
|
*mod |= FAKE_TLS_MOD_DUP_SID;
|
||||||
else if (strcmp(p,"none"))
|
else if (strcmp(p,"none"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -979,10 +1013,10 @@ static void onetime_tls_mod(struct desync_profile *dp)
|
|||||||
size_t extlen, slen;
|
size_t extlen, slen;
|
||||||
|
|
||||||
if (dp->n && !(dp->fake_tls_mod & (FAKE_TLS_MOD_SET|FAKE_TLS_MOD_CUSTOM_FAKE)))
|
if (dp->n && !(dp->fake_tls_mod & (FAKE_TLS_MOD_SET|FAKE_TLS_MOD_CUSTOM_FAKE)))
|
||||||
dp->fake_tls_mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI; // old behavior compat
|
dp->fake_tls_mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_DUP_SID; // old behavior compat + dup_sid
|
||||||
if (!(dp->fake_tls_mod & ~FAKE_TLS_MOD_SAVE_MASK))
|
if (!(dp->fake_tls_mod & ~FAKE_TLS_MOD_SAVE_MASK))
|
||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
if (!IsTLSClientHello(dp->fake_tls,dp->fake_tls_size,false))
|
if (!IsTLSClientHello(dp->fake_tls,dp->fake_tls_size,false) || (dp->fake_tls_size<(44+dp->fake_tls[43]))) // has session id ?
|
||||||
{
|
{
|
||||||
DLOG_ERR("profile %d tls mod set but tls fake structure invalid\n", dp->n);
|
DLOG_ERR("profile %d tls mod set but tls fake structure invalid\n", dp->n);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@@ -1201,6 +1235,7 @@ static void exithelp(void)
|
|||||||
" @<config_file>|$<config_file>\t\t\t; read file for options. must be the only argument. other options are ignored.\n\n"
|
" @<config_file>|$<config_file>\t\t\t; read file for options. must be the only argument. other options are ignored.\n\n"
|
||||||
#endif
|
#endif
|
||||||
" --debug=0|1|syslog|@<filename>\n"
|
" --debug=0|1|syslog|@<filename>\n"
|
||||||
|
" --version\t\t\t\t\t; print version and exit\n"
|
||||||
" --dry-run\t\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
" --dry-run\t\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
||||||
" --comment=any_text\n"
|
" --comment=any_text\n"
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@@ -1291,7 +1326,7 @@ static void exithelp(void)
|
|||||||
" --dpi-desync-any-protocol=0|1\t\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n"
|
" --dpi-desync-any-protocol=0|1\t\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n"
|
||||||
" --dpi-desync-fake-http=<filename>|0xHEX\t; file containing fake http request\n"
|
" --dpi-desync-fake-http=<filename>|0xHEX\t; file containing fake http request\n"
|
||||||
" --dpi-desync-fake-tls=<filename>|0xHEX\t\t; file containing fake TLS ClientHello (for https)\n"
|
" --dpi-desync-fake-tls=<filename>|0xHEX\t\t; file containing fake TLS ClientHello (for https)\n"
|
||||||
" --dpi-desync-fake-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,padencap\n"
|
" --dpi-desync-fake-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,dupsid,padencap\n"
|
||||||
" --dpi-desync-fake-unknown=<filename>|0xHEX\t; file containing unknown protocol fake payload\n"
|
" --dpi-desync-fake-unknown=<filename>|0xHEX\t; file containing unknown protocol fake payload\n"
|
||||||
" --dpi-desync-fake-syndata=<filename>|0xHEX\t; file containing SYN data payload\n"
|
" --dpi-desync-fake-syndata=<filename>|0xHEX\t; file containing SYN data payload\n"
|
||||||
" --dpi-desync-fake-quic=<filename>|0xHEX\t; file containing fake QUIC Initial\n"
|
" --dpi-desync-fake-quic=<filename>|0xHEX\t; file containing fake QUIC Initial\n"
|
||||||
@@ -1379,6 +1414,7 @@ void check_dp(const struct desync_profile *dp)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
set_console_io_buffering();
|
||||||
set_env_exedir(argv[0]);
|
set_env_exedir(argv[0]);
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
@@ -1459,33 +1495,34 @@ int main(int argc, char **argv)
|
|||||||
const struct option long_options[] = {
|
const struct option long_options[] = {
|
||||||
{"debug",optional_argument,0,0}, // optidx=0
|
{"debug",optional_argument,0,0}, // optidx=0
|
||||||
{"dry-run",no_argument,0,0}, // optidx=1
|
{"dry-run",no_argument,0,0}, // optidx=1
|
||||||
{"comment",optional_argument,0,0}, // optidx=2
|
{"version",no_argument,0,0}, // optidx=2
|
||||||
|
{"comment",optional_argument,0,0}, // optidx=3
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{"qnum",required_argument,0,0}, // optidx=3
|
{"qnum",required_argument,0,0}, // optidx=4
|
||||||
#elif defined(BSD)
|
#elif defined(BSD)
|
||||||
{"port",required_argument,0,0}, // optidx=3
|
{"port",required_argument,0,0}, // optidx=4
|
||||||
#else
|
#else
|
||||||
{"disabled_argument_1",no_argument,0,0},// optidx=3
|
{"disabled_argument_1",no_argument,0,0},// optidx=4
|
||||||
#endif
|
#endif
|
||||||
{"daemon",no_argument,0,0}, // optidx=4
|
{"daemon",no_argument,0,0}, // optidx=5
|
||||||
{"pidfile",required_argument,0,0}, // optidx=5
|
{"pidfile",required_argument,0,0}, // optidx=6
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
{"user",required_argument,0,0 }, // optidx=6
|
{"user",required_argument,0,0 }, // optidx=7
|
||||||
{"uid",required_argument,0,0 }, // optidx=7
|
{"uid",required_argument,0,0 }, // optidx=8
|
||||||
#else
|
#else
|
||||||
{"disabled_argument_2",no_argument,0,0}, // optidx=6
|
{"disabled_argument_2",no_argument,0,0}, // optidx=7
|
||||||
{"disabled_argument_3",no_argument,0,0}, // optidx=7
|
{"disabled_argument_3",no_argument,0,0}, // optidx=8
|
||||||
#endif
|
#endif
|
||||||
{"wsize",required_argument,0,0}, // optidx=8
|
{"wsize",required_argument,0,0}, // optidx=9
|
||||||
{"wssize",required_argument,0,0}, // optidx=9
|
{"wssize",required_argument,0,0}, // optidx=10
|
||||||
{"wssize-cutoff",required_argument,0,0},// optidx=10
|
{"wssize-cutoff",required_argument,0,0},// optidx=11
|
||||||
{"ctrack-timeouts",required_argument,0,0},// optidx=11
|
{"ctrack-timeouts",required_argument,0,0},// optidx=12
|
||||||
{"hostcase",no_argument,0,0}, // optidx=12
|
{"hostcase",no_argument,0,0}, // optidx=13
|
||||||
{"hostspell",required_argument,0,0}, // optidx=13
|
{"hostspell",required_argument,0,0}, // optidx=14
|
||||||
{"hostnospace",no_argument,0,0}, // optidx=14
|
{"hostnospace",no_argument,0,0}, // optidx=15
|
||||||
{"domcase",no_argument,0,0 }, // optidx=15
|
{"domcase",no_argument,0,0 }, // optidx=16
|
||||||
{"methodeol",no_argument,0,0 }, // optidx=16
|
{"methodeol",no_argument,0,0 }, // optidx=17
|
||||||
{"dpi-desync",required_argument,0,0}, // optidx=17
|
{"dpi-desync",required_argument,0,0}, // optidx=18
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=18
|
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=18
|
||||||
#elif defined(SO_USER_COOKIE)
|
#elif defined(SO_USER_COOKIE)
|
||||||
@@ -1493,69 +1530,69 @@ int main(int argc, char **argv)
|
|||||||
#else
|
#else
|
||||||
{"disabled_argument_4",no_argument,0,0}, // optidx=18
|
{"disabled_argument_4",no_argument,0,0}, // optidx=18
|
||||||
#endif
|
#endif
|
||||||
{"dpi-desync-ttl",required_argument,0,0}, // optidx=19
|
{"dpi-desync-ttl",required_argument,0,0}, // optidx=20
|
||||||
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=20
|
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=21
|
||||||
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=21
|
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=22
|
||||||
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=22
|
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=23
|
||||||
{"dpi-desync-fooling",required_argument,0,0}, // optidx=23
|
{"dpi-desync-fooling",required_argument,0,0}, // optidx=24
|
||||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=24
|
{"dpi-desync-repeats",required_argument,0,0}, // optidx=25
|
||||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=25
|
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=26
|
||||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=26
|
{"dpi-desync-split-pos",required_argument,0,0},// optidx=27
|
||||||
{"dpi-desync-split-http-req",required_argument,0,0 },// optidx=27
|
{"dpi-desync-split-http-req",required_argument,0,0 },// optidx=28
|
||||||
{"dpi-desync-split-tls",required_argument,0,0 },// optidx=28
|
{"dpi-desync-split-tls",required_argument,0,0 },// optidx=29
|
||||||
{"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=29
|
{"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=30
|
||||||
{"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=30
|
{"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=31
|
||||||
{"dpi-desync-fakedsplit-pattern",required_argument,0,0 },// optidx=31
|
{"dpi-desync-fakedsplit-pattern",required_argument,0,0 },// optidx=32
|
||||||
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=32
|
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=33
|
||||||
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=33
|
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=34
|
||||||
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=34
|
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=35
|
||||||
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=35
|
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=36
|
||||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=36
|
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=37
|
||||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=37
|
{"dpi-desync-fake-http",required_argument,0,0},// optidx=38
|
||||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=38
|
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=39
|
||||||
{"dpi-desync-fake-tls-mod",required_argument,0,0},// optidx=39
|
{"dpi-desync-fake-tls-mod",required_argument,0,0},// optidx=40
|
||||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=40
|
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=41
|
||||||
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=41
|
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=42
|
||||||
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=42
|
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=43
|
||||||
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=43
|
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=44
|
||||||
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=44
|
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=45
|
||||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=45
|
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=46
|
||||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=46
|
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=47
|
||||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=47
|
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=48
|
||||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=48
|
{"dpi-desync-cutoff",required_argument,0,0},// optidx=49
|
||||||
{"dpi-desync-start",required_argument,0,0},// optidx=49
|
{"dpi-desync-start",required_argument,0,0},// optidx=50
|
||||||
{"hostlist",required_argument,0,0}, // optidx=50
|
{"hostlist",required_argument,0,0}, // optidx=51
|
||||||
{"hostlist-domains",required_argument,0,0},// optidx=51
|
{"hostlist-domains",required_argument,0,0},// optidx=52
|
||||||
{"hostlist-exclude",required_argument,0,0}, // optidx=52
|
{"hostlist-exclude",required_argument,0,0}, // optidx=53
|
||||||
{"hostlist-exclude-domains",required_argument,0,0},// optidx=53
|
{"hostlist-exclude-domains",required_argument,0,0},// optidx=54
|
||||||
{"hostlist-auto",required_argument,0,0}, // optidx=54
|
{"hostlist-auto",required_argument,0,0}, // optidx=55
|
||||||
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=55
|
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=56
|
||||||
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=56
|
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=57
|
||||||
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=57
|
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=58
|
||||||
{"hostlist-auto-debug",required_argument,0,0}, // optidx=58
|
{"hostlist-auto-debug",required_argument,0,0}, // optidx=59
|
||||||
{"new",no_argument,0,0}, // optidx=59
|
{"new",no_argument,0,0}, // optidx=60
|
||||||
{"skip",no_argument,0,0}, // optidx=60
|
{"skip",no_argument,0,0}, // optidx=61
|
||||||
{"filter-l3",required_argument,0,0}, // optidx=61
|
{"filter-l3",required_argument,0,0}, // optidx=62
|
||||||
{"filter-tcp",required_argument,0,0}, // optidx=62
|
{"filter-tcp",required_argument,0,0}, // optidx=63
|
||||||
{"filter-udp",required_argument,0,0}, // optidx=63
|
{"filter-udp",required_argument,0,0}, // optidx=64
|
||||||
{"filter-l7",required_argument,0,0}, // optidx=64
|
{"filter-l7",required_argument,0,0}, // optidx=65
|
||||||
{"ipset",required_argument,0,0}, // optidx=65
|
{"ipset",required_argument,0,0}, // optidx=66
|
||||||
{"ipset-ip",required_argument,0,0}, // optidx=66
|
{"ipset-ip",required_argument,0,0}, // optidx=67
|
||||||
{"ipset-exclude",required_argument,0,0},// optidx=67
|
{"ipset-exclude",required_argument,0,0},// optidx=68
|
||||||
{"ipset-exclude-ip",required_argument,0,0}, // optidx=68
|
{"ipset-exclude-ip",required_argument,0,0}, // optidx=69
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{"bind-fix4",no_argument,0,0}, // optidx=69
|
{"bind-fix4",no_argument,0,0}, // optidx=70
|
||||||
{"bind-fix6",no_argument,0,0}, // optidx=70
|
{"bind-fix6",no_argument,0,0}, // optidx=71
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
{"wf-iface",required_argument,0,0}, // optidx=69
|
{"wf-iface",required_argument,0,0}, // optidx=70
|
||||||
{"wf-l3",required_argument,0,0}, // optidx=70
|
{"wf-l3",required_argument,0,0}, // optidx=71
|
||||||
{"wf-tcp",required_argument,0,0}, // optidx=71
|
{"wf-tcp",required_argument,0,0}, // optidx=72
|
||||||
{"wf-udp",required_argument,0,0}, // optidx=72
|
{"wf-udp",required_argument,0,0}, // optidx=73
|
||||||
{"wf-raw",required_argument,0,0}, // optidx=73
|
{"wf-raw",required_argument,0,0}, // optidx=74
|
||||||
{"wf-save",required_argument,0,0}, // optidx=74
|
{"wf-save",required_argument,0,0}, // optidx=75
|
||||||
{"ssid-filter",required_argument,0,0}, // optidx=75
|
{"ssid-filter",required_argument,0,0}, // optidx=76
|
||||||
{"nlm-filter",required_argument,0,0}, // optidx=76
|
{"nlm-filter",required_argument,0,0}, // optidx=77
|
||||||
{"nlm-list",optional_argument,0,0}, // optidx=77
|
{"nlm-list",optional_argument,0,0}, // optidx=78
|
||||||
#endif
|
#endif
|
||||||
{NULL,0,NULL,0}
|
{NULL,0,NULL,0}
|
||||||
};
|
};
|
||||||
@@ -1608,9 +1645,12 @@ int main(int argc, char **argv)
|
|||||||
case 1: /* dry-run */
|
case 1: /* dry-run */
|
||||||
bDry=true;
|
bDry=true;
|
||||||
break;
|
break;
|
||||||
case 2: /* comment */
|
case 2: /* version */
|
||||||
|
exit_clean(0);
|
||||||
break;
|
break;
|
||||||
case 3: /* qnum or port */
|
case 3: /* comment */
|
||||||
|
break;
|
||||||
|
case 4: /* qnum or port */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.qnum = atoi(optarg);
|
params.qnum = atoi(optarg);
|
||||||
if (params.qnum < 0 || params.qnum>65535)
|
if (params.qnum < 0 || params.qnum>65535)
|
||||||
@@ -1630,15 +1670,15 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 4: /* daemon */
|
case 5: /* daemon */
|
||||||
daemon = true;
|
daemon = true;
|
||||||
break;
|
break;
|
||||||
case 5: /* pidfile */
|
case 6: /* pidfile */
|
||||||
strncpy(pidfile, optarg, sizeof(pidfile));
|
strncpy(pidfile, optarg, sizeof(pidfile));
|
||||||
pidfile[sizeof(pidfile) - 1] = '\0';
|
pidfile[sizeof(pidfile) - 1] = '\0';
|
||||||
break;
|
break;
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
case 6: /* user */
|
case 7: /* user */
|
||||||
{
|
{
|
||||||
struct passwd *pwd = getpwnam(optarg);
|
struct passwd *pwd = getpwnam(optarg);
|
||||||
if (!pwd)
|
if (!pwd)
|
||||||
@@ -1651,7 +1691,7 @@ int main(int argc, char **argv)
|
|||||||
params.droproot = true;
|
params.droproot = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: /* uid */
|
case 8: /* uid */
|
||||||
params.gid = 0x7FFFFFFF; // default gid. drop gid=0
|
params.gid = 0x7FFFFFFF; // default gid. drop gid=0
|
||||||
params.droproot = true;
|
params.droproot = true;
|
||||||
if (sscanf(optarg, "%u:%u", ¶ms.uid, ¶ms.gid)<1)
|
if (sscanf(optarg, "%u:%u", ¶ms.uid, ¶ms.gid)<1)
|
||||||
@@ -1661,32 +1701,32 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 8: /* wsize */
|
case 9: /* wsize */
|
||||||
if (!parse_ws_scale_factor(optarg,&dp->wsize,&dp->wscale))
|
if (!parse_ws_scale_factor(optarg,&dp->wsize,&dp->wscale))
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
break;
|
break;
|
||||||
case 9: /* wssize */
|
case 10: /* wssize */
|
||||||
if (!parse_ws_scale_factor(optarg,&dp->wssize,&dp->wsscale))
|
if (!parse_ws_scale_factor(optarg,&dp->wssize,&dp->wsscale))
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
break;
|
break;
|
||||||
case 10: /* wssize-cutoff */
|
case 11: /* wssize-cutoff */
|
||||||
if (!parse_cutoff(optarg, &dp->wssize_cutoff, &dp->wssize_cutoff_mode))
|
if (!parse_cutoff(optarg, &dp->wssize_cutoff, &dp->wssize_cutoff_mode))
|
||||||
{
|
{
|
||||||
DLOG_ERR("invalid wssize-cutoff value\n");
|
DLOG_ERR("invalid wssize-cutoff value\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 11: /* ctrack-timeouts */
|
case 12: /* ctrack-timeouts */
|
||||||
if (sscanf(optarg, "%u:%u:%u:%u", ¶ms.ctrack_t_syn, ¶ms.ctrack_t_est, ¶ms.ctrack_t_fin, ¶ms.ctrack_t_udp)<3)
|
if (sscanf(optarg, "%u:%u:%u:%u", ¶ms.ctrack_t_syn, ¶ms.ctrack_t_est, ¶ms.ctrack_t_fin, ¶ms.ctrack_t_udp)<3)
|
||||||
{
|
{
|
||||||
DLOG_ERR("invalid ctrack-timeouts value\n");
|
DLOG_ERR("invalid ctrack-timeouts value\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 12: /* hostcase */
|
case 13: /* hostcase */
|
||||||
dp->hostcase = true;
|
dp->hostcase = true;
|
||||||
break;
|
break;
|
||||||
case 13: /* hostspell */
|
case 14: /* hostspell */
|
||||||
if (strlen(optarg) != 4)
|
if (strlen(optarg) != 4)
|
||||||
{
|
{
|
||||||
DLOG_ERR("hostspell must be exactly 4 chars long\n");
|
DLOG_ERR("hostspell must be exactly 4 chars long\n");
|
||||||
@@ -1695,7 +1735,7 @@ int main(int argc, char **argv)
|
|||||||
dp->hostcase = true;
|
dp->hostcase = true;
|
||||||
memcpy(dp->hostspell, optarg, 4);
|
memcpy(dp->hostspell, optarg, 4);
|
||||||
break;
|
break;
|
||||||
case 14: /* hostnospace */
|
case 15: /* hostnospace */
|
||||||
if (dp->methodeol)
|
if (dp->methodeol)
|
||||||
{
|
{
|
||||||
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
|
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
|
||||||
@@ -1703,10 +1743,10 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
dp->hostnospace = true;
|
dp->hostnospace = true;
|
||||||
break;
|
break;
|
||||||
case 15: /* domcase */
|
case 16: /* domcase */
|
||||||
dp->domcase = true;
|
dp->domcase = true;
|
||||||
break;
|
break;
|
||||||
case 16: /* methodeol */
|
case 17: /* methodeol */
|
||||||
if (dp->hostnospace)
|
if (dp->hostnospace)
|
||||||
{
|
{
|
||||||
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
|
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
|
||||||
@@ -1714,7 +1754,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
dp->methodeol = true;
|
dp->methodeol = true;
|
||||||
break;
|
break;
|
||||||
case 17: /* dpi-desync */
|
case 18: /* dpi-desync */
|
||||||
{
|
{
|
||||||
char *mode=optarg,*mode2,*mode3;
|
char *mode=optarg,*mode2,*mode3;
|
||||||
mode2 = mode ? strchr(mode,',') : NULL;
|
mode2 = mode ? strchr(mode,',') : NULL;
|
||||||
@@ -1760,7 +1800,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
case 18: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
case 19: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||||
params.desync_fwmark = 0;
|
params.desync_fwmark = 0;
|
||||||
if (sscanf(optarg, "0x%X", ¶ms.desync_fwmark)<=0) sscanf(optarg, "%u", ¶ms.desync_fwmark);
|
if (sscanf(optarg, "0x%X", ¶ms.desync_fwmark)<=0) sscanf(optarg, "%u", ¶ms.desync_fwmark);
|
||||||
@@ -1775,27 +1815,27 @@ int main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 19: /* dpi-desync-ttl */
|
case 20: /* dpi-desync-ttl */
|
||||||
dp->desync_ttl = (uint8_t)atoi(optarg);
|
dp->desync_ttl = (uint8_t)atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 20: /* dpi-desync-ttl6 */
|
case 21: /* dpi-desync-ttl6 */
|
||||||
dp->desync_ttl6 = (uint8_t)atoi(optarg);
|
dp->desync_ttl6 = (uint8_t)atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 21: /* dpi-desync-autottl */
|
case 22: /* dpi-desync-autottl */
|
||||||
if (!parse_autottl(optarg, &dp->desync_autottl))
|
if (!parse_autottl(optarg, &dp->desync_autottl))
|
||||||
{
|
{
|
||||||
DLOG_ERR("dpi-desync-autottl value error\n");
|
DLOG_ERR("dpi-desync-autottl value error\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 22: /* dpi-desync-autottl6 */
|
case 23: /* dpi-desync-autottl6 */
|
||||||
if (!parse_autottl(optarg, &dp->desync_autottl6))
|
if (!parse_autottl(optarg, &dp->desync_autottl6))
|
||||||
{
|
{
|
||||||
DLOG_ERR("dpi-desync-autottl6 value error\n");
|
DLOG_ERR("dpi-desync-autottl6 value error\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 23: /* dpi-desync-fooling */
|
case 24: /* dpi-desync-fooling */
|
||||||
{
|
{
|
||||||
char *e,*p = optarg;
|
char *e,*p = optarg;
|
||||||
while (p)
|
while (p)
|
||||||
@@ -1830,17 +1870,17 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 24: /* dpi-desync-repeats */
|
case 25: /* dpi-desync-repeats */
|
||||||
if (sscanf(optarg,"%u",&dp->desync_repeats)<1 || !dp->desync_repeats || dp->desync_repeats>20)
|
if (sscanf(optarg,"%u",&dp->desync_repeats)<1 || !dp->desync_repeats || dp->desync_repeats>20)
|
||||||
{
|
{
|
||||||
DLOG_ERR("dpi-desync-repeats must be within 1..20\n");
|
DLOG_ERR("dpi-desync-repeats must be within 1..20\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 25: /* dpi-desync-skip-nosni */
|
case 26: /* dpi-desync-skip-nosni */
|
||||||
dp->desync_skip_nosni = !optarg || atoi(optarg);
|
dp->desync_skip_nosni = !optarg || atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 26: /* dpi-desync-split-pos */
|
case 27: /* dpi-desync-split-pos */
|
||||||
{
|
{
|
||||||
int ct;
|
int ct;
|
||||||
if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct))
|
if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct))
|
||||||
@@ -1851,7 +1891,7 @@ int main(int argc, char **argv)
|
|||||||
dp->split_count += ct;
|
dp->split_count += ct;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 27: /* dpi-desync-split-http-req */
|
case 28: /* dpi-desync-split-http-req */
|
||||||
// obsolete arg
|
// obsolete arg
|
||||||
DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
|
DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
|
||||||
if (dp->split_count>=MAX_SPLITS)
|
if (dp->split_count>=MAX_SPLITS)
|
||||||
@@ -1866,7 +1906,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
dp->split_count++;
|
dp->split_count++;
|
||||||
break;
|
break;
|
||||||
case 28: /* dpi-desync-split-tls */
|
case 29: /* dpi-desync-split-tls */
|
||||||
// obsolete arg
|
// obsolete arg
|
||||||
DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
|
DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
|
||||||
if (dp->split_count>=MAX_SPLITS)
|
if (dp->split_count>=MAX_SPLITS)
|
||||||
@@ -1881,7 +1921,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
dp->split_count++;
|
dp->split_count++;
|
||||||
break;
|
break;
|
||||||
case 29: /* dpi-desync-split-seqovl */
|
case 30: /* dpi-desync-split-seqovl */
|
||||||
if (!strcmp(optarg,"0"))
|
if (!strcmp(optarg,"0"))
|
||||||
{
|
{
|
||||||
// allow zero = disable seqovl
|
// allow zero = disable seqovl
|
||||||
@@ -1894,7 +1934,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 30: /* dpi-desync-split-seqovl-pattern */
|
case 31: /* dpi-desync-split-seqovl-pattern */
|
||||||
{
|
{
|
||||||
char buf[sizeof(dp->seqovl_pattern)];
|
char buf[sizeof(dp->seqovl_pattern)];
|
||||||
size_t sz=sizeof(buf);
|
size_t sz=sizeof(buf);
|
||||||
@@ -1902,7 +1942,7 @@ int main(int argc, char **argv)
|
|||||||
fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz);
|
fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 31: /* dpi-desync-fakedsplit-pattern */
|
case 32: /* dpi-desync-fakedsplit-pattern */
|
||||||
{
|
{
|
||||||
char buf[sizeof(dp->fsplit_pattern)];
|
char buf[sizeof(dp->fsplit_pattern)];
|
||||||
size_t sz=sizeof(buf);
|
size_t sz=sizeof(buf);
|
||||||
@@ -1910,7 +1950,7 @@ int main(int argc, char **argv)
|
|||||||
fill_pattern(dp->fsplit_pattern,sizeof(dp->fsplit_pattern),buf,sz);
|
fill_pattern(dp->fsplit_pattern,sizeof(dp->fsplit_pattern),buf,sz);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 32: /* dpi-desync-ipfrag-pos-tcp */
|
case 33: /* dpi-desync-ipfrag-pos-tcp */
|
||||||
if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_tcp)<1 || dp->desync_ipfrag_pos_tcp<1 || dp->desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN)
|
if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_tcp)<1 || dp->desync_ipfrag_pos_tcp<1 || dp->desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN)
|
||||||
{
|
{
|
||||||
DLOG_ERR("dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
DLOG_ERR("dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||||
@@ -1922,7 +1962,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 33: /* dpi-desync-ipfrag-pos-udp */
|
case 34: /* dpi-desync-ipfrag-pos-udp */
|
||||||
if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_udp)<1 || dp->desync_ipfrag_pos_udp<1 || dp->desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN)
|
if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_udp)<1 || dp->desync_ipfrag_pos_udp<1 || dp->desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN)
|
||||||
{
|
{
|
||||||
DLOG_ERR("dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
DLOG_ERR("dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||||
@@ -1934,71 +1974,71 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 34: /* dpi-desync-badseq-increments */
|
case 35: /* dpi-desync-badseq-increments */
|
||||||
if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment))
|
if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment))
|
||||||
{
|
{
|
||||||
DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
|
DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 35: /* dpi-desync-badack-increment */
|
case 36: /* dpi-desync-badack-increment */
|
||||||
if (!parse_badseq_increment(optarg,&dp->desync_badseq_ack_increment))
|
if (!parse_badseq_increment(optarg,&dp->desync_badseq_ack_increment))
|
||||||
{
|
{
|
||||||
DLOG_ERR("dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
|
DLOG_ERR("dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 36: /* dpi-desync-any-protocol */
|
case 37: /* dpi-desync-any-protocol */
|
||||||
dp->desync_any_proto = !optarg || atoi(optarg);
|
dp->desync_any_proto = !optarg || atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 37: /* dpi-desync-fake-http */
|
case 38: /* dpi-desync-fake-http */
|
||||||
dp->fake_http_size = sizeof(dp->fake_http);
|
dp->fake_http_size = sizeof(dp->fake_http);
|
||||||
load_file_or_exit(optarg,dp->fake_http,&dp->fake_http_size);
|
load_file_or_exit(optarg,dp->fake_http,&dp->fake_http_size);
|
||||||
break;
|
break;
|
||||||
case 38: /* dpi-desync-fake-tls */
|
case 39: /* dpi-desync-fake-tls */
|
||||||
dp->fake_tls_size = sizeof(dp->fake_tls);
|
dp->fake_tls_size = sizeof(dp->fake_tls);
|
||||||
load_file_or_exit(optarg,dp->fake_tls,&dp->fake_tls_size);
|
load_file_or_exit(optarg,dp->fake_tls,&dp->fake_tls_size);
|
||||||
dp->fake_tls_mod |= FAKE_TLS_MOD_CUSTOM_FAKE;
|
dp->fake_tls_mod |= FAKE_TLS_MOD_CUSTOM_FAKE;
|
||||||
break;
|
break;
|
||||||
case 39: /* dpi-desync-fake-tls-mod */
|
case 40: /* dpi-desync-fake-tls-mod */
|
||||||
if (!parse_tlsmod_list(optarg,&dp->fake_tls_mod))
|
if (!parse_tlsmod_list(optarg,&dp->fake_tls_mod))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid tls mod : %s\n",optarg);
|
DLOG_ERR("Invalid tls mod : %s\n",optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 40: /* dpi-desync-fake-unknown */
|
case 41: /* dpi-desync-fake-unknown */
|
||||||
dp->fake_unknown_size = sizeof(dp->fake_unknown);
|
dp->fake_unknown_size = sizeof(dp->fake_unknown);
|
||||||
load_file_or_exit(optarg,dp->fake_unknown,&dp->fake_unknown_size);
|
load_file_or_exit(optarg,dp->fake_unknown,&dp->fake_unknown_size);
|
||||||
break;
|
break;
|
||||||
case 41: /* dpi-desync-fake-syndata */
|
case 42: /* dpi-desync-fake-syndata */
|
||||||
dp->fake_syndata_size = sizeof(dp->fake_syndata);
|
dp->fake_syndata_size = sizeof(dp->fake_syndata);
|
||||||
load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size);
|
load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size);
|
||||||
break;
|
break;
|
||||||
case 42: /* dpi-desync-fake-quic */
|
case 43: /* dpi-desync-fake-quic */
|
||||||
dp->fake_quic_size = sizeof(dp->fake_quic);
|
dp->fake_quic_size = sizeof(dp->fake_quic);
|
||||||
load_file_or_exit(optarg,dp->fake_quic,&dp->fake_quic_size);
|
load_file_or_exit(optarg,dp->fake_quic,&dp->fake_quic_size);
|
||||||
break;
|
break;
|
||||||
case 43: /* dpi-desync-fake-wireguard */
|
case 44: /* dpi-desync-fake-wireguard */
|
||||||
dp->fake_wg_size = sizeof(dp->fake_wg);
|
dp->fake_wg_size = sizeof(dp->fake_wg);
|
||||||
load_file_or_exit(optarg,dp->fake_wg,&dp->fake_wg_size);
|
load_file_or_exit(optarg,dp->fake_wg,&dp->fake_wg_size);
|
||||||
break;
|
break;
|
||||||
case 44: /* dpi-desync-fake-dht */
|
case 45: /* dpi-desync-fake-dht */
|
||||||
dp->fake_dht_size = sizeof(dp->fake_dht);
|
dp->fake_dht_size = sizeof(dp->fake_dht);
|
||||||
load_file_or_exit(optarg,dp->fake_dht,&dp->fake_dht_size);
|
load_file_or_exit(optarg,dp->fake_dht,&dp->fake_dht_size);
|
||||||
break;
|
break;
|
||||||
case 45: /* dpi-desync-fake-unknown-udp */
|
case 46: /* dpi-desync-fake-unknown-udp */
|
||||||
dp->fake_unknown_udp_size = sizeof(dp->fake_unknown_udp);
|
dp->fake_unknown_udp_size = sizeof(dp->fake_unknown_udp);
|
||||||
load_file_or_exit(optarg,dp->fake_unknown_udp,&dp->fake_unknown_udp_size);
|
load_file_or_exit(optarg,dp->fake_unknown_udp,&dp->fake_unknown_udp_size);
|
||||||
break;
|
break;
|
||||||
case 46: /* dpi-desync-udplen-increment */
|
case 47: /* dpi-desync-udplen-increment */
|
||||||
if (sscanf(optarg,"%d",&dp->udplen_increment)<1 || dp->udplen_increment>0x7FFF || dp->udplen_increment<-0x8000)
|
if (sscanf(optarg,"%d",&dp->udplen_increment)<1 || dp->udplen_increment>0x7FFF || dp->udplen_increment<-0x8000)
|
||||||
{
|
{
|
||||||
DLOG_ERR("dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
|
DLOG_ERR("dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 47: /* dpi-desync-udplen-pattern */
|
case 48: /* dpi-desync-udplen-pattern */
|
||||||
{
|
{
|
||||||
char buf[sizeof(dp->udplen_pattern)];
|
char buf[sizeof(dp->udplen_pattern)];
|
||||||
size_t sz=sizeof(buf);
|
size_t sz=sizeof(buf);
|
||||||
@@ -2006,21 +2046,21 @@ int main(int argc, char **argv)
|
|||||||
fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz);
|
fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 48: /* desync-cutoff */
|
case 49: /* desync-cutoff */
|
||||||
if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode))
|
if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode))
|
||||||
{
|
{
|
||||||
DLOG_ERR("invalid desync-cutoff value\n");
|
DLOG_ERR("invalid desync-cutoff value\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 49: /* desync-start */
|
case 50: /* desync-start */
|
||||||
if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode))
|
if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode))
|
||||||
{
|
{
|
||||||
DLOG_ERR("invalid desync-start value\n");
|
DLOG_ERR("invalid desync-start value\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 50: /* hostlist */
|
case 51: /* hostlist */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterHostlist(dp, false, optarg))
|
if (!RegisterHostlist(dp, false, optarg))
|
||||||
{
|
{
|
||||||
@@ -2028,7 +2068,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 51: /* hostlist-domains */
|
case 52: /* hostlist-domains */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
|
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
|
||||||
{
|
{
|
||||||
@@ -2041,7 +2081,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 52: /* hostlist-exclude */
|
case 53: /* hostlist-exclude */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterHostlist(dp, true, optarg))
|
if (!RegisterHostlist(dp, true, optarg))
|
||||||
{
|
{
|
||||||
@@ -2049,7 +2089,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 53: /* hostlist-exclude-domains */
|
case 54: /* hostlist-exclude-domains */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
|
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
|
||||||
{
|
{
|
||||||
@@ -2062,7 +2102,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 54: /* hostlist-auto */
|
case 55: /* hostlist-auto */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (dp->hostlist_auto)
|
if (dp->hostlist_auto)
|
||||||
{
|
{
|
||||||
@@ -2090,7 +2130,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 55: /* hostlist-auto-fail-threshold */
|
case 56: /* hostlist-auto-fail-threshold */
|
||||||
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||||
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
||||||
{
|
{
|
||||||
@@ -2098,7 +2138,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 56: /* hostlist-auto-fail-time */
|
case 57: /* hostlist-auto-fail-time */
|
||||||
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||||
if (dp->hostlist_auto_fail_time<1)
|
if (dp->hostlist_auto_fail_time<1)
|
||||||
{
|
{
|
||||||
@@ -2106,7 +2146,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 57: /* hostlist-auto-retrans-threshold */
|
case 58: /* hostlist-auto-retrans-threshold */
|
||||||
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
|
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
|
||||||
if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10)
|
if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10)
|
||||||
{
|
{
|
||||||
@@ -2114,7 +2154,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 58: /* hostlist-auto-debug */
|
case 59: /* hostlist-auto-debug */
|
||||||
{
|
{
|
||||||
FILE *F = fopen(optarg,"a+t");
|
FILE *F = fopen(optarg,"a+t");
|
||||||
if (!F)
|
if (!F)
|
||||||
@@ -2128,7 +2168,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 59: /* new */
|
case 60: /* new */
|
||||||
if (bSkip)
|
if (bSkip)
|
||||||
{
|
{
|
||||||
dp_clear(dp);
|
dp_clear(dp);
|
||||||
@@ -2150,18 +2190,18 @@ int main(int argc, char **argv)
|
|||||||
anon_hl = anon_hl_exclude = NULL;
|
anon_hl = anon_hl_exclude = NULL;
|
||||||
anon_ips = anon_ips_exclude = NULL;
|
anon_ips = anon_ips_exclude = NULL;
|
||||||
break;
|
break;
|
||||||
case 60: /* skip */
|
case 61: /* skip */
|
||||||
bSkip = true;
|
bSkip = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 61: /* filter-l3 */
|
case 62: /* filter-l3 */
|
||||||
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
||||||
{
|
{
|
||||||
DLOG_ERR("bad value for --filter-l3\n");
|
DLOG_ERR("bad value for --filter-l3\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 62: /* filter-tcp */
|
case 63: /* filter-tcp */
|
||||||
if (!parse_pf_list(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);
|
||||||
@@ -2171,7 +2211,7 @@ int main(int argc, char **argv)
|
|||||||
if (!port_filters_deny_if_empty(&dp->pf_udp))
|
if (!port_filters_deny_if_empty(&dp->pf_udp))
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
break;
|
break;
|
||||||
case 63: /* filter-udp */
|
case 64: /* filter-udp */
|
||||||
if (!parse_pf_list(optarg,&dp->pf_udp))
|
if (!parse_pf_list(optarg,&dp->pf_udp))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||||
@@ -2181,14 +2221,14 @@ int main(int argc, char **argv)
|
|||||||
if (!port_filters_deny_if_empty(&dp->pf_tcp))
|
if (!port_filters_deny_if_empty(&dp->pf_tcp))
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
break;
|
break;
|
||||||
case 64: /* filter-l7 */
|
case 65: /* filter-l7 */
|
||||||
if (!parse_l7_list(optarg,&dp->filter_l7))
|
if (!parse_l7_list(optarg,&dp->filter_l7))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 65: /* ipset */
|
case 66: /* ipset */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterIpset(dp, false, optarg))
|
if (!RegisterIpset(dp, false, optarg))
|
||||||
{
|
{
|
||||||
@@ -2196,7 +2236,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 66: /* ipset-ip */
|
case 67: /* ipset-ip */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
||||||
{
|
{
|
||||||
@@ -2209,7 +2249,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 67: /* ipset-exclude */
|
case 68: /* ipset-exclude */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterIpset(dp, true, optarg))
|
if (!RegisterIpset(dp, true, optarg))
|
||||||
{
|
{
|
||||||
@@ -2217,7 +2257,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 68: /* ipset-exclude-ip */
|
case 69: /* ipset-exclude-ip */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
||||||
{
|
{
|
||||||
@@ -2233,28 +2273,28 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
case 69: /* bind-fix4 */
|
case 70: /* bind-fix4 */
|
||||||
params.bind_fix4 = true;
|
params.bind_fix4 = true;
|
||||||
break;
|
break;
|
||||||
case 70: /* bind-fix6 */
|
case 71: /* bind-fix6 */
|
||||||
params.bind_fix6 = true;
|
params.bind_fix6 = true;
|
||||||
break;
|
break;
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
case 69: /* wf-iface */
|
case 70: /* wf-iface */
|
||||||
if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx))
|
if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx))
|
||||||
{
|
{
|
||||||
DLOG_ERR("bad value for --wf-iface\n");
|
DLOG_ERR("bad value for --wf-iface\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 70: /* wf-l3 */
|
case 71: /* wf-l3 */
|
||||||
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
|
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
|
||||||
{
|
{
|
||||||
DLOG_ERR("bad value for --wf-l3\n");
|
DLOG_ERR("bad value for --wf-l3\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 71: /* wf-tcp */
|
case 72: /* wf-tcp */
|
||||||
hash_wf_tcp=hash_jen(optarg,strlen(optarg));
|
hash_wf_tcp=hash_jen(optarg,strlen(optarg));
|
||||||
if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) ||
|
if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) ||
|
||||||
!wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst)))
|
!wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst)))
|
||||||
@@ -2263,7 +2303,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 72: /* wf-udp */
|
case 73: /* wf-udp */
|
||||||
hash_wf_udp=hash_jen(optarg,strlen(optarg));
|
hash_wf_udp=hash_jen(optarg,strlen(optarg));
|
||||||
if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) ||
|
if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) ||
|
||||||
!wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst)))
|
!wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst)))
|
||||||
@@ -2272,7 +2312,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 73: /* wf-raw */
|
case 74: /* wf-raw */
|
||||||
hash_wf_raw=hash_jen(optarg,strlen(optarg));
|
hash_wf_raw=hash_jen(optarg,strlen(optarg));
|
||||||
if (optarg[0]=='@')
|
if (optarg[0]=='@')
|
||||||
{
|
{
|
||||||
@@ -2286,11 +2326,11 @@ int main(int argc, char **argv)
|
|||||||
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
|
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 74: /* wf-save */
|
case 75: /* wf-save */
|
||||||
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
||||||
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
||||||
break;
|
break;
|
||||||
case 75: /* ssid-filter */
|
case 76: /* ssid-filter */
|
||||||
hash_ssid_filter=hash_jen(optarg,strlen(optarg));
|
hash_ssid_filter=hash_jen(optarg,strlen(optarg));
|
||||||
{
|
{
|
||||||
char *e,*p = optarg;
|
char *e,*p = optarg;
|
||||||
@@ -2308,7 +2348,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 76: /* nlm-filter */
|
case 77: /* nlm-filter */
|
||||||
hash_nlm_filter=hash_jen(optarg,strlen(optarg));
|
hash_nlm_filter=hash_jen(optarg,strlen(optarg));
|
||||||
{
|
{
|
||||||
char *e,*p = optarg;
|
char *e,*p = optarg;
|
||||||
@@ -2326,7 +2366,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 77: /* nlm-list */
|
case 78: /* nlm-list */
|
||||||
if (!nlm_list(optarg && !strcmp(optarg,"all")))
|
if (!nlm_list(optarg && !strcmp(optarg,"all")))
|
||||||
{
|
{
|
||||||
DLOG_ERR("could not get list of NLM networks\n");
|
DLOG_ERR("could not get list of NLM networks\n");
|
||||||
|
@@ -42,8 +42,9 @@
|
|||||||
#define FAKE_TLS_MOD_SET 0x01
|
#define FAKE_TLS_MOD_SET 0x01
|
||||||
#define FAKE_TLS_MOD_CUSTOM_FAKE 0x02
|
#define FAKE_TLS_MOD_CUSTOM_FAKE 0x02
|
||||||
#define FAKE_TLS_MOD_RND 0x10
|
#define FAKE_TLS_MOD_RND 0x10
|
||||||
#define FAKE_TLS_MOD_RND_SNI 0x20
|
#define FAKE_TLS_MOD_DUP_SID 0x20
|
||||||
#define FAKE_TLS_MOD_PADENCAP 0x40
|
#define FAKE_TLS_MOD_RND_SNI 0x40
|
||||||
|
#define FAKE_TLS_MOD_PADENCAP 0x80
|
||||||
|
|
||||||
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
|
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
|
||||||
|
|
||||||
|
27
nfq/pools.c
27
nfq/pools.c
@@ -31,6 +31,9 @@
|
|||||||
free(elem); \
|
free(elem); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
|
||||||
|
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
|
||||||
|
elem->flags = flg;
|
||||||
|
|
||||||
|
|
||||||
#undef uthash_nonfatal_oom
|
#undef uthash_nonfatal_oom
|
||||||
@@ -42,27 +45,31 @@ static void ut_oom_recover(void *elem)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for not zero terminated strings
|
// for not zero terminated strings
|
||||||
bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen)
|
bool HostlistPoolAddStrLen(hostlist_pool **pp, const char *s, size_t slen, uint32_t flags)
|
||||||
{
|
{
|
||||||
ADD_STR_POOL(strpool, pp, s, slen)
|
ADD_HOSTLIST_POOL(hostlist_pool, pp, s, slen, flags)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// for zero terminated strings
|
// for zero terminated strings
|
||||||
bool StrPoolAddStr(strpool **pp, const char *s)
|
bool HostlistPoolAddStr(hostlist_pool **pp, const char *s, uint32_t flags)
|
||||||
{
|
{
|
||||||
return StrPoolAddStrLen(pp, s, strlen(s));
|
return HostlistPoolAddStrLen(pp, s, strlen(s), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StrPoolCheckStr(strpool *p, const char *s)
|
hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s)
|
||||||
{
|
{
|
||||||
strpool *elem;
|
hostlist_pool *elem;
|
||||||
HASH_FIND_STR(p, s, elem);
|
HASH_FIND_STR(p, s, elem);
|
||||||
return elem != NULL;
|
return elem;
|
||||||
|
}
|
||||||
|
bool HostlistPoolCheckStr(hostlist_pool *p, const char *s)
|
||||||
|
{
|
||||||
|
return !!HostlistPoolGetStr(p,s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StrPoolDestroy(strpool **pp)
|
void HostlistPoolDestroy(hostlist_pool **pp)
|
||||||
{
|
{
|
||||||
DESTROY_STR_POOL(strpool, pp)
|
DESTROY_STR_POOL(hostlist_pool, pp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -178,7 +185,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
|
|||||||
static void hostlist_files_entry_destroy(struct hostlist_file *entry)
|
static void hostlist_files_entry_destroy(struct hostlist_file *entry)
|
||||||
{
|
{
|
||||||
free(entry->filename);
|
free(entry->filename);
|
||||||
StrPoolDestroy(&entry->hostlist);
|
HostlistPoolDestroy(&entry->hostlist);
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
void hostlist_files_destroy(struct hostlist_files_head *head)
|
void hostlist_files_destroy(struct hostlist_files_head *head)
|
||||||
|
29
nfq/pools.h
29
nfq/pools.h
@@ -12,15 +12,18 @@
|
|||||||
#define HASH_FUNCTION HASH_BER
|
#define HASH_FUNCTION HASH_BER
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
typedef struct strpool {
|
#define HOSTLIST_POOL_FLAG_STRICT_MATCH 1
|
||||||
char *str; /* key */
|
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
|
||||||
} strpool;
|
|
||||||
|
|
||||||
void StrPoolDestroy(strpool **pp);
|
typedef struct hostlist_pool {
|
||||||
bool StrPoolAddStr(strpool **pp,const char *s);
|
char *str; /* key */
|
||||||
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
|
uint32_t flags; /* custom data */
|
||||||
bool StrPoolCheckStr(strpool *p,const char *s);
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
|
} hostlist_pool;
|
||||||
|
|
||||||
|
void HostlistPoolDestroy(hostlist_pool **pp);
|
||||||
|
bool HostlistPoolAddStr(hostlist_pool **pp, const char *s, uint32_t flags);
|
||||||
|
bool HostlistPoolAddStrLen(hostlist_pool **pp, const char *s, size_t slen, uint32_t flags);
|
||||||
|
hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s);
|
||||||
|
|
||||||
struct str_list {
|
struct str_list {
|
||||||
char *str;
|
char *str;
|
||||||
@@ -29,10 +32,10 @@ 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 */
|
||||||
time_t expire; /* when to expire record (unixtime) */
|
time_t expire; /* when to expire record (unixtime) */
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
} hostfail_pool;
|
} hostfail_pool;
|
||||||
|
|
||||||
void HostFailPoolDestroy(hostfail_pool **pp);
|
void HostFailPoolDestroy(hostfail_pool **pp);
|
||||||
@@ -51,7 +54,7 @@ void strlist_destroy(struct str_list_head *head);
|
|||||||
struct hostlist_file {
|
struct hostlist_file {
|
||||||
char *filename;
|
char *filename;
|
||||||
file_mod_sig mod_sig;
|
file_mod_sig mod_sig;
|
||||||
strpool *hostlist;
|
hostlist_pool *hostlist;
|
||||||
LIST_ENTRY(hostlist_file) next;
|
LIST_ENTRY(hostlist_file) next;
|
||||||
};
|
};
|
||||||
LIST_HEAD(hostlist_files_head, hostlist_file);
|
LIST_HEAD(hostlist_files_head, hostlist_file);
|
||||||
|
@@ -287,7 +287,7 @@ bool can_drop_root(void)
|
|||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
// has some caps
|
// has some caps
|
||||||
return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID)|(1<<CAP_SETPCAP));
|
return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID));
|
||||||
#else
|
#else
|
||||||
// effective root
|
// effective root
|
||||||
return !geteuid();
|
return !geteuid();
|
||||||
@@ -319,11 +319,7 @@ bool droproot(uid_t uid, gid_t gid)
|
|||||||
DLOG_PERROR("setuid");
|
DLOG_PERROR("setuid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef __linux__
|
|
||||||
return dropcaps();
|
|
||||||
#else
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_id(void)
|
void print_id(void)
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS += -std=gnu99 -Os -flto=auto
|
CFLAGS += -std=gnu99 -Os -flto=auto
|
||||||
|
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||||
LIBS = -lz -lpthread
|
LIBS = -lz -lpthread
|
||||||
|
LIBS_SYSTEMD = -lz -lsystemd
|
||||||
LIBS_ANDROID = -lz
|
LIBS_ANDROID = -lz
|
||||||
SRC_FILES = *.c
|
SRC_FILES = *.c
|
||||||
SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
|
SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
|
||||||
@@ -11,6 +13,9 @@ all: tpws
|
|||||||
tpws: $(SRC_FILES)
|
tpws: $(SRC_FILES)
|
||||||
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES) $(LIBS) $(LDFLAGS)
|
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES) $(LIBS) $(LDFLAGS)
|
||||||
|
|
||||||
|
systemd: $(SRC_FILES)
|
||||||
|
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o tpws $(SRC_FILES) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||||
|
|
||||||
android: $(SRC_FILES)
|
android: $(SRC_FILES)
|
||||||
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES_ANDROID) $(LIBS_ANDROID) $(LDFLAGS)
|
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES_ANDROID) $(LIBS_ANDROID) $(LDFLAGS)
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
#include "andr/ifaddrs.h"
|
#include "andr/ifaddrs.h"
|
||||||
@@ -77,6 +78,13 @@ char *strncasestr(const char *s, const char *find, size_t slen)
|
|||||||
return (char *)s;
|
return (char *)s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool str_ends_with(const char *s, const char *suffix)
|
||||||
|
{
|
||||||
|
size_t slen = strlen(s);
|
||||||
|
size_t suffix_len = strlen(suffix);
|
||||||
|
return suffix_len <= slen && !strcmp(s + slen - suffix_len, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
bool load_file(const char *filename, void *buffer, size_t *buffer_size)
|
bool load_file(const char *filename, void *buffer, size_t *buffer_size)
|
||||||
{
|
{
|
||||||
FILE *F;
|
FILE *F;
|
||||||
@@ -327,6 +335,17 @@ bool file_mod_signature(const char *filename, file_mod_sig *ms)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool file_open_test(const char *filename, int flags)
|
||||||
|
{
|
||||||
|
int fd = open(filename,flags);
|
||||||
|
if (fd>=0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool pf_in_range(uint16_t port, const port_filter *pf)
|
bool pf_in_range(uint16_t port, const port_filter *pf)
|
||||||
{
|
{
|
||||||
return port && (((!pf->from && !pf->to) || (port >= pf->from && port <= pf->to)) ^ pf->neg);
|
return port && (((!pf->from && !pf->to) || (port >= pf->from && port <= pf->to)) ^ pf->neg);
|
||||||
@@ -371,6 +390,11 @@ bool pf_is_empty(const port_filter *pf)
|
|||||||
return !pf->neg && !pf->from && !pf->to;
|
return !pf->neg && !pf->from && !pf->to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_console_io_buffering(void)
|
||||||
|
{
|
||||||
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
setvbuf(stderr, NULL, _IOLBF, 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool set_env_exedir(const char *argv0)
|
bool set_env_exedir(const char *argv0)
|
||||||
{
|
{
|
||||||
@@ -548,4 +572,20 @@ bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_wsl(void)
|
||||||
|
{
|
||||||
|
struct utsname buf;
|
||||||
|
if (uname(&buf) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (strcmp(buf.sysname, "Linux") != 0)
|
||||||
|
return 0;
|
||||||
|
if (str_ends_with(buf.release, "microsoft-standard-WSL2"))
|
||||||
|
return 2;
|
||||||
|
if (str_ends_with(buf.release, "-Microsoft"))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
|
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
|
||||||
typedef union
|
typedef union
|
||||||
@@ -22,6 +23,8 @@ void rtrim(char *s);
|
|||||||
void replace_char(char *s, char from, char to);
|
void replace_char(char *s, char from, char to);
|
||||||
char *strncasestr(const char *s,const char *find, size_t slen);
|
char *strncasestr(const char *s,const char *find, size_t slen);
|
||||||
|
|
||||||
|
bool str_ends_with(const char *s, const char *suffix);
|
||||||
|
|
||||||
bool load_file(const char *filename,void *buffer,size_t *buffer_size);
|
bool load_file(const char *filename,void *buffer,size_t *buffer_size);
|
||||||
bool append_to_list_file(const char *filename, const char *s);
|
bool append_to_list_file(const char *filename, const char *s);
|
||||||
|
|
||||||
@@ -71,6 +74,7 @@ typedef struct
|
|||||||
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
|
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
|
||||||
bool file_mod_signature(const char *filename, file_mod_sig *ms);
|
bool file_mod_signature(const char *filename, file_mod_sig *ms);
|
||||||
time_t file_mod_time(const char *filename);
|
time_t file_mod_time(const char *filename);
|
||||||
|
bool file_open_test(const char *filename, int flags);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -81,6 +85,7 @@ bool pf_in_range(uint16_t port, const port_filter *pf);
|
|||||||
bool pf_parse(const char *s, port_filter *pf);
|
bool pf_parse(const char *s, port_filter *pf);
|
||||||
bool pf_is_empty(const port_filter *pf);
|
bool pf_is_empty(const port_filter *pf);
|
||||||
|
|
||||||
|
void set_console_io_buffering(void);
|
||||||
bool set_env_exedir(const char *argv0);
|
bool set_env_exedir(const char *argv0);
|
||||||
|
|
||||||
#ifndef IN_LOOPBACK
|
#ifndef IN_LOOPBACK
|
||||||
@@ -131,4 +136,6 @@ void msleep(unsigned int ms);
|
|||||||
bool socket_supports_notsent();
|
bool socket_supports_notsent();
|
||||||
bool socket_has_notsent(int sfd);
|
bool socket_has_notsent(int sfd);
|
||||||
bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms);
|
bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms);
|
||||||
|
|
||||||
|
int is_wsl();
|
||||||
#endif
|
#endif
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
// inplace tolower() and add to pool
|
// inplace tolower() and add to pool
|
||||||
static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct)
|
||||||
{
|
{
|
||||||
char *p=*s;
|
char *p=*s;
|
||||||
|
|
||||||
@@ -17,10 +17,16 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// advance until eol lowering all chars
|
// advance until eol lowering all chars
|
||||||
for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
|
uint32_t flags = 0;
|
||||||
if (!StrPoolAddStrLen(hostlist, *s, p-*s))
|
if (*p=='^')
|
||||||
{
|
{
|
||||||
StrPoolDestroy(hostlist);
|
p = ++(*s);
|
||||||
|
flags |= HOSTLIST_POOL_FLAG_STRICT_MATCH;
|
||||||
|
}
|
||||||
|
for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
|
||||||
|
if (!HostlistPoolAddStrLen(hostlist, *s, p-*s, flags))
|
||||||
|
{
|
||||||
|
HostlistPoolDestroy(hostlist);
|
||||||
*hostlist = NULL;
|
*hostlist = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -32,12 +38,12 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppendHostlistItem(strpool **hostlist, char *s)
|
bool AppendHostlistItem(hostlist_pool **hostlist, char *s)
|
||||||
{
|
{
|
||||||
return addpool(hostlist,&s,s+strlen(s),NULL);
|
return addpool(hostlist,&s,s+strlen(s),NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppendHostList(strpool **hostlist, const char *filename)
|
bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||||
{
|
{
|
||||||
char *p, *e, s[256], *zbuf;
|
char *p, *e, s[256], *zbuf;
|
||||||
size_t zsize;
|
size_t zsize;
|
||||||
@@ -109,14 +115,15 @@ static bool LoadHostList(struct hostlist_file *hfile)
|
|||||||
if (!file_mod_signature(hfile->filename, &fsig))
|
if (!file_mod_signature(hfile->filename, &fsig))
|
||||||
{
|
{
|
||||||
// stat() error
|
// stat() error
|
||||||
|
DLOG_PERROR("file_mod_signature");
|
||||||
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
|
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
|
||||||
StrPoolDestroy(&hfile->hostlist);
|
HostlistPoolDestroy(&hfile->hostlist);
|
||||||
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
||||||
{
|
{
|
||||||
StrPoolDestroy(&hfile->hostlist);
|
HostlistPoolDestroy(&hfile->hostlist);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
hfile->mod_sig=fsig;
|
hfile->mod_sig=fsig;
|
||||||
@@ -137,10 +144,10 @@ static bool LoadHostLists(struct hostlist_files_head *list)
|
|||||||
return bres;
|
return bres;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NonEmptyHostlist(strpool **hostlist)
|
bool NonEmptyHostlist(hostlist_pool **hostlist)
|
||||||
{
|
{
|
||||||
// add impossible hostname if the list is empty
|
// add impossible hostname if the list is empty
|
||||||
return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4);
|
return *hostlist ? true : HostlistPoolAddStrLen(hostlist, "@&()", 4, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MakeAutolistsNonEmpty()
|
static void MakeAutolistsNonEmpty()
|
||||||
@@ -163,19 +170,34 @@ bool LoadAllHostLists()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool SearchHostList(strpool *hostlist, const char *host)
|
static bool SearchHostList(hostlist_pool *hostlist, const char *host)
|
||||||
{
|
{
|
||||||
if (hostlist)
|
if (hostlist)
|
||||||
{
|
{
|
||||||
const char *p = host;
|
const char *p = host;
|
||||||
bool bInHostList;
|
const struct hostlist_pool *hp;
|
||||||
|
bool bHostFull=true;
|
||||||
while (p)
|
while (p)
|
||||||
{
|
{
|
||||||
bInHostList = StrPoolCheckStr(hostlist, p);
|
VPRINT("hostlist check for %s : ", p);
|
||||||
VPRINT("hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
|
hp = HostlistPoolGetStr(hostlist, p);
|
||||||
if (bInHostList) return true;
|
if (hp)
|
||||||
|
{
|
||||||
|
if ((hp->flags & HOSTLIST_POOL_FLAG_STRICT_MATCH) && !bHostFull)
|
||||||
|
{
|
||||||
|
VPRINT("negative : strict_mismatch : %s != %s\n", p, host);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VPRINT("positive\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
VPRINT("negative\n");
|
||||||
p = strchr(p, '.');
|
p = strchr(p, '.');
|
||||||
if (p) p++;
|
if (p) p++;
|
||||||
|
bHostFull = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@@ -4,10 +4,10 @@
|
|||||||
#include "pools.h"
|
#include "pools.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
|
||||||
bool AppendHostlistItem(strpool **hostlist, char *s);
|
bool AppendHostlistItem(hostlist_pool **hostlist, char *s);
|
||||||
bool AppendHostList(strpool **hostlist, const char *filename);
|
bool AppendHostList(hostlist_pool **hostlist, const char *filename);
|
||||||
bool LoadAllHostLists();
|
bool LoadAllHostLists();
|
||||||
bool NonEmptyHostlist(strpool **hostlist);
|
bool NonEmptyHostlist(hostlist_pool **hostlist);
|
||||||
// return : true = apply fooling, false = do not apply
|
// return : true = apply fooling, false = do not apply
|
||||||
bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *excluded, bool bSkipReloadCheck);
|
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);
|
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||||
|
@@ -130,6 +130,7 @@ static bool LoadIpset(struct ipset_file *hfile)
|
|||||||
if (!file_mod_signature(hfile->filename, &fsig))
|
if (!file_mod_signature(hfile->filename, &fsig))
|
||||||
{
|
{
|
||||||
// stat() error
|
// stat() error
|
||||||
|
DLOG_PERROR("file_mod_signature");
|
||||||
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
27
tpws/pools.c
27
tpws/pools.c
@@ -31,6 +31,9 @@
|
|||||||
free(elem); \
|
free(elem); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
|
||||||
|
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
|
||||||
|
elem->flags = flg;
|
||||||
|
|
||||||
|
|
||||||
#undef uthash_nonfatal_oom
|
#undef uthash_nonfatal_oom
|
||||||
@@ -42,27 +45,31 @@ static void ut_oom_recover(void *elem)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for not zero terminated strings
|
// for not zero terminated strings
|
||||||
bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen)
|
bool HostlistPoolAddStrLen(hostlist_pool **pp, const char *s, size_t slen, uint32_t flags)
|
||||||
{
|
{
|
||||||
ADD_STR_POOL(strpool, pp, s, slen)
|
ADD_HOSTLIST_POOL(hostlist_pool, pp, s, slen, flags)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// for zero terminated strings
|
// for zero terminated strings
|
||||||
bool StrPoolAddStr(strpool **pp, const char *s)
|
bool HostlistPoolAddStr(hostlist_pool **pp, const char *s, uint32_t flags)
|
||||||
{
|
{
|
||||||
return StrPoolAddStrLen(pp, s, strlen(s));
|
return HostlistPoolAddStrLen(pp, s, strlen(s), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StrPoolCheckStr(strpool *p, const char *s)
|
hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s)
|
||||||
{
|
{
|
||||||
strpool *elem;
|
hostlist_pool *elem;
|
||||||
HASH_FIND_STR(p, s, elem);
|
HASH_FIND_STR(p, s, elem);
|
||||||
return elem != NULL;
|
return elem;
|
||||||
|
}
|
||||||
|
bool HostlistPoolCheckStr(hostlist_pool *p, const char *s)
|
||||||
|
{
|
||||||
|
return !!HostlistPoolGetStr(p,s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StrPoolDestroy(strpool **pp)
|
void HostlistPoolDestroy(hostlist_pool **pp)
|
||||||
{
|
{
|
||||||
DESTROY_STR_POOL(strpool, pp)
|
DESTROY_STR_POOL(hostlist_pool, pp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -178,7 +185,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
|
|||||||
static void hostlist_files_entry_destroy(struct hostlist_file *entry)
|
static void hostlist_files_entry_destroy(struct hostlist_file *entry)
|
||||||
{
|
{
|
||||||
free(entry->filename);
|
free(entry->filename);
|
||||||
StrPoolDestroy(&entry->hostlist);
|
HostlistPoolDestroy(&entry->hostlist);
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
void hostlist_files_destroy(struct hostlist_files_head *head)
|
void hostlist_files_destroy(struct hostlist_files_head *head)
|
||||||
|
29
tpws/pools.h
29
tpws/pools.h
@@ -12,15 +12,18 @@
|
|||||||
#define HASH_FUNCTION HASH_BER
|
#define HASH_FUNCTION HASH_BER
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
typedef struct strpool {
|
#define HOSTLIST_POOL_FLAG_STRICT_MATCH 1
|
||||||
char *str; /* key */
|
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
|
||||||
} strpool;
|
|
||||||
|
|
||||||
void StrPoolDestroy(strpool **pp);
|
typedef struct hostlist_pool {
|
||||||
bool StrPoolAddStr(strpool **pp,const char *s);
|
char *str; /* key */
|
||||||
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
|
uint32_t flags; /* custom data */
|
||||||
bool StrPoolCheckStr(strpool *p,const char *s);
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
|
} hostlist_pool;
|
||||||
|
|
||||||
|
void HostlistPoolDestroy(hostlist_pool **pp);
|
||||||
|
bool HostlistPoolAddStr(hostlist_pool **pp, const char *s, uint32_t flags);
|
||||||
|
bool HostlistPoolAddStrLen(hostlist_pool **pp, const char *s, size_t slen, uint32_t flags);
|
||||||
|
hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s);
|
||||||
|
|
||||||
struct str_list {
|
struct str_list {
|
||||||
char *str;
|
char *str;
|
||||||
@@ -29,10 +32,10 @@ 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 */
|
||||||
time_t expire; /* when to expire record (unixtime) */
|
time_t expire; /* when to expire record (unixtime) */
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
} hostfail_pool;
|
} hostfail_pool;
|
||||||
|
|
||||||
void HostFailPoolDestroy(hostfail_pool **pp);
|
void HostFailPoolDestroy(hostfail_pool **pp);
|
||||||
@@ -51,7 +54,7 @@ void strlist_destroy(struct str_list_head *head);
|
|||||||
struct hostlist_file {
|
struct hostlist_file {
|
||||||
char *filename;
|
char *filename;
|
||||||
file_mod_sig mod_sig;
|
file_mod_sig mod_sig;
|
||||||
strpool *hostlist;
|
hostlist_pool *hostlist;
|
||||||
LIST_ENTRY(hostlist_file) next;
|
LIST_ENTRY(hostlist_file) next;
|
||||||
};
|
};
|
||||||
LIST_HEAD(hostlist_files_head, hostlist_file);
|
LIST_HEAD(hostlist_files_head, hostlist_file);
|
||||||
|
@@ -263,7 +263,7 @@ bool can_drop_root(void)
|
|||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
// has some caps
|
// has some caps
|
||||||
return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID)|(1<<CAP_SETPCAP));
|
return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID));
|
||||||
#else
|
#else
|
||||||
// effective root
|
// effective root
|
||||||
return !geteuid();
|
return !geteuid();
|
||||||
@@ -295,11 +295,7 @@ bool droproot(uid_t uid, gid_t gid)
|
|||||||
DLOG_PERROR("setuid");
|
DLOG_PERROR("setuid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef __linux__
|
|
||||||
return dropcaps();
|
|
||||||
#else
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_id(void)
|
void print_id(void)
|
||||||
|
@@ -433,7 +433,7 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
|||||||
{
|
{
|
||||||
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_auto->hostlist, hostname))
|
if (!HostlistPoolAddStr(&dp->hostlist_auto->hostlist, hostname, 0))
|
||||||
{
|
{
|
||||||
DLOG_ERR("StrPoolAddStr out of memory\n");
|
DLOG_ERR("StrPoolAddStr out of memory\n");
|
||||||
return;
|
return;
|
||||||
|
166
tpws/tpws.c
166
tpws/tpws.c
@@ -116,6 +116,27 @@ static int8_t block_sigpipe(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool test_list_files()
|
||||||
|
{
|
||||||
|
struct hostlist_file *hfile;
|
||||||
|
struct ipset_file *ifile;
|
||||||
|
|
||||||
|
LIST_FOREACH(hfile, ¶ms.hostlists, next)
|
||||||
|
if (hfile->filename && !file_open_test(hfile->filename, O_RDONLY))
|
||||||
|
{
|
||||||
|
DLOG_PERROR("file_open_test");
|
||||||
|
DLOG_ERR("cannot access hostlist file '%s'\n",hfile->filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LIST_FOREACH(ifile, ¶ms.ipsets, next)
|
||||||
|
if (ifile->filename && !file_open_test(ifile->filename, O_RDONLY))
|
||||||
|
{
|
||||||
|
DLOG_PERROR("file_open_test");
|
||||||
|
DLOG_ERR("cannot access ipset file '%s'\n",ifile->filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_interface_online(const char *ifname)
|
static bool is_interface_online(const char *ifname)
|
||||||
{
|
{
|
||||||
@@ -197,6 +218,7 @@ static void exithelp(void)
|
|||||||
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
|
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
|
||||||
" --debug-level=0|1|2\t\t\t; specify debug level\n"
|
" --debug-level=0|1|2\t\t\t; specify debug level\n"
|
||||||
" --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
" --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
||||||
|
" --version\t\t\t\t; print version and exit\n"
|
||||||
" --comment=any_text\n"
|
" --comment=any_text\n"
|
||||||
"\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"
|
||||||
@@ -511,7 +533,7 @@ static bool parse_pf_list(char *opt, struct port_filters_head *pfl)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_domain_list(char *opt, strpool **pp)
|
static bool parse_domain_list(char *opt, hostlist_pool **pp)
|
||||||
{
|
{
|
||||||
char *e,*p,c;
|
char *e,*p,c;
|
||||||
|
|
||||||
@@ -691,41 +713,42 @@ void parse_params(int argc, char *argv[])
|
|||||||
{ "debug",optional_argument,0,0 },// optidx=45
|
{ "debug",optional_argument,0,0 },// optidx=45
|
||||||
{ "debug-level",required_argument,0,0 },// optidx=46
|
{ "debug-level",required_argument,0,0 },// optidx=46
|
||||||
{ "dry-run",no_argument,0,0 },// optidx=47
|
{ "dry-run",no_argument,0,0 },// optidx=47
|
||||||
{ "comment",optional_argument,0,0 },// optidx=48
|
{ "version",no_argument,0,0 },// optidx=48
|
||||||
{ "local-rcvbuf",required_argument,0,0 },// optidx=49
|
{ "comment",optional_argument,0,0 },// optidx=49
|
||||||
{ "local-sndbuf",required_argument,0,0 },// optidx=50
|
{ "local-rcvbuf",required_argument,0,0 },// optidx=50
|
||||||
{ "remote-rcvbuf",required_argument,0,0 },// optidx=51
|
{ "local-sndbuf",required_argument,0,0 },// optidx=51
|
||||||
{ "remote-sndbuf",required_argument,0,0 },// optidx=52
|
{ "remote-rcvbuf",required_argument,0,0 },// optidx=52
|
||||||
{ "socks",no_argument,0,0 },// optidx=53
|
{ "remote-sndbuf",required_argument,0,0 },// optidx=53
|
||||||
{ "no-resolve",no_argument,0,0 },// optidx=54
|
{ "socks",no_argument,0,0 },// optidx=54
|
||||||
{ "resolver-threads",required_argument,0,0 },// optidx=55
|
{ "no-resolve",no_argument,0,0 },// optidx=55
|
||||||
{ "skip-nodelay",no_argument,0,0 },// optidx=56
|
{ "resolver-threads",required_argument,0,0 },// optidx=56
|
||||||
{ "tamper-start",required_argument,0,0 },// optidx=57
|
{ "skip-nodelay",no_argument,0,0 },// optidx=57
|
||||||
{ "tamper-cutoff",required_argument,0,0 },// optidx=58
|
{ "tamper-start",required_argument,0,0 },// optidx=58
|
||||||
{ "connect-bind-addr",required_argument,0,0 },// optidx=59
|
{ "tamper-cutoff",required_argument,0,0 },// optidx=59
|
||||||
|
{ "connect-bind-addr",required_argument,0,0 },// optidx=60
|
||||||
|
|
||||||
{ "new",no_argument,0,0 }, // optidx=60
|
{ "new",no_argument,0,0 }, // optidx=61
|
||||||
{ "skip",no_argument,0,0 }, // optidx=61
|
{ "skip",no_argument,0,0 }, // optidx=62
|
||||||
{ "filter-l3",required_argument,0,0 }, // optidx=62
|
{ "filter-l3",required_argument,0,0 }, // optidx=63
|
||||||
{ "filter-tcp",required_argument,0,0 }, // optidx=63
|
{ "filter-tcp",required_argument,0,0 }, // optidx=64
|
||||||
{ "filter-l7",required_argument,0,0 }, // optidx=64
|
{ "filter-l7",required_argument,0,0 }, // optidx=65
|
||||||
{ "ipset",required_argument,0,0 }, // optidx=65
|
{ "ipset",required_argument,0,0 }, // optidx=66
|
||||||
{ "ipset-ip",required_argument,0,0 }, // optidx=66
|
{ "ipset-ip",required_argument,0,0 }, // optidx=67
|
||||||
{ "ipset-exclude",required_argument,0,0 }, // optidx=67
|
{ "ipset-exclude",required_argument,0,0 }, // optidx=68
|
||||||
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=68
|
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=69
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
{ "enable-pf",no_argument,0,0 },// optidx=69
|
{ "enable-pf",no_argument,0,0 },// optidx=69
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=69
|
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=79
|
||||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=70
|
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=71
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=69
|
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=70
|
||||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=70
|
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=71
|
||||||
{ "mss",required_argument,0,0 }, // optidx=71
|
{ "mss",required_argument,0,0 }, // optidx=72
|
||||||
{ "fix-seg",optional_argument,0,0 }, // optidx=72
|
{ "fix-seg",optional_argument,0,0 }, // optidx=73
|
||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
{ "nosplice",no_argument,0,0 }, // optidx=73
|
{ "nosplice",no_argument,0,0 }, // optidx=74
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
|
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
|
||||||
@@ -1176,43 +1199,46 @@ void parse_params(int argc, char *argv[])
|
|||||||
case 47: /* dry-run */
|
case 47: /* dry-run */
|
||||||
bDry = true;
|
bDry = true;
|
||||||
break;
|
break;
|
||||||
case 48: /* comment */
|
case 48: /* version */
|
||||||
|
exit_clean(0);
|
||||||
break;
|
break;
|
||||||
case 49: /* local-rcvbuf */
|
case 49: /* comment */
|
||||||
|
break;
|
||||||
|
case 50: /* local-rcvbuf */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.local_rcvbuf = atoi(optarg)/2;
|
params.local_rcvbuf = atoi(optarg)/2;
|
||||||
#else
|
#else
|
||||||
params.local_rcvbuf = atoi(optarg);
|
params.local_rcvbuf = atoi(optarg);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 50: /* local-sndbuf */
|
case 51: /* local-sndbuf */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.local_sndbuf = atoi(optarg)/2;
|
params.local_sndbuf = atoi(optarg)/2;
|
||||||
#else
|
#else
|
||||||
params.local_sndbuf = atoi(optarg);
|
params.local_sndbuf = atoi(optarg);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 51: /* remote-rcvbuf */
|
case 52: /* remote-rcvbuf */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.remote_rcvbuf = atoi(optarg)/2;
|
params.remote_rcvbuf = atoi(optarg)/2;
|
||||||
#else
|
#else
|
||||||
params.remote_rcvbuf = atoi(optarg);
|
params.remote_rcvbuf = atoi(optarg);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 52: /* remote-sndbuf */
|
case 53: /* remote-sndbuf */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.remote_sndbuf = atoi(optarg)/2;
|
params.remote_sndbuf = atoi(optarg)/2;
|
||||||
#else
|
#else
|
||||||
params.remote_sndbuf = atoi(optarg);
|
params.remote_sndbuf = atoi(optarg);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 53: /* socks */
|
case 54: /* socks */
|
||||||
params.proxy_type = CONN_TYPE_SOCKS;
|
params.proxy_type = CONN_TYPE_SOCKS;
|
||||||
break;
|
break;
|
||||||
case 54: /* no-resolve */
|
case 55: /* no-resolve */
|
||||||
params.no_resolve = true;
|
params.no_resolve = true;
|
||||||
break;
|
break;
|
||||||
case 55: /* resolver-threads */
|
case 56: /* resolver-threads */
|
||||||
params.resolver_threads = atoi(optarg);
|
params.resolver_threads = atoi(optarg);
|
||||||
if (params.resolver_threads<1 || params.resolver_threads>300)
|
if (params.resolver_threads<1 || params.resolver_threads>300)
|
||||||
{
|
{
|
||||||
@@ -1220,10 +1246,10 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 56: /* skip-nodelay */
|
case 57: /* skip-nodelay */
|
||||||
params.skip_nodelay = true;
|
params.skip_nodelay = true;
|
||||||
break;
|
break;
|
||||||
case 57: /* tamper-start */
|
case 58: /* tamper-start */
|
||||||
{
|
{
|
||||||
const char *p=optarg;
|
const char *p=optarg;
|
||||||
if (*p=='n')
|
if (*p=='n')
|
||||||
@@ -1237,7 +1263,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper_lim = true;
|
params.tamper_lim = true;
|
||||||
break;
|
break;
|
||||||
case 58: /* tamper-cutoff */
|
case 59: /* tamper-cutoff */
|
||||||
{
|
{
|
||||||
const char *p=optarg;
|
const char *p=optarg;
|
||||||
if (*p=='n')
|
if (*p=='n')
|
||||||
@@ -1251,7 +1277,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper_lim = true;
|
params.tamper_lim = true;
|
||||||
break;
|
break;
|
||||||
case 59: /* connect-bind-addr */
|
case 60: /* connect-bind-addr */
|
||||||
{
|
{
|
||||||
char *p = strchr(optarg,'%');
|
char *p = strchr(optarg,'%');
|
||||||
if (p) *p++=0;
|
if (p) *p++=0;
|
||||||
@@ -1279,7 +1305,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case 60: /* new */
|
case 61: /* new */
|
||||||
if (bSkip)
|
if (bSkip)
|
||||||
{
|
{
|
||||||
dp_clear(dp);
|
dp_clear(dp);
|
||||||
@@ -1300,31 +1326,31 @@ void parse_params(int argc, char *argv[])
|
|||||||
anon_hl = anon_hl_exclude = NULL;
|
anon_hl = anon_hl_exclude = NULL;
|
||||||
anon_ips = anon_ips_exclude = NULL;
|
anon_ips = anon_ips_exclude = NULL;
|
||||||
break;
|
break;
|
||||||
case 61: /* skip */
|
case 62: /* skip */
|
||||||
bSkip = true;
|
bSkip = true;
|
||||||
break;
|
break;
|
||||||
case 62: /* filter-l3 */
|
case 63: /* filter-l3 */
|
||||||
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
||||||
{
|
{
|
||||||
DLOG_ERR("bad value for --filter-l3\n");
|
DLOG_ERR("bad value for --filter-l3\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 63: /* filter-tcp */
|
case 64: /* filter-tcp */
|
||||||
if (!parse_pf_list(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);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 64: /* filter-l7 */
|
case 65: /* filter-l7 */
|
||||||
if (!parse_l7_list(optarg,&dp->filter_l7))
|
if (!parse_l7_list(optarg,&dp->filter_l7))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 65: /* ipset */
|
case 66: /* ipset */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterIpset(dp, false, optarg))
|
if (!RegisterIpset(dp, false, optarg))
|
||||||
{
|
{
|
||||||
@@ -1333,7 +1359,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 66: /* ipset-ip */
|
case 67: /* ipset-ip */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
||||||
{
|
{
|
||||||
@@ -1347,7 +1373,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 67: /* ipset-exclude */
|
case 68: /* ipset-exclude */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterIpset(dp, true, optarg))
|
if (!RegisterIpset(dp, true, optarg))
|
||||||
{
|
{
|
||||||
@@ -1356,7 +1382,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 68: /* ipset-exclude-ip */
|
case 69: /* ipset-exclude-ip */
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
||||||
{
|
{
|
||||||
@@ -1372,11 +1398,11 @@ void parse_params(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
case 69: /* enable-pf */
|
case 70: /* enable-pf */
|
||||||
params.pf_enable = true;
|
params.pf_enable = true;
|
||||||
break;
|
break;
|
||||||
#elif defined(__linux__) || defined(__APPLE__)
|
#elif defined(__linux__) || defined(__APPLE__)
|
||||||
case 69: /* local-tcp-user-timeout */
|
case 70: /* local-tcp-user-timeout */
|
||||||
params.tcp_user_timeout_local = atoi(optarg);
|
params.tcp_user_timeout_local = atoi(optarg);
|
||||||
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
|
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
|
||||||
{
|
{
|
||||||
@@ -1384,7 +1410,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 70: /* remote-tcp-user-timeout */
|
case 71: /* remote-tcp-user-timeout */
|
||||||
params.tcp_user_timeout_remote = atoi(optarg);
|
params.tcp_user_timeout_remote = atoi(optarg);
|
||||||
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
|
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
|
||||||
{
|
{
|
||||||
@@ -1395,7 +1421,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
case 71: /* mss */
|
case 72: /* mss */
|
||||||
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
|
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
|
||||||
dp->mss = atoi(optarg);
|
dp->mss = atoi(optarg);
|
||||||
if (dp->mss<88 || dp->mss>32767)
|
if (dp->mss<88 || dp->mss>32767)
|
||||||
@@ -1404,7 +1430,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 72: /* fix-seg */
|
case 73: /* fix-seg */
|
||||||
if (!params.fix_seg_avail)
|
if (!params.fix_seg_avail)
|
||||||
{
|
{
|
||||||
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
|
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
|
||||||
@@ -1424,7 +1450,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
|
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
|
||||||
break;
|
break;
|
||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
case 73: /* nosplice */
|
case 74: /* nosplice */
|
||||||
params.nosplice = true;
|
params.nosplice = true;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -1464,6 +1490,10 @@ void parse_params(int argc, char *argv[])
|
|||||||
fprintf(stderr, "could not chown %s. log file may not be writable after privilege drop\n", params.debug_logfile);
|
fprintf(stderr, "could not chown %s. log file may not be writable after privilege drop\n", params.debug_logfile);
|
||||||
if (params.droproot && *params.hostlist_auto_debuglog && chown(params.hostlist_auto_debuglog, params.uid, -1))
|
if (params.droproot && *params.hostlist_auto_debuglog && chown(params.hostlist_auto_debuglog, params.uid, -1))
|
||||||
DLOG_ERR("could not chown %s. auto hostlist debug log may not be writable after privilege drop\n", params.hostlist_auto_debuglog);
|
DLOG_ERR("could not chown %s. auto hostlist debug log may not be writable after privilege drop\n", params.hostlist_auto_debuglog);
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
bool bHasMSS=false, bHasOOB=false, bHasDisorder=false;
|
||||||
|
#endif
|
||||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||||
{
|
{
|
||||||
dp = &dpl->dp;
|
dp = &dpl->dp;
|
||||||
@@ -1474,7 +1504,22 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
if (params.droproot && dp->hostlist_auto && chown(dp->hostlist_auto->filename, params.uid, -1))
|
if (params.droproot && dp->hostlist_auto && chown(dp->hostlist_auto->filename, params.uid, -1))
|
||||||
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
|
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
|
||||||
|
#ifdef __linux__
|
||||||
|
if (dp->mss) bHasMSS=true;
|
||||||
|
if (dp->oob || dp->oob_http || dp->oob_tls) bHasOOB=true;
|
||||||
|
if (dp->disorder || dp->disorder_http || dp->disorder_tls) bHasDisorder=true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef __linux__
|
||||||
|
if (is_wsl()==1)
|
||||||
|
{
|
||||||
|
if (!params.nosplice) DLOG_CONDUP("WARNING ! WSL1 may have problems with splice. Consider using `--nosplice`.\n");
|
||||||
|
if (bHasMSS) DLOG_CONDUP("WARNING ! WSL1 does not support MSS socket option. MSS will likely fail.\n");
|
||||||
|
if (bHasOOB) DLOG_CONDUP("WARNING ! WSL1 does not support OOB. OOB will likely fail.\n");
|
||||||
|
if (bHasDisorder) DLOG_CONDUP("WARNING ! Windows retransmits whole TCP segment. Disorder will not function properly.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!LoadAllHostLists())
|
if (!LoadAllHostLists())
|
||||||
{
|
{
|
||||||
@@ -1668,6 +1713,7 @@ int main(int argc, char *argv[])
|
|||||||
struct salisten_s list[MAX_BINDS];
|
struct salisten_s list[MAX_BINDS];
|
||||||
char ip_port[48];
|
char ip_port[48];
|
||||||
|
|
||||||
|
set_console_io_buffering();
|
||||||
set_env_exedir(argv[0]);
|
set_env_exedir(argv[0]);
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
mask_from_preflen6_prepare();
|
mask_from_preflen6_prepare();
|
||||||
@@ -1918,10 +1964,16 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
set_ulimit();
|
set_ulimit();
|
||||||
sec_harden();
|
sec_harden();
|
||||||
|
|
||||||
if (params.droproot && !droproot(params.uid,params.gid))
|
if (params.droproot && !droproot(params.uid,params.gid))
|
||||||
goto exiterr;
|
goto exiterr;
|
||||||
|
#ifdef __linux__
|
||||||
|
if (!dropcaps())
|
||||||
|
goto exiterr;
|
||||||
|
#endif
|
||||||
print_id();
|
print_id();
|
||||||
|
if (params.droproot && !test_list_files())
|
||||||
|
goto exiterr;
|
||||||
|
|
||||||
//splice() causes the process to receive the SIGPIPE-signal if one part (for
|
//splice() causes the process to receive the SIGPIPE-signal if one part (for
|
||||||
//example a socket) is closed during splice(). I would rather have splice()
|
//example a socket) is closed during splice(). I would rather have splice()
|
||||||
//fail and return -1, so blocking SIGPIPE.
|
//fail and return -1, so blocking SIGPIPE.
|
||||||
|
@@ -16,6 +16,10 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#ifdef USE_SYSTEMD
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "tpws.h"
|
#include "tpws.h"
|
||||||
#include "tpws_conn.h"
|
#include "tpws_conn.h"
|
||||||
#include "redirect.h"
|
#include "redirect.h"
|
||||||
@@ -25,6 +29,15 @@
|
|||||||
#include "hostlist.h"
|
#include "hostlist.h"
|
||||||
#include "linux_compat.h"
|
#include "linux_compat.h"
|
||||||
|
|
||||||
|
static void notify_ready(void)
|
||||||
|
{
|
||||||
|
#ifdef USE_SYSTEMD
|
||||||
|
int r = sd_notify(0, "READY=1");
|
||||||
|
if (r < 0)
|
||||||
|
DLOG_ERR("sd_notify: %s\n", strerror(-r));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// keep separate legs counter. counting every time thousands of legs can consume cpu
|
// keep separate legs counter. counting every time thousands of legs can consume cpu
|
||||||
static int legs_local, legs_remote;
|
static int legs_local, legs_remote;
|
||||||
/*
|
/*
|
||||||
@@ -1542,6 +1555,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
|
|||||||
VPRINT("initialized multi threaded resolver with %d threads\n",resolver_thread_count());
|
VPRINT("initialized multi threaded resolver with %d threads\n",resolver_thread_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notify_ready();
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
ReloadCheck();
|
ReloadCheck();
|
||||||
@@ -1755,8 +1770,6 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
|
|||||||
// at least one leg was removed. recount legs
|
// at least one leg was removed. recount legs
|
||||||
print_legs();
|
print_legs();
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(stderr); fflush(stdout); // for console messages
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ex:
|
ex:
|
||||||
|
Reference in New Issue
Block a user