mirror of
https://github.com/bol-van/zapret.git
synced 2025-08-10 01:02:03 +03:00
Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a560e251a1 | ||
|
2ff0f9c0ff | ||
|
4dbd673eaa | ||
|
497810ab4e | ||
|
4cfed1db7e | ||
|
fd6b7a2b7f | ||
|
6d865ad790 | ||
|
dfe36aee4c | ||
|
2d704a859d | ||
|
8026d11f71 | ||
|
2f77cec863 | ||
|
ba7954f068 | ||
|
8b5c951451 | ||
|
84e75b0f28 | ||
|
c4e5db309f | ||
|
769f7b60c8 | ||
|
b0578c5e9f | ||
|
40362bfb5b | ||
|
10eb9050a1 | ||
|
b63e598085 | ||
|
c60f9c9027 | ||
|
951c980bec | ||
|
5eaec085dd | ||
|
721b353776 | ||
|
e6d2051c87 | ||
|
e665794ac4 | ||
|
7db14a07c5 | ||
|
c14554c1f3 | ||
|
ced1682003 | ||
|
4701f27372 | ||
|
a1699067b3 | ||
|
643fc0c456 | ||
|
09c07f6d21 | ||
|
dd72c68ae6 | ||
|
9c1a3e77cc | ||
|
ae957e9a73 | ||
|
bc47a13ba4 | ||
|
20b69cb63d | ||
|
ef4f8a2b86 | ||
|
d00d341505 | ||
|
0738d3980f | ||
|
34ff4630bf | ||
|
f8b5f602a4 | ||
|
8dacb57a86 |
@@ -396,13 +396,24 @@ check_system()
|
||||
PKTWS="$WINWS"
|
||||
PKTWSD=winws
|
||||
FWTYPE=windivert
|
||||
# ts fooling requires timestamps. they are disabled by default in windows.
|
||||
echo enabling tcp timestamps
|
||||
netsh interface tcp set global timestamps=enabled >/dev/null
|
||||
;;
|
||||
*)
|
||||
echo $UNAME not supported
|
||||
exitp 5
|
||||
esac
|
||||
echo $UNAME${SUBSYS:+/$SUBSYS} detected
|
||||
echo -n 'kernel: '
|
||||
if [ -f "/proc/version" ]; then
|
||||
cat /proc/version
|
||||
else
|
||||
uname -a
|
||||
fi
|
||||
echo firewall type is $FWTYPE
|
||||
echo CURL=$CURL
|
||||
$CURL --version
|
||||
}
|
||||
|
||||
zp_already_running()
|
||||
@@ -627,7 +638,11 @@ curl_with_subst_ip()
|
||||
# $2 - port
|
||||
# $3 - ip
|
||||
# $4+ - curl params
|
||||
local connect_to="--connect-to $1::[$3]${2:+:$2}" arg
|
||||
local ip="$3"
|
||||
case "$ip" in
|
||||
*:*) ip="[$ip]" ;;
|
||||
esac
|
||||
local connect_to="--connect-to $1::$ip${2:+:$2}" arg
|
||||
shift ; shift ; shift
|
||||
[ "$CURL_VERBOSE" = 1 ] && arg="-v"
|
||||
[ "$CURL_CMD" = 1 ] && echo $CURL ${arg:+$arg }$connect_to "$@"
|
||||
@@ -1183,6 +1198,7 @@ warn_fool()
|
||||
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.' ;;
|
||||
ts) echo 'WARNING ! although ts fooling worked it will not work without timestamps being enabled in the client OS. In windows timestamps are DISABLED by default.'
|
||||
esac
|
||||
}
|
||||
pktws_curl_test_update_vary()
|
||||
@@ -1309,7 +1325,7 @@ pktws_check_domain_http_bypass_()
|
||||
}
|
||||
f=
|
||||
[ "$UNAME" = "OpenBSD" ] || f="badsum"
|
||||
f="$f badseq datanoack md5sig"
|
||||
f="$f badseq datanoack ts md5sig"
|
||||
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
|
||||
for fooling in $f; do
|
||||
ok=0
|
||||
|
@@ -406,12 +406,15 @@ has_bad_ws_options()
|
||||
{
|
||||
# $1 - nfqws/tpws opts
|
||||
|
||||
# kernel or user mode ipset usage should be wise
|
||||
# if all traffic is already intercepted it would be OK to use ip-based specialized profiles
|
||||
# but if all traffic is intercepted only to filter a group of ip its BAD. kernel ipset should be used.
|
||||
# I cannot insert brain to copy-pasters, I know they will misuse. But it's their problem.
|
||||
# zapret is not made for newbies
|
||||
#contains "$1" "--ipset"
|
||||
contains "$1" "--ipset" && {
|
||||
echo
|
||||
echo "WARNING !!! --ipset parameter is present"
|
||||
echo "It's OK if you only specialize already redirected traffic and also process the rest."
|
||||
echo "If you redirect port X to process several IPs from the list and do nothing with the rest - IT'S VERY INEFFECTIVE !"
|
||||
echo "Kernel ipsets should be used instead. Write custom scripts and filter IPs in kernel."
|
||||
echo
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
check_bad_ws_options()
|
||||
@@ -428,8 +431,5 @@ check_bad_ws_options()
|
||||
}
|
||||
help_bad_ws_options()
|
||||
{
|
||||
echo "WARNING ! you have specified --ipset option"
|
||||
echo "WARNING ! it would work but on ${UNAME:-$(uname)} it's not the best option"
|
||||
echo "WARNING ! you should use kernel mode sets. they are much more efficient."
|
||||
echo "WARNING ! to use ipsets you have to write your own custom script"
|
||||
echo "WARNING ! BAD options detected"
|
||||
}
|
||||
|
@@ -112,6 +112,10 @@ unprepare_tpws_fw()
|
||||
unprepare_tpws_fw4
|
||||
}
|
||||
|
||||
ipt_mark_filter()
|
||||
{
|
||||
[ -n "$FILTER_MARK" ] && echo "-m mark --mark $FILTER_MARK/$FILTER_MARK"
|
||||
}
|
||||
|
||||
ipt_print_op()
|
||||
{
|
||||
@@ -136,7 +140,7 @@ _fw_tpws4()
|
||||
|
||||
ipt_print_op $1 "$2" "tpws (port $3)"
|
||||
|
||||
rule="$2 $IPSET_EXCLUDE dst $IPBAN_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3"
|
||||
rule="$(ipt_mark_filter) $2 $IPSET_EXCLUDE dst $IPBAN_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3"
|
||||
for i in $4 ; do
|
||||
ipt_add_del $1 PREROUTING -t nat -i $i $rule
|
||||
done
|
||||
@@ -164,7 +168,7 @@ _fw_tpws6()
|
||||
|
||||
ipt_print_op $1 "$2" "tpws (port $3)" 6
|
||||
|
||||
rule="$2 $IPSET_EXCLUDE6 dst $IPBAN_EXCLUDE6 dst"
|
||||
rule="$(ipt_mark_filter) $2 $IPSET_EXCLUDE6 dst $IPBAN_EXCLUDE6 dst"
|
||||
for i in $4 ; do
|
||||
_dnat6_target $i DNAT6
|
||||
[ -n "$DNAT6" -a "$DNAT6" != "-" ] && ipt6_add_del $1 PREROUTING -t nat -i $i $rule -j DNAT --to [$DNAT6]:$3
|
||||
@@ -202,7 +206,7 @@ _fw_nfqws_post4()
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)"
|
||||
|
||||
rule="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
rule="$(ipt_mark_filter) -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
ipt_add_del $1 POSTROUTING -t mangle -o $i $rule
|
||||
@@ -223,7 +227,7 @@ _fw_nfqws_post6()
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)" 6
|
||||
|
||||
rule="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
rule="$(ipt_mark_filter) -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
ipt6_add_del $1 POSTROUTING -t mangle -o $i $rule
|
||||
|
@@ -312,6 +312,10 @@ nft_filter_apply_ipset_target()
|
||||
nft_filter_apply_ipset_target6 $2
|
||||
}
|
||||
|
||||
nft_mark_filter()
|
||||
{
|
||||
[ -n "$FILTER_MARK" ] && echo "mark and $FILTER_MARK != 0"
|
||||
}
|
||||
|
||||
nft_script_add_ifset_element()
|
||||
{
|
||||
@@ -403,9 +407,10 @@ _nft_fw_tpws4()
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2"
|
||||
local mark_filter=$(nft_mark_filter)
|
||||
nft_print_op "$filter" "tpws (port $2)" 4
|
||||
nft_insert_rule dnat_output skuid != $WS_USER ${3:+oifname @wanif }$filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
|
||||
nft_insert_rule dnat_pre iifname @lanif $filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
|
||||
nft_insert_rule dnat_output skuid != $WS_USER ${3:+oifname @wanif} $mark_filter $filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
|
||||
nft_insert_rule dnat_pre iifname @lanif $mark_filter $filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
|
||||
prepare_route_localnet
|
||||
}
|
||||
}
|
||||
@@ -418,10 +423,11 @@ _nft_fw_tpws6()
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" DNAT6 i
|
||||
local mark_filter=$(nft_mark_filter)
|
||||
nft_print_op "$filter" "tpws (port $port)" 6
|
||||
nft_insert_rule dnat_output skuid != $WS_USER ${4:+oifname @wanif6 }$filter ip6 daddr != @nozapret6 ip6 daddr != @ipban6 $FW_EXTRA_POST dnat ip6 to [::1]:$port
|
||||
nft_insert_rule dnat_output skuid != $WS_USER ${4:+oifname @wanif6} $mark_filter $filter ip6 daddr != @nozapret6 ip6 daddr != @ipban6 $FW_EXTRA_POST dnat ip6 to [::1]:$port
|
||||
[ -n "$3" ] && {
|
||||
nft_insert_rule dnat_pre $filter ip6 daddr != @nozapret6 ip6 daddr != @ipban6 $FW_EXTRA_POST dnat ip6 to iifname map @link_local:$port
|
||||
nft_insert_rule dnat_pre $mark_filter $filter ip6 daddr != @nozapret6 ip6 daddr != @ipban6 $FW_EXTRA_POST dnat ip6 to iifname map @link_local:$port
|
||||
for i in $3; do
|
||||
_dnat6_target $i DNAT6
|
||||
# can be multiple tpws processes on different ports
|
||||
@@ -468,7 +474,7 @@ _nft_fw_nfqws_post4()
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_postchain) setmark
|
||||
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4
|
||||
rule="${3:+oifname @wanif }$filter ip daddr != @nozapret"
|
||||
rule="${3:+oifname @wanif} $(nft_mark_filter) $filter ip daddr != @nozapret"
|
||||
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
|
||||
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||
@@ -483,7 +489,7 @@ _nft_fw_nfqws_post6()
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_postchain) setmark
|
||||
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6
|
||||
rule="${3:+oifname @wanif6 }$filter ip6 daddr != @nozapret6"
|
||||
rule="${3:+oifname @wanif6} $(nft_mark_filter) $filter ip6 daddr != @nozapret6"
|
||||
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
|
||||
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||
@@ -508,7 +514,7 @@ _nft_fw_nfqws_pre4()
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule
|
||||
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 4
|
||||
rule="${3:+iifname @wanif }$filter ip saddr != @nozapret"
|
||||
rule="${3:+iifname @wanif} $filter ip saddr != @nozapret"
|
||||
nft_insert_rule $(get_prechain) $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
}
|
||||
}
|
||||
@@ -521,7 +527,7 @@ _nft_fw_nfqws_pre6()
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule
|
||||
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 6
|
||||
rule="${3:+iifname @wanif6 }$filter ip6 saddr != @nozapret6"
|
||||
rule="${3:+iifname @wanif6} $filter ip6 saddr != @nozapret6"
|
||||
nft_insert_rule $(get_prechain) $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
}
|
||||
}
|
||||
|
@@ -47,6 +47,12 @@ GZIP_LISTS=1
|
||||
DESYNC_MARK=0x40000000
|
||||
DESYNC_MARK_POSTNAT=0x20000000
|
||||
|
||||
# do not pass outgoing traffic to tpws/nfqws not marked with this bit
|
||||
# this setting allows to write your own rules to limit traffic that should be fooled
|
||||
# for example based on source IP or incoming interface name
|
||||
# no filter if not defined
|
||||
#FILTER_MARK=0x10000000
|
||||
|
||||
TPWS_SOCKS_ENABLE=0
|
||||
# tpws socks listens on this port on localhost and LAN interfaces
|
||||
TPPORT_SOCKS=987
|
||||
|
@@ -312,7 +312,7 @@ In OpenBSD default `tpws` bind is ipv6 only. To bind to ipv4 specify
|
||||
Use `--bind-addr=0.0.0.0 --bind-addr=::` to achieve the same default bind as in
|
||||
others OSes.
|
||||
|
||||
`tpws` for forwarded traffic only :
|
||||
`tpws` for forwarded traffic only (OLDER OS versions):
|
||||
|
||||
`/etc/pf.conf`:
|
||||
```
|
||||
@@ -323,13 +323,31 @@ pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988
|
||||
Then:
|
||||
```
|
||||
pfctl -f /etc/pf.conf
|
||||
tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
|
||||
tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 --enable-pf
|
||||
```
|
||||
|
||||
Its not clear how to do rdr-to outgoing traffic. I could not make route-to
|
||||
scheme work. rdr-to support is done using /dev/pf, that's why transparent mode
|
||||
requires root.
|
||||
|
||||
`tpws` for forwarded traffic only (NEWER OS versions):
|
||||
|
||||
```
|
||||
pass on em1 inet proto tcp to port {80,443} divert-to 127.0.0.1 port 989
|
||||
pass on em1 inet6 proto tcp to port {80,443} divert-to ::1 port 989
|
||||
```
|
||||
|
||||
Then:
|
||||
```
|
||||
pfctl -f /etc/pf.conf
|
||||
tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
|
||||
```
|
||||
|
||||
tpws must be bound exactly to diverted IPs, not `0.0.0.0` or `::`.
|
||||
|
||||
It's also not clear how to divert connections from local system.
|
||||
|
||||
|
||||
`dvtws` for all traffic:
|
||||
|
||||
`/etc/pf.conf`:
|
||||
|
33
docs/bsd.md
33
docs/bsd.md
@@ -19,7 +19,8 @@
|
||||
* [pfsense](#pfsense)
|
||||
* [OpenBSD](#openbsd)
|
||||
* [tpws bind на ipv4](#tpws-bind-на-ipv4)
|
||||
* [tpws для проходящего трафика](#tpws-для-проходящего-трафика)
|
||||
* [tpws для проходящего трафика (старые системы)](#tpws-для-проходящего-трафика-старая-схема-не-работает-в-новых-версиях))
|
||||
* [tpws для проходящего трафика (новые системы)](#tpws-для-проходящего-трафика-новые-системы))
|
||||
* [Запуск dvtws](#запуск-dvtws)
|
||||
* [Проблемы с badsum](#проблемы-с-badsum)
|
||||
* [Особенность отправки fake пакетов](#особенность-отправки-fake-пакетов)
|
||||
@@ -392,7 +393,11 @@ rdr pass on em1 inet6 proto tcp from any to any port = https -> fe80::20c:29ff:5
|
||||
Но лучше все же так не делать, а сажать на определенные внутренние адреса или интерфейсы.
|
||||
|
||||
|
||||
### tpws для проходящего трафика
|
||||
### tpws для проходящего трафика (старая схема не работает в новых версиях)
|
||||
|
||||
В этом варианте tpws обращается явно к редиректору pf и пытается от него получить оригинальный адрес назначения.
|
||||
Как показывает практика, это не работает на новых версиях OpenBSD. Возвращается ошибка ioctl.
|
||||
Последняя проверенная версия, где это работает, - 6.8 . Между 6.8 и 7.4 разработчики сломали этот механизм.
|
||||
|
||||
`/etc/pf.conf`:
|
||||
```
|
||||
@@ -402,15 +407,35 @@ pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988
|
||||
|
||||
```sh
|
||||
$ pfctl -f /etc/pf.conf
|
||||
$ tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
|
||||
$ tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 --enable-pf
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> [!NOTE]
|
||||
> В PF не выходит делать rdr-to с той же системы, где работает proxy.
|
||||
> Вариант с route-to не сохраняет мета информацию. Адрес назначения теряется.
|
||||
> Поэтому этот вариант годится для squid, берущего адрес из протокола прикладного уровня, но не годится для tpws, полагающегося на метаданные ОС.
|
||||
> Поддержка rdr-to реализована через `/dev/pf`, поэтому прозрачный режим **требует root**.
|
||||
|
||||
### tpws для проходящего трафика (новые системы)
|
||||
|
||||
В новых версиях предлагается использовать divert-to вместо rdr-to.
|
||||
Минимально проверенная версия, где это работает, 7.4. Может работать или не работать на более старых - исследование не проводилось.
|
||||
|
||||
`/etc/pf.conf`:
|
||||
```
|
||||
pass on em1 inet proto tcp to port {80,443} divert-to 127.0.0.1 port 989
|
||||
pass on em1 inet6 proto tcp to port {80,443} divert-to ::1 port 989
|
||||
```
|
||||
|
||||
tpws должен иметь бинд на точно такой адрес, который указан в правилах pf. `0.0.0.0` или `::` не работает.
|
||||
|
||||
```sh
|
||||
$ pfctl -f /etc/pf.conf
|
||||
$ tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Так же не понятно как делать divert с самой системы, где работает tpws.
|
||||
|
||||
### Запуск dvtws
|
||||
|
||||
|
@@ -56,14 +56,27 @@ sysctl net.inet6.ip6.forwarding=1
|
||||
|
||||
OpenBSD PF :
|
||||
|
||||
(OLD OpenBSD versions)
|
||||
|
||||
; dont know how to rdr-to from local system. doesn't seem to work. only works for routed traffic.
|
||||
|
||||
/etc/pf.conf
|
||||
pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988
|
||||
pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988
|
||||
pfctl -f /etc/pf.conf
|
||||
/opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 --enable-pf
|
||||
|
||||
(NEW OpenBSD versions)
|
||||
|
||||
; dont know how to divert-to from local system
|
||||
|
||||
/etc/pf.conf
|
||||
pass on em1 inet proto tcp to port {80,443} divert-to 127.0.0.1 port 989
|
||||
pass on em1 inet6 proto tcp to port {80,443} divert-to ::1 port 989
|
||||
pfctl -f /etc/pf.conf
|
||||
/opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
|
||||
|
||||
|
||||
; dvtws works both for routed and local
|
||||
|
||||
pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state
|
||||
|
@@ -514,6 +514,23 @@ install_easy: stop if running embedded release on traditional linux system (some
|
||||
install_bin: add "read elf" arch detection method
|
||||
binaries: renamed arch dirs in binaries
|
||||
|
||||
v71.2
|
||||
v71.1.1
|
||||
|
||||
nfqws: use wireless ext in case nl80211 does not return SSID
|
||||
|
||||
v71.2
|
||||
|
||||
nfqws: apply udp desync to replayed packets with non-zero reasm offset (except fake)
|
||||
blockcheck: display curl version and kernel version
|
||||
install_bin: stop if no binaries found. display help text.
|
||||
winws: increase buffers for port filter
|
||||
tpws: tpws no more opens /dev/pf in OpenBSD by default. requires --enable-pf like in FreeBSD. this is migration from rdr-to to divert-to redirection scheme.
|
||||
install_easy: warn if --ipset parameter is specified
|
||||
|
||||
v71.3
|
||||
|
||||
init.d: FILTER_MARK
|
||||
nfqws: ts fooling
|
||||
blockcheck: test ts fooling
|
||||
blockcheck: auto enable tcp timestamps in windows
|
||||
tpws,nfqws: special handling of IP-like hostnames. strip :port from hostname:port
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# zapret v71.1.1
|
||||
# zapret v71.3
|
||||
|
||||
# SCAMMER WARNING
|
||||
|
||||
@@ -175,6 +175,7 @@ nfqws takes the following parameters:
|
||||
--dup-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-64. "0:0-0" or "-" disables autottl.
|
||||
--dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dup-autottl for ipv6 only
|
||||
--dup-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2
|
||||
--dup-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment for dup. default -600000
|
||||
--dup-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment for dup. default -10000
|
||||
--dup-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment for dup. default -66000
|
||||
--dup-start=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
||||
@@ -197,6 +198,7 @@ nfqws takes the following parameters:
|
||||
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder
|
||||
--dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8.
|
||||
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32.
|
||||
--dpi-desync-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment. default -600000
|
||||
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
|
||||
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
|
||||
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
||||
@@ -286,6 +288,12 @@ Fakes are separate generated by nfqws packets carrying false information for DPI
|
||||
* **datanoack** sends tcp fakes without ACK flag. Servers do not accept this but DPI may accept.
|
||||
This mode may break NAT and may not work with iptables if masquerade is used, even from the router itself.
|
||||
Works with nftables properly. Likely requires external IP address (some ISPs pass these packets through their NAT).
|
||||
* **ts** adds to TSval ts increment value (-600000 by default). Servers discard packets with TSval in some range.
|
||||
Practical tests suggest increment between -100 and -0x80000000.
|
||||
Timestamps are generated by client OS. In linux timestamps are enabled by default. In windows by default timestamps are disabled.
|
||||
They can be enabled with this command : `netsh interface tcp set global timestamps=enabled` .
|
||||
ts fooling requires that timestamps are enabled. They must be enabled on every client OS.
|
||||
TSecr is left unmodified.
|
||||
* **autottl** tries to automatically guess hop count to the server and compute TTL by adding some delta value that can be positive or negative.
|
||||
Positive deltas must be preceeded by unary `+` sign. Deltas without any unary sign are treated negative for old versions compatibility reasons.
|
||||
This tech relies on well known TTL default values used by OS : 64,128,255.
|
||||
@@ -556,9 +564,9 @@ There is special support for all tcp split options for multi segment TLS. Split
|
||||
### UDP support
|
||||
|
||||
UDP attacks are limited. Its not possible to fragment UDP on transport level, only on network (ip) level.
|
||||
Only desync modes `fake`,`hopbyhop`,`destopt`,`ipfrag1` and `ipfrag2` are applicable.
|
||||
`fake`,`hopbyhop`,`destopt` can be used in combo with `ipfrag2`.
|
||||
`fake` can be used in combo with `udplen` and `tamper`.
|
||||
Only desync modes `fake`,`fakeknown`,`hopbyhop`,`destopt`,`ipfrag1`,`ipfrag2`,`udplen` and `tamper` are applicable.
|
||||
`fake`,`fakeknown`,`hopbyhop`,`destopt`,`ipfrag1` are 1st phase modes, others - 2nd phase.
|
||||
As always it's possible to combine one mode from 1st phase with one mode from 2nd phase but not possible to mix same phase modes.
|
||||
|
||||
`udplen` increases udp payload size by `--dpi-desync-udplen-increment` bytes. Padding is filled with zeroes by default but can be overriden with a pattern.
|
||||
This option can resist DPIs that track outgoing UDP packet sizes.
|
||||
@@ -1225,6 +1233,23 @@ Don't use `<HOSTLIST>` in highly specialized profiles. Use your own filter or ho
|
||||
`<HOSTLIST_NOAUTO>` marker uses standard autohostlist as usual hostlist thus disabling auto additions in this profile.
|
||||
If any other profile adds something this profile accepts the change automatically.
|
||||
|
||||
Change loop prevention mark bit
|
||||
|
||||
`DESYNC_MARK=0x40000000`
|
||||
|
||||
Change postnat scheme mark bit
|
||||
|
||||
`DESYNC_MARK_POSTNAT=0x20000000`
|
||||
|
||||
If uncommented pass to zapret only packets marked with this bit
|
||||
|
||||
`#FILTER_MARK_POSTNAT=0x10000000`
|
||||
|
||||
Bit must be set in your own rules.
|
||||
* iptables - in mangle PREROUTING and mangle OUTPUT before zapret rules (iptables -I _after_ zapret rules application).
|
||||
* nftables - in output and prerouting hooks with priority -102 or lower.
|
||||
|
||||
Mark criterias can be any. For example, source IP or source interface name.
|
||||
|
||||
**tpws** socks proxy mode switch
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# zapret v71.1.1
|
||||
# zapret v71.3
|
||||
|
||||
# ВНИМАНИЕ, остерегайтесь мошенников
|
||||
|
||||
@@ -195,7 +195,8 @@ dvtws, собираемый из тех же исходников (см. [док
|
||||
--dup-ttl6=<int> ; модифицировать ipv6 hop limit дубликатов. если не указано, используется значение --dup-ttl
|
||||
--dup-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +1:3-64. "0:0-0" или "-" отключает функцию
|
||||
--dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
|
||||
--dup-fooling=<fooling> ; дополнительные методики как сделать, чтобы дубликат не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
|
||||
--dup-fooling=<fooling> ; дополнительные методики как сделать, чтобы дубликат не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2
|
||||
--dup-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000
|
||||
--dup-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
|
||||
--dup-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
||||
--dup-start=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
||||
@@ -211,13 +212,14 @@ dvtws, собираемый из тех же исходников (см. [док
|
||||
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение --dpi-desync-ttl
|
||||
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. "0:0-0" или "-" отключает функцию
|
||||
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
|
||||
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
|
||||
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2
|
||||
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
|
||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
||||
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
|
||||
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
|
||||
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; чем заполнять фейковую часть overlap
|
||||
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; чем заполнять фейки в fakedsplit/fakeddisorder
|
||||
--dpi-desync-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000
|
||||
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
|
||||
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
||||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||||
@@ -339,6 +341,12 @@ dvtws, собираемый из тех же исходников (см. [док
|
||||
выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому работает даже с внутренним провайдерским IP.
|
||||
Но linux NAT оно не пройдет, так что за домашним роутером эта техника скорее всего не сработает, но может сработать с него.
|
||||
Может сработать и через роутер, если подключение по проводу, и на роутере включено аппаратное ускорение.
|
||||
* `ts` прибавляет к значению TSval таймштампа tcp значение ts increment (по умолчанию -600000). Сервера отбрасывают пакеты
|
||||
с TSval в определенных пределах. По практическим тестам инкремент должен быть где-то от -100 до -0x80000000.
|
||||
timestamps генерирует клиентская ОС. В linux таймштампы включены по умолчанию, в windows выключены по умолчанию.
|
||||
Можно включить через команду `netsh interface tcp set global timestamps=enabled`.
|
||||
ts fooling требует, чтобы таймштампы были включены, иначе работать не будет. Включать надо на каждом клиентском устройстве.
|
||||
TSecr оставляется без изменений. Так же требуется, чтобы сервер понимал timestamps, но это в большинстве случаев так.
|
||||
* `autottl`. Суть режима в автоматическом определении TTL, чтобы пакет почти наверняка прошел DPI и немного не дошел до
|
||||
сервера (`--dpi-desync-autottl`). Или наоборот - TTL едва хватило, чтобы он все-таки дошел до сервера (см `--dup-autottl`, `--orig-autottl`).
|
||||
Берутся базовые значения TTL 64,128,255, смотрится входящий пакет (да, требуется направить первый входящий пакет на nfqws !).
|
||||
@@ -662,8 +670,11 @@ chrome рандомизирует фингерпринт TLS. SNI может о
|
||||
### ПОДДЕРЖКА UDP
|
||||
|
||||
Атаки на udp более ограничены в возможностях. udp нельзя фрагментировать иначе, чем на уровне ip.
|
||||
Для UDP действуют только режимы десинхронизации `fake`, `hopbyhop`, `destopt`, `ipfrag1`, `ipfrag2`, `udplen`, `tamper`.
|
||||
Возможно сочетание `fake`, `hopbyhop`, `destopt` с `ipfrag2`, `fake`, `fakeknown` с udplen и tamper.
|
||||
|
||||
Для UDP действуют только режимы десинхронизации `fake`, `fakeknown`, `hopbyhop`, `destopt`, `ipfrag1`, `ipfrag2`, `udplen`, `tamper`.
|
||||
Режимами первой фазы являются `fake`, `fakeknown`, `hopbyhop`, `destopt`, `ipfrag1`. Второй фазы - `ipfrag2`, `udplen`, `tamper`.
|
||||
Как обычно, возможно сочетание режимов первой и второй фазы, но не двух режимов одной фазы.
|
||||
|
||||
`udplen` увеличивает размер udp пакета на указанное в `--dpi-desync-udplen-increment` количество байтов.
|
||||
Паддинг заполняется нулями по умолчанию, но можно задать свой паттерн.
|
||||
Предназначено для обмана DPI, ориентирующегося на размеры пакетов.
|
||||
@@ -1491,7 +1502,7 @@ LISTS_RELOAD=- отключает перезагрузку листов.
|
||||
`ipset/zapret-hosts-users.txt.gz` или `ipset/zapret-hosts-users.txt`,
|
||||
`ipset/zapret-hosts.txt.gz` или `ipset/zapret-hosts.txt`
|
||||
и 1 exclude список
|
||||
`ipset/zapret-hosts-users-exclude.txt.gz` или `ipset/zapret-hosts-users-exclude.txt`
|
||||
`ipset/zapret-hosts-user-exclude.txt.gz` или `ipset/zapret-hosts-user-exclude.txt`
|
||||
|
||||
При режимах фильтрации `MODE_FILTER=hostlist` или `MODE_FILTER=autohostlist` система запуска передает **nfqws** или **tpws** все листы, файлы которых присутствуют.
|
||||
Передача происходит через замену маркеров `<HOSTLIST>` и `<HOSTLIST_NOAUTO>` на реальные параметры `--hostlist`, `--hostlist-exclude`, `--hostlist-auto`.
|
||||
@@ -1830,6 +1841,21 @@ nfqws начнет получать адреса пакетов из локал
|
||||
То есть на этом профиле не происходит автоматическое добавление заблокированных доменов.
|
||||
Но если на другом профиле что-то будет добавлено, то этот профиль примет изменения автоматически.
|
||||
|
||||
***Изменение бита mark для предотвращения зацикливания***\
|
||||
`DESYNC_MARK=0x40000000`
|
||||
|
||||
***Изменение бита mark для пометки пакетов, проходящих по POSTNAT схеме (только nftables)***\
|
||||
`DESYNC_MARK_POSTNAT=0x20000000`
|
||||
|
||||
***Если раскоментировано, пометка пакетов, которые должны быть обработаны zapret.***\
|
||||
`#FILTER_MARK_POSTNAT=0x10000000`
|
||||
|
||||
Бит должен быть установлен вашими собственными правилами.
|
||||
* Для iptables - в цепочках mangle PREROUTING и mangle OUTPUT перед правилами zapret (iptables -I _после_ применения правил zapret).
|
||||
* Для nftables - в хуках output и prerouting с приоритетом -102 или ниже.
|
||||
|
||||
Критерии пометки любые. Например, IP адрес или интерфейс источника. Это ответ на вопрос "как мне сделать, чтобы телик не ходил через zapret или чтобы через него ходил только мой комп".
|
||||
|
||||
***Включение стандартной опции tpws в режиме socks***\
|
||||
`TPWS_SOCKS_ENABLE=0`
|
||||
|
||||
|
@@ -84,7 +84,7 @@ SubInterface используется windivert, но практически в
|
||||
autottl и autohostlist. При включении autohostlist так же перенаправляются пакеты данных с http redirect с кодами 302 и 307.
|
||||
Всегда добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6.
|
||||
Для сложных нестандартных сценариев могут потребоваться свои фильтры. Логично будет начать со стандартного шаблона,
|
||||
сохраненного через `--wf-save`. Нужно править файл и подсовывать его в параметре `--wf-raw`. Максимальный размер фильтра - **8 Kb**.
|
||||
сохраненного через `--wf-save`. Нужно править файл и подсовывать его в параметре `--wf-raw`. Максимальный размер фильтра - **16 Kb**.
|
||||
|
||||
Можно запускать несколько процессов **winws** с разными стратегиями. Однако, не следует делать пересекающиеся фильтры.
|
||||
|
||||
|
@@ -127,8 +127,41 @@ ccp()
|
||||
#cp -f "../$BINS/$1" "$ZAPRET_BASE/$2" && echo copying : "../$BINS/$1" =\> "$ZAPRET_BASE/$2"
|
||||
}
|
||||
|
||||
|
||||
UNAME=$(uname)
|
||||
|
||||
[ "$1" = getarch ] ||
|
||||
if [ ! -d "$BINDIR" ] || ! dir_is_not_empty "$BINDIR" ]; then
|
||||
echo "no binaries found"
|
||||
case $UNAME in
|
||||
Linux)
|
||||
echo "you need to download release from github or build binaries from source"
|
||||
echo "building from source requires debian/ubuntu packages : make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libmnl-dev libsystemd-dev"
|
||||
echo "libsystemd-dev required only on systemd based systems"
|
||||
echo "on distributions with other package manager find dev package analogs"
|
||||
echo "to compile on systems with systemd : make systemd"
|
||||
echo "to compile on other systems : make"
|
||||
;;
|
||||
Darwin)
|
||||
echo "you need to download release from github or build binaries from source"
|
||||
echo "to compile : make mac"
|
||||
;;
|
||||
FreeBSD)
|
||||
echo "you need to download release from github or build binaries from source"
|
||||
echo "to compile : make"
|
||||
;;
|
||||
OpenBSD)
|
||||
echo "to compile : make bsd"
|
||||
;;
|
||||
CYGWIN*)
|
||||
echo "you need to download release from github or build binaries from source"
|
||||
echo "to compile : read docs"
|
||||
echo "to make things easier use zapret-win-bundle"
|
||||
;;
|
||||
esac
|
||||
exit 1
|
||||
fi
|
||||
|
||||
unset PKTWS
|
||||
case $UNAME in
|
||||
Linux)
|
||||
|
@@ -102,7 +102,7 @@ check_bins()
|
||||
make_target=systemd
|
||||
;;
|
||||
esac
|
||||
CFLAGS="${cf:+$cf }${CFLAGS}" make -C "$EXEDIR" $make_target || {
|
||||
CFLAGS="${cf:+$cf }${CFLAGS}" OPTIMIZE=-O2 make -C "$EXEDIR" $make_target || {
|
||||
echo could not compile
|
||||
make -C "$EXEDIR" clean
|
||||
exitp 8
|
||||
|
@@ -1,5 +1,6 @@
|
||||
CC ?= gcc
|
||||
CFLAGS += -std=gnu99 -Os -flto=auto
|
||||
CC ?= cc
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_WIN = -static
|
||||
LIBS =
|
||||
|
@@ -1,5 +1,6 @@
|
||||
CC ?= gcc
|
||||
CFLAGS += -std=gnu99 -Os
|
||||
CC ?= cc
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE)
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_WIN = -static
|
||||
LIBS = -lpthread
|
||||
|
@@ -1,5 +1,6 @@
|
||||
CC ?= cc
|
||||
CFLAGS += -std=gnu99 -s -Os -Wno-address-of-packed-member -flto=auto
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto -Wno-address-of-packed-member
|
||||
LIBS = -lz
|
||||
SRC_FILES = *.c crypto/*.c
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
CC ?= gcc
|
||||
CFLAGS += -std=gnu99 -Os -flto=auto
|
||||
CC ?= cc
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
|
||||
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
||||
|
@@ -29,6 +29,7 @@ void ConntrackClearHostname(t_ctrack *track)
|
||||
{
|
||||
free(track->hostname);
|
||||
track->hostname = NULL;
|
||||
track->hostname_is_ip = false;
|
||||
}
|
||||
static void ConntrackClearTrack(t_ctrack *track)
|
||||
{
|
||||
|
@@ -86,6 +86,7 @@ typedef struct
|
||||
t_l7proto l7proto;
|
||||
bool l7proto_discovered;
|
||||
char *hostname;
|
||||
bool hostname_is_ip;
|
||||
bool hostname_discovered;
|
||||
bool hostname_ah_check; // should perform autohostlist checks
|
||||
|
||||
|
@@ -118,6 +118,7 @@ static void fill_tcphdr(
|
||||
uint16_t nsport, uint16_t ndport,
|
||||
uint16_t nwsize, uint8_t scale_factor,
|
||||
uint32_t *timestamps,
|
||||
uint32_t ts_increment,
|
||||
uint32_t badseq_increment,
|
||||
uint32_t badseq_ack_increment,
|
||||
uint16_t data_len)
|
||||
@@ -165,13 +166,13 @@ static void fill_tcphdr(
|
||||
*(uint32_t*)(tcpopt+t+14)=random();
|
||||
t+=18;
|
||||
}
|
||||
if (timestamps || (fooling & FOOL_TS))
|
||||
if (timestamps)
|
||||
{
|
||||
tcpopt[t] = 8; // kind
|
||||
tcpopt[t+1] = 10; // len
|
||||
// forge only TSecr if orig timestamp is present
|
||||
*(uint32_t*)(tcpopt+t+2) = timestamps ? timestamps[0] : -1;
|
||||
*(uint32_t*)(tcpopt+t+6) = (timestamps && !(fooling & FOOL_TS)) ? timestamps[1] : -1;
|
||||
memcpy(tcpopt+t+2,timestamps,8);
|
||||
// forge TSval, keep TSecr
|
||||
if (fooling & FOOL_TS) *(uint32_t*)(tcpopt+t+2) = net32_add(*(uint32_t*)(tcpopt+t+2),ts_increment);
|
||||
t+=10;
|
||||
}
|
||||
if (scale_factor!=SCALE_NONE)
|
||||
@@ -242,6 +243,7 @@ bool prepare_tcp_segment4(
|
||||
uint8_t tos,
|
||||
uint16_t ip_id,
|
||||
uint32_t fooling,
|
||||
uint32_t ts_increment,
|
||||
uint32_t badseq_increment,
|
||||
uint32_t badseq_ack_increment,
|
||||
const void *data, uint16_t len,
|
||||
@@ -257,7 +259,7 @@ bool prepare_tcp_segment4(
|
||||
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
|
||||
|
||||
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, DF, ttl, tos, ip_id);
|
||||
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
|
||||
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,ts_increment,badseq_increment,badseq_ack_increment,len);
|
||||
|
||||
memcpy(payload,data,len);
|
||||
tcp4_fix_checksum(tcp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
|
||||
@@ -279,6 +281,7 @@ bool prepare_tcp_segment6(
|
||||
uint8_t ttl,
|
||||
uint32_t flow_label,
|
||||
uint32_t fooling,
|
||||
uint32_t ts_increment,
|
||||
uint32_t badseq_increment,
|
||||
uint32_t badseq_ack_increment,
|
||||
const void *data, uint16_t len,
|
||||
@@ -343,7 +346,7 @@ bool prepare_tcp_segment6(
|
||||
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
|
||||
|
||||
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl, flow_label);
|
||||
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
|
||||
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,ts_increment,badseq_increment,badseq_ack_increment,len);
|
||||
|
||||
memcpy(payload,data,len);
|
||||
tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
|
||||
@@ -368,15 +371,16 @@ bool prepare_tcp_segment(
|
||||
uint16_t ip_id,
|
||||
uint32_t flow_label,
|
||||
uint32_t fooling,
|
||||
uint32_t ts_increment,
|
||||
uint32_t badseq_increment,
|
||||
uint32_t badseq_ack_increment,
|
||||
const void *data, uint16_t len,
|
||||
uint8_t *buf, size_t *buflen)
|
||||
{
|
||||
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
|
||||
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,DF,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
||||
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,DF,ttl,tos,ip_id,fooling,ts_increment,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
||||
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
|
||||
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
||||
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,ts_increment,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
||||
false;
|
||||
}
|
||||
|
||||
|
@@ -81,6 +81,7 @@ bool prepare_tcp_segment4(
|
||||
uint8_t tos,
|
||||
uint16_t ip_id,
|
||||
uint32_t fooling,
|
||||
uint32_t ts_increment,
|
||||
uint32_t badseq_increment,
|
||||
uint32_t badseq_ack_increment,
|
||||
const void *data, uint16_t len,
|
||||
@@ -97,6 +98,7 @@ bool prepare_tcp_segment6(
|
||||
uint8_t ttl,
|
||||
uint32_t flow_label,
|
||||
uint32_t fooling,
|
||||
uint32_t ts_increment,
|
||||
uint32_t badseq_increment,
|
||||
uint32_t badseq_ack_increment,
|
||||
const void *data, uint16_t len,
|
||||
@@ -116,6 +118,7 @@ bool prepare_tcp_segment(
|
||||
uint16_t ip_id,
|
||||
uint32_t flow_label,
|
||||
uint32_t fooling,
|
||||
uint32_t ts_increment,
|
||||
uint32_t badseq_increment,
|
||||
uint32_t badseq_ack_increment,
|
||||
const void *data, uint16_t len,
|
||||
|
114
nfq/desync.c
114
nfq/desync.c
@@ -223,7 +223,7 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
|
||||
|
||||
static bool dp_match(
|
||||
struct desync_profile *dp,
|
||||
uint8_t l3proto, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto, const char *ssid,
|
||||
uint8_t l3proto, const struct sockaddr *dest, const char *hostname, bool bNoSubdom, t_l7proto l7proto, const char *ssid,
|
||||
bool *bCheckDone, bool *bCheckResult, bool *bExcluded)
|
||||
{
|
||||
bool bHostlistsEmpty;
|
||||
@@ -267,7 +267,7 @@ static bool dp_match(
|
||||
{
|
||||
if (bCheckDone) *bCheckDone = true;
|
||||
bool b;
|
||||
b = HostlistCheck(dp, hostname, bExcluded, true);
|
||||
b = HostlistCheck(dp, hostname, bNoSubdom, bExcluded, true);
|
||||
if (bCheckResult) *bCheckResult = b;
|
||||
return b;
|
||||
}
|
||||
@@ -276,7 +276,7 @@ static bool dp_match(
|
||||
}
|
||||
static struct desync_profile *dp_find(
|
||||
struct desync_profile_list_head *head,
|
||||
uint8_t l3proto, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto, const char *ssid,
|
||||
uint8_t l3proto, const struct sockaddr *dest, const char *hostname, bool bNoSubdom, t_l7proto l7proto, const char *ssid,
|
||||
bool *bCheckDone, bool *bCheckResult, bool *bExcluded)
|
||||
{
|
||||
struct desync_profile_list *dpl;
|
||||
@@ -289,7 +289,7 @@ static struct desync_profile *dp_find(
|
||||
if (bCheckDone) *bCheckDone = false;
|
||||
LIST_FOREACH(dpl, head, next)
|
||||
{
|
||||
if (dp_match(&dpl->dp,l3proto,dest,hostname,l7proto,ssid,bCheckDone,bCheckResult,bExcluded))
|
||||
if (dp_match(&dpl->dp,l3proto,dest,hostname,bNoSubdom,l7proto,ssid,bCheckDone,bCheckResult,bExcluded))
|
||||
{
|
||||
DLOG("desync profile %d matches\n",dpl->dp.n);
|
||||
return &dpl->dp;
|
||||
@@ -418,7 +418,7 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname, const char *client_ip_port, t_l7proto l7proto)
|
||||
static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname, bool bNoSubdom, const char *client_ip_port, t_l7proto l7proto)
|
||||
{
|
||||
hostfail_pool *fail_counter;
|
||||
|
||||
@@ -442,7 +442,7 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
||||
|
||||
DLOG("auto hostlist (profile %d) : rechecking %s to avoid duplicates\n", dp->n, hostname);
|
||||
bool bExcluded=false;
|
||||
if (!HostlistCheck(dp, hostname, &bExcluded, false) && !bExcluded)
|
||||
if (!HostlistCheck(dp, hostname, bNoSubdom, &bExcluded, false) && !bExcluded)
|
||||
{
|
||||
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);
|
||||
@@ -477,7 +477,7 @@ static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto, const struct s
|
||||
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, proto, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto))
|
||||
{
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : client %s : proto %s : retrans threshold reached", ctrack->hostname, ctrack->dp->n, client_ip_port, l7proto_str(ctrack->l7proto));
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, client_ip_port, ctrack->l7proto);
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +783,7 @@ static void autottl_rediscover(t_ctrack *ctrack, const struct in_addr *a4, const
|
||||
}
|
||||
}
|
||||
|
||||
static bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname)
|
||||
static bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname, bool hostname_is_ip)
|
||||
{
|
||||
if (!params.cache_hostname) return true;
|
||||
|
||||
@@ -801,11 +801,12 @@ static bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr
|
||||
DLOG_ERR("ipcache_put_hostname: out of memory\n");
|
||||
return false;
|
||||
}
|
||||
DLOG("hostname cached: %s\n", hostname);
|
||||
ipc->hostname_is_ip = hostname_is_ip;
|
||||
DLOG("hostname cached (is_ip=%u): %s\n", hostname_is_ip, hostname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr *a6, char *hostname, size_t hostname_buf_len)
|
||||
static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr *a6, char *hostname, size_t hostname_buf_len, bool *hostname_is_ip)
|
||||
{
|
||||
if (!params.cache_hostname)
|
||||
{
|
||||
@@ -820,8 +821,9 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
|
||||
}
|
||||
if (ipc->hostname)
|
||||
{
|
||||
DLOG("got cached hostname: %s\n", ipc->hostname);
|
||||
DLOG("got cached hostname (is_ip=%u): %s\n", ipc->hostname_is_ip, ipc->hostname);
|
||||
snprintf(hostname,hostname_buf_len,"%s",ipc->hostname);
|
||||
if (hostname_is_ip) *hostname_is_ip = ipc->hostname_is_ip;
|
||||
}
|
||||
else
|
||||
*hostname = 0;
|
||||
@@ -981,7 +983,7 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
|
||||
flags_orig, sack, nmss,
|
||||
dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
ip_has_df(dis->ip),ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->dup_fooling_mode,dp->dup_badseq_increment,dp->dup_badseq_ack_increment,
|
||||
dp->dup_fooling_mode,dp->dup_ts_increment,dp->dup_badseq_increment,dp->dup_badseq_ack_increment,
|
||||
dis->data_payload, dis->len_payload, pkt, &len))
|
||||
{
|
||||
DLOG_ERR("dup: packet reconstruct failed\n");
|
||||
@@ -1140,11 +1142,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
{
|
||||
if (!ctrack_replay->hostname && !bReverse)
|
||||
{
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host)) && *host)
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host), &ctrack_replay->hostname_is_ip) && *host)
|
||||
if (!(ctrack_replay->hostname = strdup(host)))
|
||||
DLOG_ERR("strdup(host): out of memory\n");
|
||||
}
|
||||
dp = ctrack_replay->dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
|
||||
dp = ctrack_replay->dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->hostname_is_ip, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
}
|
||||
if (!dp)
|
||||
@@ -1176,17 +1178,19 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
else if (!ctrack || !ctrack->dp_search_complete)
|
||||
{
|
||||
const char *hostname = NULL;
|
||||
bool hostname_is_ip = false;
|
||||
if (ctrack)
|
||||
{
|
||||
hostname = ctrack->hostname;
|
||||
hostname_is_ip = ctrack->hostname_is_ip;
|
||||
if (!hostname && !bReverse)
|
||||
{
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host)) && *host)
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host), &hostname_is_ip) && *host)
|
||||
if (!(hostname = ctrack_replay->hostname = strdup(host)))
|
||||
DLOG_ERR("strdup(host): out of memory\n");
|
||||
}
|
||||
}
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, ssid, NULL, NULL, NULL);
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, hostname, hostname_is_ip, ctrack ? ctrack->l7proto : UNKNOWN, ssid, NULL, NULL, NULL);
|
||||
if (ctrack)
|
||||
{
|
||||
ctrack->dp = dp;
|
||||
@@ -1268,7 +1272,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
}
|
||||
}
|
||||
if (bFail)
|
||||
auto_hostlist_failed(dp, ctrack->hostname, client_ip_port, ctrack->l7proto);
|
||||
auto_hostlist_failed(dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
else
|
||||
if (dis->len_payload)
|
||||
auto_hostlist_reset_fail_counter(dp, ctrack->hostname, client_ip_port, ctrack->l7proto);
|
||||
@@ -1326,7 +1330,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_ACK, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, SCALE_NONE, timestamps,
|
||||
DF,ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
|
||||
FOOL_NONE,0,0,NULL, 0, pkt1, &pkt1_len))
|
||||
FOOL_NONE,0,0,0,NULL, 0, pkt1, &pkt1_len))
|
||||
{
|
||||
DLOG_ERR("cannot prepare split SYNACK ACK part\n");
|
||||
goto send_orig;
|
||||
@@ -1371,7 +1375,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN|TH_ACK, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
NULL, 0, pkt1, &pkt1_len))
|
||||
{
|
||||
goto send_orig;
|
||||
@@ -1395,7 +1399,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, bSack, nmss, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
|
||||
0,0,0, dp->fake_syndata,dp->fake_syndata_size, pkt1,&pkt1_len))
|
||||
0,0,0,0, dp->fake_syndata,dp->fake_syndata_size, pkt1,&pkt1_len))
|
||||
{
|
||||
goto send_orig;
|
||||
}
|
||||
@@ -1426,7 +1430,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
int multisplit_count;
|
||||
int i;
|
||||
uint16_t ip_id;
|
||||
bool bHaveHost=false;
|
||||
bool bHaveHost=false, bHostIsIp=false;
|
||||
t_l7proto l7proto = UNKNOWN;
|
||||
|
||||
if (replay)
|
||||
@@ -1547,7 +1551,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
if (dseq>=0x1000000 && !(dseq & 0x80000000)) ctrack->req_seq_abandoned=true;
|
||||
}
|
||||
|
||||
if (bHaveHost) DLOG("hostname: %s\n",host);
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp=strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n",host);
|
||||
}
|
||||
|
||||
bool bDiscoveredL7;
|
||||
if (ctrack_replay)
|
||||
@@ -1567,6 +1575,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
{
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname=strdup(host);
|
||||
ctrack_replay->hostname_is_ip=bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
@@ -1574,7 +1583,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
goto send_orig;
|
||||
}
|
||||
ctrack_replay->hostname_discovered=true;
|
||||
if (!ipcache_put_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host))
|
||||
if (!ipcache_put_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, bHostIsIp))
|
||||
{
|
||||
reasm_orig_cancel(ctrack);
|
||||
goto send_orig;
|
||||
@@ -1590,6 +1599,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
ctrack_replay ? ctrack_replay->l7proto : l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
if (ctrack_replay)
|
||||
@@ -1638,7 +1648,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
{
|
||||
if (!bCheckDone)
|
||||
bCheckResult = HostlistCheck(dp, host, &bCheckExcluded, false);
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
if (bCheckResult)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
else
|
||||
@@ -1862,7 +1872,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
fake_data, fake_item->size, pkt1, &pkt1_len))
|
||||
{
|
||||
reasm_orig_cancel(ctrack);
|
||||
@@ -1886,7 +1896,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (dp->desync_mode==DESYNC_RSTACK ? TH_ACK:0), false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
NULL, 0, pkt1, &pkt1_len))
|
||||
{
|
||||
reasm_orig_cancel(ctrack);
|
||||
@@ -1914,7 +1924,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_orig,0,0,IP6_FLOW(dis->ip6),
|
||||
fooling_orig,0,0,
|
||||
fooling_orig,0,0,0,
|
||||
dis->data_payload, dis->len_payload, pkt1, &pkt1_len))
|
||||
{
|
||||
goto send_orig;
|
||||
@@ -1983,7 +1993,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack,
|
||||
dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
fooling_orig,0,0,
|
||||
fooling_orig,0,0,0,
|
||||
seg, seg_len, pkt1, &pkt1_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
@@ -2053,7 +2063,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack,
|
||||
dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
fooling_orig,0,0,
|
||||
fooling_orig,0,0,0,
|
||||
seg, seg_len, pkt1, &pkt1_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
||||
@@ -2112,7 +2122,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
fakeseg2_len = sizeof(fakeseg2);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
pat+split_pos, dis->len_payload-split_pos, fakeseg2, &fakeseg2_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
||||
@@ -2124,7 +2134,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq , split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
fooling_orig,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
seg, seg_len, pkt1, &pkt1_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
||||
@@ -2144,7 +2154,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
seg_len = sizeof(fakeseg);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
pat, split_pos, fakeseg, &seg_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
||||
@@ -2156,7 +2166,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
fooling_orig,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dis->data_payload, split_pos, pkt1, &pkt1_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
||||
@@ -2192,7 +2202,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
fakeseg_len = sizeof(fakeseg);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
pat, split_pos, fakeseg, &fakeseg_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
@@ -2228,7 +2238,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,-seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
fooling_orig,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
seg, seg_len, pkt1, &pkt1_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
@@ -2259,7 +2269,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
fakeseg_len = sizeof(fakeseg);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
pat+split_pos, dis->len_payload-split_pos, fakeseg, &fakeseg_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
@@ -2271,7 +2281,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
fooling_orig,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dis->data_payload+split_pos, dis->len_payload-split_pos, pkt1, &pkt1_len))
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
@@ -2409,11 +2419,11 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
{
|
||||
if (!ctrack_replay->hostname && !bReverse)
|
||||
{
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host)) && *host)
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host), &ctrack_replay->hostname_is_ip) && *host)
|
||||
if (!(ctrack_replay->hostname = strdup(host)))
|
||||
DLOG_ERR("strdup(host): out of memory\n");
|
||||
}
|
||||
dp = ctrack_replay->dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
|
||||
dp = ctrack_replay->dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->hostname_is_ip, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
}
|
||||
if (!dp)
|
||||
@@ -2421,9 +2431,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
DLOG("matching desync profile not found\n");
|
||||
return verdict;
|
||||
}
|
||||
|
||||
// no need to desync middle packets in reasm session
|
||||
if (reasm_offset) goto send_orig;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2448,17 +2455,19 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
else if (!ctrack || !ctrack->dp_search_complete)
|
||||
{
|
||||
const char *hostname = NULL;
|
||||
bool hostname_is_ip = false;
|
||||
if (ctrack)
|
||||
{
|
||||
hostname = ctrack->hostname;
|
||||
hostname_is_ip = ctrack->hostname_is_ip;
|
||||
if (!hostname && !bReverse)
|
||||
{
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host)) && *host)
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host), &hostname_is_ip) && *host)
|
||||
if (!(hostname = ctrack_replay->hostname = strdup(host)))
|
||||
DLOG_ERR("strdup(host): out of memory\n");
|
||||
}
|
||||
}
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, ssid, NULL, NULL, NULL);
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, hostname, hostname_is_ip, ctrack ? ctrack->l7proto : UNKNOWN, ssid, NULL, NULL, NULL);
|
||||
if (ctrack)
|
||||
{
|
||||
ctrack->dp = dp;
|
||||
@@ -2506,7 +2515,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
if (dis->len_payload)
|
||||
{
|
||||
struct blob_collection_head *fake;
|
||||
bool bHaveHost=false;
|
||||
bool bHaveHost=false, bHostIsIp=false;
|
||||
uint16_t ip_id;
|
||||
|
||||
if (IsQUICInitial(dis->data_payload,dis->len_payload))
|
||||
@@ -2693,7 +2702,11 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
}
|
||||
}
|
||||
|
||||
if (bHaveHost) DLOG("hostname: %s\n",host);
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp=strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n",host);
|
||||
}
|
||||
|
||||
bool bDiscoveredL7;
|
||||
if (ctrack_replay)
|
||||
@@ -2714,12 +2727,13 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
ctrack_replay->hostname_discovered=true;
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname=strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto send_orig;
|
||||
}
|
||||
if (!ipcache_put_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host))
|
||||
if (!ipcache_put_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, bHostIsIp))
|
||||
goto send_orig;
|
||||
}
|
||||
}
|
||||
@@ -2731,6 +2745,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
ctrack_replay ? ctrack_replay->l7proto : l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
if (ctrack_replay)
|
||||
@@ -2775,7 +2790,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
{
|
||||
if (!bCheckDone)
|
||||
bCheckResult = HostlistCheck(dp, host, &bCheckExcluded, false);
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
if (bCheckResult)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
else
|
||||
@@ -2839,6 +2854,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
break;
|
||||
}
|
||||
case DESYNC_FAKE:
|
||||
if (!reasm_offset)
|
||||
{
|
||||
struct blob_item *fake_item;
|
||||
int n=0;
|
||||
@@ -2862,8 +2878,8 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
goto send_orig;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
}
|
||||
bFake = true;
|
||||
}
|
||||
bFake = true;
|
||||
break;
|
||||
case DESYNC_HOPBYHOP:
|
||||
case DESYNC_DESTOPT:
|
||||
|
@@ -124,6 +124,61 @@ void expand_bits(void *target, const void *source, unsigned int source_bitlen, u
|
||||
if ((bitlen &= 7)) ((uint8_t*)target)[bytelen] = ((uint8_t*)source)[bytelen] & (~((1 << (8-bitlen)) - 1));
|
||||
}
|
||||
|
||||
// " [fd00::1]" => "fd00::1"
|
||||
// "[fd00::1]:8000" => "fd00::1"
|
||||
// "127.0.0.1" => "127.0.0.1"
|
||||
// " 127.0.0.1:8000" => "127.0.0.1"
|
||||
// " vk.com:8000" => "vk.com"
|
||||
// return value: true - host is ip addr
|
||||
bool strip_host_to_ip(char *host)
|
||||
{
|
||||
size_t l;
|
||||
char *h,*p;
|
||||
uint8_t addr[16];
|
||||
|
||||
for (h = host ; *h==' ' || *h=='\t' ; h++);
|
||||
l = strlen(h);
|
||||
if (l>=2)
|
||||
{
|
||||
if (*h=='[')
|
||||
{
|
||||
// ipv6 ?
|
||||
for (p=++h ; *p && *p!=']' ; p++);
|
||||
if (*p==']')
|
||||
{
|
||||
l = p-h;
|
||||
memmove(host,h,l);
|
||||
host[l]=0;
|
||||
return inet_pton(AF_INET6, host, addr)>0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inet_pton(AF_INET6, h, addr)>0)
|
||||
{
|
||||
// ipv6 ?
|
||||
if (host!=h)
|
||||
{
|
||||
l = strlen(h);
|
||||
memmove(host,h,l);
|
||||
host[l]=0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ipv4 ?
|
||||
for (p=h ; *p && *p!=':' ; p++);
|
||||
l = p-h;
|
||||
if (host!=h) memmove(host,h,l);
|
||||
host[l]=0;
|
||||
return inet_pton(AF_INET, host, addr)>0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ntop46(const struct sockaddr *sa, char *str, size_t len)
|
||||
{
|
||||
if (!len) return;
|
||||
|
@@ -33,6 +33,8 @@ bool append_to_list_file(const char *filename, const char *s);
|
||||
|
||||
void expand_bits(void *target, const void *source, unsigned int source_bitlen, unsigned int target_bytelen);
|
||||
|
||||
bool strip_host_to_ip(char *host);
|
||||
|
||||
void print_sockaddr(const struct sockaddr *sa);
|
||||
void ntop46(const struct sockaddr *sa, char *str, size_t len);
|
||||
void ntop46_port(const struct sockaddr *sa, char *str, size_t len);
|
||||
|
@@ -170,7 +170,7 @@ bool LoadAllHostLists()
|
||||
|
||||
|
||||
|
||||
static bool SearchHostList(hostlist_pool *hostlist, const char *host)
|
||||
static bool SearchHostList(hostlist_pool *hostlist, const char *host, bool no_match_subdomains)
|
||||
{
|
||||
if (hostlist)
|
||||
{
|
||||
@@ -195,6 +195,7 @@ static bool SearchHostList(hostlist_pool *hostlist, const char *host)
|
||||
}
|
||||
else
|
||||
DLOG("negative\n");
|
||||
if (no_match_subdomains) break;
|
||||
p = strchr(p, '.');
|
||||
if (p) p++;
|
||||
bHostFull = false;
|
||||
@@ -220,7 +221,7 @@ bool HostlistsReloadCheckForProfile(const struct desync_profile *dp)
|
||||
return HostlistsReloadCheck(&dp->hl_collection) && HostlistsReloadCheck(&dp->hl_collection_exclude);
|
||||
}
|
||||
// return : true = apply fooling, false = do not apply
|
||||
static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, const struct hostlist_collection_head *hostlists_exclude, const char *host, bool *excluded, bool bSkipReloadCheck)
|
||||
static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, const struct hostlist_collection_head *hostlists_exclude, const char *host, bool no_match_subdomains, bool *excluded, bool bSkipReloadCheck)
|
||||
{
|
||||
struct hostlist_item *item;
|
||||
|
||||
@@ -233,7 +234,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
LIST_FOREACH(item, hostlists_exclude, next)
|
||||
{
|
||||
DLOG("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchHostList(item->hfile->hostlist, host))
|
||||
if (SearchHostList(item->hfile->hostlist, host, no_match_subdomains))
|
||||
{
|
||||
if (excluded) *excluded = true;
|
||||
return false;
|
||||
@@ -245,7 +246,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
LIST_FOREACH(item, hostlists, next)
|
||||
{
|
||||
DLOG("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchHostList(item->hfile->hostlist, host))
|
||||
if (SearchHostList(item->hfile->hostlist, host, no_match_subdomains))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -255,10 +256,10 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
|
||||
|
||||
// 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 no_match_subdomains, bool *excluded, bool bSkipReloadCheck)
|
||||
{
|
||||
DLOG("* hostlist check for profile %d\n",dp->n);
|
||||
return HostlistCheck_(&dp->hl_collection, &dp->hl_collection_exclude, host, excluded, bSkipReloadCheck);
|
||||
return HostlistCheck_(&dp->hl_collection, &dp->hl_collection_exclude, host, no_match_subdomains, excluded, bSkipReloadCheck);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -9,7 +9,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename);
|
||||
bool LoadAllHostLists();
|
||||
bool NonEmptyHostlist(hostlist_pool **hostlist);
|
||||
// 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 no_match_subdomains, bool *excluded, bool bSkipReloadCheck);
|
||||
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||
bool HostlistsReloadCheckForProfile(const struct desync_profile *dp);
|
||||
void HostlistsDebug();
|
||||
|
42
nfq/nfqws.c
42
nfq/nfqws.c
@@ -735,7 +735,7 @@ static bool parse_cutoff(const char *opt, unsigned int *value, char *mode)
|
||||
*mode = (*opt=='n' || *opt=='d' || *opt=='s') ? *opt++ : 'n';
|
||||
return sscanf(opt, "%u", value)>0;
|
||||
}
|
||||
static bool parse_badseq_increment(const char *opt, uint32_t *value)
|
||||
static bool parse_net32_signed(const char *opt, uint32_t *value)
|
||||
{
|
||||
if (((opt[0]=='0' && opt[1]=='x') || (opt[0]=='-' && opt[1]=='0' && opt[2]=='x')) && sscanf(opt+2+(opt[0]=='-'), "%X", (int32_t*)value)>0)
|
||||
{
|
||||
@@ -1449,7 +1449,7 @@ static bool wf_make_filter(
|
||||
const char *pf_tcp_src, const char *pf_tcp_dst,
|
||||
const char *pf_udp_src, const char *pf_udp_dst)
|
||||
{
|
||||
char pf_dst_buf[512],iface[64];
|
||||
char pf_dst_buf[8192],iface[64];
|
||||
const char *pf_dst;
|
||||
const char *f_tcpin = *pf_tcp_src ? dp_list_have_autohostlist(¶ms.desync_profiles) ? "(" DIVERT_TCP_INBOUNDS " or (" DIVERT_HTTP_REDIRECT "))" : DIVERT_TCP_INBOUNDS : "";
|
||||
const char *f_tcp_not_empty = (*pf_tcp_src && !dp_list_need_all_out(¶ms.desync_profiles)) ? DIVERT_TCP_NOT_EMPTY " and " : "";
|
||||
@@ -1579,7 +1579,8 @@ static void exithelp(void)
|
||||
" --dup-ttl6=<int>\t\t\t\t; set ipv6 hop limit for dups. by default ttl value is used\n"
|
||||
" --dup-autottl=[<delta>[:<min>[-<max>]]|-]\t; auto ttl mode for both ipv4 and ipv6. default: %d:%u-%u\n"
|
||||
" --dup-autottl6=[<delta>[:<min>[-<max>]]|-]\t; overrides --dup-autottl for ipv6 only\n"
|
||||
" --dup-fooling=<mode>[,<mode>]\t\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2\n"
|
||||
" --dup-fooling=<mode>[,<mode>]\t\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2\n"
|
||||
" --dup-ts-increment=<int|0xHEX>\t\t\t; ts fooling TSval signed increment for dup. default %d\n"
|
||||
" --dup-badseq-increment=<int|0xHEX>\t\t; badseq fooling seq signed increment for dup. default %d\n"
|
||||
" --dup-badack-increment=<int|0xHEX>\t\t; badseq fooling ackseq signed increment for dup. default %d\n"
|
||||
" --dup-start=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
|
||||
@@ -1601,7 +1602,7 @@ static void exithelp(void)
|
||||
" --dpi-desync-ttl6=<int>\t\t\t; set ipv6 hop limit for fake packet. by default --dpi-desync-ttl value is used.\n"
|
||||
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: %d:%u-%u\n"
|
||||
" --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dpi-desync-autottl for ipv6 only\n"
|
||||
" --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2\n"
|
||||
" --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2\n"
|
||||
" --dpi-desync-repeats=<N>\t\t\t; send every desync packet N times\n"
|
||||
" --dpi-desync-skip-nosni=0|1\t\t\t; 1(default)=do not act on ClientHello without SNI\n"
|
||||
" --dpi-desync-split-pos=N|-N|marker+N|marker-N\t; comma separated list of split positions\n"
|
||||
@@ -1613,6 +1614,7 @@ static void exithelp(void)
|
||||
" --dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder\n"
|
||||
" --dpi-desync-ipfrag-pos-tcp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
||||
" --dpi-desync-ipfrag-pos-udp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
||||
" --dpi-desync-ts-increment=<int|0xHEX>\t\t; ts fooling TSval signed increment. default %d\n"
|
||||
" --dpi-desync-badseq-increment=<int|0xHEX>\t; badseq fooling seq signed increment. default %d\n"
|
||||
" --dpi-desync-badack-increment=<int|0xHEX>\t; badseq fooling ackseq signed increment. default %d\n"
|
||||
" --dpi-desync-any-protocol=0|1\t\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n"
|
||||
@@ -1636,14 +1638,14 @@ static void exithelp(void)
|
||||
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT, HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
|
||||
AUTOTTL_DEFAULT_ORIG_DELTA,AUTOTTL_DEFAULT_ORIG_MIN,AUTOTTL_DEFAULT_ORIG_MAX,
|
||||
AUTOTTL_DEFAULT_DUP_DELTA,AUTOTTL_DEFAULT_DUP_MIN,AUTOTTL_DEFAULT_DUP_MAX,
|
||||
BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT,
|
||||
TS_INCREMENT_DEFAULT, BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT,
|
||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||
DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT,
|
||||
#endif
|
||||
AUTOTTL_DEFAULT_DESYNC_DELTA,AUTOTTL_DEFAULT_DESYNC_MIN,AUTOTTL_DEFAULT_DESYNC_MAX,
|
||||
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_UDP_DEFAULT,
|
||||
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_TCP_DEFAULT,
|
||||
BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT,
|
||||
TS_INCREMENT_DEFAULT, BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT,
|
||||
UDPLEN_INCREMENT_DEFAULT
|
||||
);
|
||||
exit(1);
|
||||
@@ -1762,6 +1764,7 @@ enum opt_indices {
|
||||
IDX_DUP_AUTOTTL,
|
||||
IDX_DUP_AUTOTTL6,
|
||||
IDX_DUP_FOOLING,
|
||||
IDX_DUP_TS_INCREMENT,
|
||||
IDX_DUP_BADSEQ_INCREMENT,
|
||||
IDX_DUP_BADACK_INCREMENT,
|
||||
IDX_DUP_REPLACE,
|
||||
@@ -1788,6 +1791,7 @@ enum opt_indices {
|
||||
IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN,
|
||||
IDX_DPI_DESYNC_IPFRAG_POS_TCP,
|
||||
IDX_DPI_DESYNC_IPFRAG_POS_UDP,
|
||||
IDX_DPI_DESYNC_TS_INCREMENT,
|
||||
IDX_DPI_DESYNC_BADSEQ_INCREMENT,
|
||||
IDX_DPI_DESYNC_BADACK_INCREMENT,
|
||||
IDX_DPI_DESYNC_ANY_PROTOCOL,
|
||||
@@ -1886,6 +1890,7 @@ static const struct option long_options[] = {
|
||||
[IDX_DUP_AUTOTTL] = {"dup-autottl", optional_argument, 0, 0},
|
||||
[IDX_DUP_AUTOTTL6] = {"dup-autottl6", optional_argument, 0, 0},
|
||||
[IDX_DUP_FOOLING] = {"dup-fooling", required_argument, 0, 0},
|
||||
[IDX_DUP_TS_INCREMENT] = {"dup-ts-increment", required_argument, 0, 0},
|
||||
[IDX_DUP_BADSEQ_INCREMENT] = {"dup-badseq-increment", required_argument, 0, 0},
|
||||
[IDX_DUP_BADACK_INCREMENT] = {"dup-badack-increment", required_argument, 0, 0},
|
||||
[IDX_DUP_REPLACE] = {"dup-replace", optional_argument, 0, 0},
|
||||
@@ -1912,6 +1917,7 @@ static const struct option long_options[] = {
|
||||
[IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN] = {"dpi-desync-fakedsplit-pattern", required_argument, 0, 0},
|
||||
[IDX_DPI_DESYNC_IPFRAG_POS_TCP] = {"dpi-desync-ipfrag-pos-tcp", required_argument, 0, 0},
|
||||
[IDX_DPI_DESYNC_IPFRAG_POS_UDP] = {"dpi-desync-ipfrag-pos-udp", required_argument, 0, 0},
|
||||
[IDX_DPI_DESYNC_TS_INCREMENT] = {"dpi-desync-ts-increment", required_argument, 0, 0},
|
||||
[IDX_DPI_DESYNC_BADSEQ_INCREMENT] = {"dpi-desync-badseq-increment", required_argument, 0, 0},
|
||||
[IDX_DPI_DESYNC_BADACK_INCREMENT] = {"dpi-desync-badack-increment", required_argument, 0, 0},
|
||||
[IDX_DPI_DESYNC_ANY_PROTOCOL] = {"dpi-desync-any-protocol", optional_argument, 0, 0},
|
||||
@@ -1987,7 +1993,7 @@ int main(int argc, char **argv)
|
||||
struct hostlist_file *anon_hl = NULL, *anon_hl_exclude = NULL;
|
||||
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
|
||||
#ifdef __CYGWIN__
|
||||
char windivert_filter[8192], wf_pf_tcp_src[256], wf_pf_tcp_dst[256], wf_pf_udp_src[256], wf_pf_udp_dst[256], wf_save_file[256];
|
||||
char windivert_filter[16384], wf_pf_tcp_src[4096], wf_pf_tcp_dst[4096], wf_pf_udp_src[4096], wf_pf_udp_dst[4096], wf_save_file[256];
|
||||
bool wf_ipv4=true, wf_ipv6=true;
|
||||
unsigned int IfIdx=0, SubIfIdx=0;
|
||||
unsigned int hash_wf_tcp=0,hash_wf_udp=0,hash_wf_raw=0,hash_ssid_filter=0,hash_nlm_filter=0;
|
||||
@@ -2360,15 +2366,22 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case IDX_DUP_TS_INCREMENT:
|
||||
if (!parse_net32_signed(optarg,&dp->dup_ts_increment))
|
||||
{
|
||||
DLOG_ERR("dup-ts-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case IDX_DUP_BADSEQ_INCREMENT:
|
||||
if (!parse_badseq_increment(optarg,&dp->dup_badseq_increment))
|
||||
if (!parse_net32_signed(optarg,&dp->dup_badseq_increment))
|
||||
{
|
||||
DLOG_ERR("dup-badseq-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case IDX_DUP_BADACK_INCREMENT:
|
||||
if (!parse_badseq_increment(optarg,&dp->dup_badseq_ack_increment))
|
||||
if (!parse_net32_signed(optarg,&dp->dup_badseq_ack_increment))
|
||||
{
|
||||
DLOG_ERR("dup-badack-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
@@ -2559,15 +2572,22 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case IDX_DPI_DESYNC_TS_INCREMENT:
|
||||
if (!parse_net32_signed(optarg,&dp->desync_ts_increment))
|
||||
{
|
||||
DLOG_ERR("dpi-desync-ts-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case IDX_DPI_DESYNC_BADSEQ_INCREMENT:
|
||||
if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment))
|
||||
if (!parse_net32_signed(optarg,&dp->desync_badseq_increment))
|
||||
{
|
||||
DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case IDX_DPI_DESYNC_BADACK_INCREMENT:
|
||||
if (!parse_badseq_increment(optarg,&dp->desync_badseq_ack_increment))
|
||||
if (!parse_net32_signed(optarg,&dp->desync_badseq_ack_increment))
|
||||
{
|
||||
DLOG_ERR("dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
|
@@ -227,6 +227,7 @@ void dp_init(struct desync_profile *dp)
|
||||
dp->fake_syndata_size = 16;
|
||||
dp->wscale=-1; // default - dont change scale factor (client)
|
||||
dp->desync_ttl6 = dp->dup_ttl6 = dp->orig_mod_ttl6 = 0xFF; // unused
|
||||
dp->desync_ts_increment = dp->dup_ts_increment = TS_INCREMENT_DEFAULT;
|
||||
dp->desync_badseq_increment = dp->dup_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
|
||||
dp->desync_badseq_ack_increment = dp->dup_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
|
||||
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = dp->dup_start_mode = dp->dup_cutoff_mode = dp->orig_mod_start_mode = dp->orig_mod_cutoff_mode = 'n'; // packet number by default
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#define BADSEQ_INCREMENT_DEFAULT -10000
|
||||
#define BADSEQ_ACK_INCREMENT_DEFAULT -66000
|
||||
|
||||
#define TS_INCREMENT_DEFAULT -600000
|
||||
|
||||
#define IPFRAG_UDP_DEFAULT 8
|
||||
#define IPFRAG_TCP_DEFAULT 32
|
||||
|
||||
@@ -108,7 +110,7 @@ struct desync_profile
|
||||
unsigned int dup_repeats;
|
||||
uint8_t dup_ttl, dup_ttl6;
|
||||
uint32_t dup_fooling_mode;
|
||||
uint32_t dup_badseq_increment, dup_badseq_ack_increment;
|
||||
uint32_t dup_ts_increment, dup_badseq_increment, dup_badseq_ack_increment;
|
||||
autottl dup_autottl, dup_autottl6;
|
||||
|
||||
char orig_mod_start_mode, orig_mod_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
||||
@@ -121,7 +123,7 @@ struct desync_profile
|
||||
uint8_t desync_ttl, desync_ttl6;
|
||||
autottl desync_autottl, desync_autottl6;
|
||||
uint32_t desync_fooling_mode;
|
||||
uint32_t desync_badseq_increment, desync_badseq_ack_increment;
|
||||
uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment;
|
||||
|
||||
struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun;
|
||||
uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],fsplit_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
|
||||
|
@@ -629,6 +629,7 @@ static void ipcache_item_init(ip_cache_item *item)
|
||||
{
|
||||
ipcache_item_touch(item);
|
||||
item->hostname = NULL;
|
||||
item->hostname_is_ip = false;
|
||||
item->hops = 0;
|
||||
}
|
||||
static void ipcache_item_destroy(ip_cache_item *item)
|
||||
@@ -690,7 +691,7 @@ static void ipcache4Print(ip_cache4 *ipcache)
|
||||
{
|
||||
*s_ip=0;
|
||||
inet_ntop(AF_INET, &ipc->key.addr, s_ip, sizeof(s_ip));
|
||||
printf("%s iface=%s : hops %u hostname=%s now=last+%llu\n", s_ip, ipc->key.iface, ipc->data.hops, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
|
||||
printf("%s iface=%s : hops %u hostname=%s hostname_is_ip=%u now=last+%llu\n", s_ip, ipc->key.iface, ipc->data.hops, ipc->data.hostname ? ipc->data.hostname : "", ipc->data.hostname_is_ip, (unsigned long long)(now-ipc->data.last));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -748,7 +749,7 @@ static void ipcache6Print(ip_cache6 *ipcache)
|
||||
{
|
||||
*s_ip=0;
|
||||
inet_ntop(AF_INET6, &ipc->key.addr, s_ip, sizeof(s_ip));
|
||||
printf("%s iface=%s : hops %u hostname=%s now=last+%llu\n", s_ip, ipc->key.iface, ipc->data.hops, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
|
||||
printf("%s iface=%s : hops %u hostname=%s hostname_is_ip=%u now=last+%llu\n", s_ip, ipc->key.iface, ipc->data.hops, ipc->data.hostname ? ipc->data.hostname : "", ipc->data.hostname_is_ip, (unsigned long long)(now-ipc->data.last));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -182,6 +182,7 @@ typedef struct ip_cache_item
|
||||
{
|
||||
time_t last;
|
||||
char *hostname;
|
||||
bool hostname_is_ip;
|
||||
uint8_t hops;
|
||||
} ip_cache_item;
|
||||
typedef struct ip_cache4
|
||||
|
@@ -1,5 +1,6 @@
|
||||
CC ?= cc
|
||||
CFLAGS += -std=gnu99 -s -Os -flto=auto
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto
|
||||
LIBS = -lz -lpthread
|
||||
SRC_FILES = *.c
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
CC ?= gcc
|
||||
CFLAGS += -std=gnu99 -Os -flto=auto
|
||||
CC ?= cc
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
|
||||
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
LDFLAGS_ANDROID = -llog
|
||||
|
@@ -123,6 +123,61 @@ void expand_bits(void *target, const void *source, unsigned int source_bitlen, u
|
||||
if ((bitlen &= 7)) ((uint8_t*)target)[bytelen] = ((uint8_t*)source)[bytelen] & (~((1 << (8-bitlen)) - 1));
|
||||
}
|
||||
|
||||
// " [fd00::1]" => "fd00::1"
|
||||
// "[fd00::1]:8000" => "fd00::1"
|
||||
// "127.0.0.1" => "127.0.0.1"
|
||||
// " 127.0.0.1:8000" => "127.0.0.1"
|
||||
// " vk.com:8000" => "vk.com"
|
||||
// return value: true - host is ip addr
|
||||
bool strip_host_to_ip(char *host)
|
||||
{
|
||||
size_t l;
|
||||
char *h,*p;
|
||||
uint8_t addr[16];
|
||||
|
||||
for (h = host ; *h==' ' || *h=='\t' ; h++);
|
||||
l = strlen(h);
|
||||
if (l>=2)
|
||||
{
|
||||
if (*h=='[')
|
||||
{
|
||||
// ipv6 ?
|
||||
for (p=++h ; *p && *p!=']' ; p++);
|
||||
if (*p==']')
|
||||
{
|
||||
l = p-h;
|
||||
memmove(host,h,l);
|
||||
host[l]=0;
|
||||
return inet_pton(AF_INET6, host, addr)>0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inet_pton(AF_INET6, h, addr)>0)
|
||||
{
|
||||
// ipv6 ?
|
||||
if (host!=h)
|
||||
{
|
||||
l = strlen(h);
|
||||
memmove(host,h,l);
|
||||
host[l]=0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ipv4 ?
|
||||
for (p=h ; *p && *p!=':' ; p++);
|
||||
l = p-h;
|
||||
if (host!=h) memmove(host,h,l);
|
||||
host[l]=0;
|
||||
return inet_pton(AF_INET, host, addr)>0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ntop46(const struct sockaddr *sa, char *str, size_t len)
|
||||
{
|
||||
if (!len) return;
|
||||
|
@@ -31,6 +31,8 @@ bool append_to_list_file(const char *filename, const char *s);
|
||||
|
||||
void expand_bits(void *target, const void *source, unsigned int source_bitlen, unsigned int target_bytelen);
|
||||
|
||||
bool strip_host_to_ip(char *host);
|
||||
|
||||
void ntop46(const struct sockaddr *sa, char *str, size_t len);
|
||||
void ntop46_port(const struct sockaddr *sa, char *str, size_t len);
|
||||
void print_sockaddr(const struct sockaddr *sa);
|
||||
|
@@ -170,7 +170,7 @@ bool LoadAllHostLists()
|
||||
|
||||
|
||||
|
||||
static bool SearchHostList(hostlist_pool *hostlist, const char *host)
|
||||
static bool SearchHostList(hostlist_pool *hostlist, const char *host, bool no_match_subdomains)
|
||||
{
|
||||
if (hostlist)
|
||||
{
|
||||
@@ -195,6 +195,7 @@ static bool SearchHostList(hostlist_pool *hostlist, const char *host)
|
||||
}
|
||||
else
|
||||
VPRINT("negative\n");
|
||||
if (no_match_subdomains) break;
|
||||
p = strchr(p, '.');
|
||||
if (p) p++;
|
||||
bHostFull = false;
|
||||
@@ -220,7 +221,7 @@ bool HostlistsReloadCheckForProfile(const struct desync_profile *dp)
|
||||
return HostlistsReloadCheck(&dp->hl_collection) && HostlistsReloadCheck(&dp->hl_collection_exclude);
|
||||
}
|
||||
// return : true = apply fooling, false = do not apply
|
||||
static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, const struct hostlist_collection_head *hostlists_exclude, const char *host, bool *excluded, bool bSkipReloadCheck)
|
||||
static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, const struct hostlist_collection_head *hostlists_exclude, const char *host, bool no_match_subdomains, bool *excluded, bool bSkipReloadCheck)
|
||||
{
|
||||
struct hostlist_item *item;
|
||||
|
||||
@@ -233,7 +234,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
LIST_FOREACH(item, hostlists_exclude, next)
|
||||
{
|
||||
VPRINT("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchHostList(item->hfile->hostlist, host))
|
||||
if (SearchHostList(item->hfile->hostlist, host, no_match_subdomains))
|
||||
{
|
||||
if (excluded) *excluded = true;
|
||||
return false;
|
||||
@@ -245,7 +246,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
LIST_FOREACH(item, hostlists, next)
|
||||
{
|
||||
VPRINT("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchHostList(item->hfile->hostlist, host))
|
||||
if (SearchHostList(item->hfile->hostlist, host, no_match_subdomains))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -255,10 +256,10 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
|
||||
|
||||
// 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 no_match_subdomains, bool *excluded, bool bSkipReloadCheck)
|
||||
{
|
||||
VPRINT("* hostlist check for profile %d\n",dp->n);
|
||||
return HostlistCheck_(&dp->hl_collection, &dp->hl_collection_exclude, host, excluded, bSkipReloadCheck);
|
||||
return HostlistCheck_(&dp->hl_collection, &dp->hl_collection_exclude, host, no_match_subdomains, excluded, bSkipReloadCheck);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -9,7 +9,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename);
|
||||
bool LoadAllHostLists();
|
||||
bool NonEmptyHostlist(hostlist_pool **hostlist);
|
||||
// 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 no_match_subdomains, bool *excluded, bool bSkipReloadCheck);
|
||||
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||
bool HostlistsReloadCheckForProfile(const struct desync_profile *dp);
|
||||
void HostlistsDebug();
|
||||
|
@@ -616,6 +616,7 @@ static void ipcache_item_init(ip_cache_item *item)
|
||||
{
|
||||
ipcache_item_touch(item);
|
||||
item->hostname = NULL;
|
||||
item->hostname_is_ip = false;
|
||||
}
|
||||
static void ipcache_item_destroy(ip_cache_item *item)
|
||||
{
|
||||
@@ -675,7 +676,7 @@ static void ipcache4Print(ip_cache4 *ipcache)
|
||||
{
|
||||
*s_ip=0;
|
||||
inet_ntop(AF_INET, &ipc->key.addr, s_ip, sizeof(s_ip));
|
||||
printf("%s : hostname=%s now=last+%llu\n", s_ip, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
|
||||
printf("%s : hostname=%s hostname_is_ip=%u now=last+%llu\n", s_ip, ipc->data.hostname ? ipc->data.hostname : "", ipc->data.hostname_is_ip, (unsigned long long)(now-ipc->data.last));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -732,7 +733,7 @@ static void ipcache6Print(ip_cache6 *ipcache)
|
||||
{
|
||||
*s_ip=0;
|
||||
inet_ntop(AF_INET6, &ipc->key.addr, s_ip, sizeof(s_ip));
|
||||
printf("%s : hostname=%s now=last+%llu\n", s_ip, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
|
||||
printf("%s : hostname=%s hostname_is_ip=%u now=last+%llu\n", s_ip, ipc->data.hostname ? ipc->data.hostname : "", ipc->data.hostname_is_ip, (unsigned long long)(now-ipc->data.last));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -179,6 +179,7 @@ typedef struct ip_cache_item
|
||||
{
|
||||
time_t last;
|
||||
char *hostname;
|
||||
bool hostname_is_ip;
|
||||
} ip_cache_item;
|
||||
typedef struct ip_cache4
|
||||
{
|
||||
|
@@ -91,7 +91,7 @@ static void TLSDebug(const uint8_t *tls,size_t sz)
|
||||
TLSDebugHandshake(tls+5,sz-5);
|
||||
}
|
||||
|
||||
bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname)
|
||||
bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname, bool hostname_is_ip)
|
||||
{
|
||||
if (!params.cache_hostname) return true;
|
||||
|
||||
@@ -109,11 +109,12 @@ bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, c
|
||||
DLOG_ERR("ipcache_put_hostname: out of memory\n");
|
||||
return false;
|
||||
}
|
||||
VPRINT("hostname cached: %s\n", hostname);
|
||||
ipc->hostname_is_ip = hostname_is_ip;
|
||||
VPRINT("hostname cached (is_ip=%u): %s\n", hostname_is_ip, hostname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr *a6, char *hostname, size_t hostname_buf_len)
|
||||
static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr *a6, char *hostname, size_t hostname_buf_len, bool *hostname_is_ip)
|
||||
{
|
||||
if (!params.cache_hostname)
|
||||
{
|
||||
@@ -128,15 +129,16 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
|
||||
}
|
||||
if (ipc->hostname)
|
||||
{
|
||||
VPRINT("got cached hostname: %s\n", ipc->hostname);
|
||||
VPRINT("got cached hostname (is_ip=%u): %s\n", ipc->hostname_is_ip, ipc->hostname);
|
||||
snprintf(hostname,hostname_buf_len,"%s",ipc->hostname);
|
||||
if (hostname_is_ip) *hostname_is_ip = ipc->hostname_is_ip;
|
||||
}
|
||||
else
|
||||
*hostname = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dp_match(struct desync_profile *dp, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto)
|
||||
static bool dp_match(struct desync_profile *dp, const struct sockaddr *dest, const char *hostname, bool bNoSubdom, t_l7proto l7proto)
|
||||
{
|
||||
bool bHostlistsEmpty;
|
||||
|
||||
@@ -167,11 +169,11 @@ static bool dp_match(struct desync_profile *dp, const struct sockaddr *dest, con
|
||||
return true;
|
||||
else if (hostname)
|
||||
// if hostlists are present profile matches only if hostname is known and satisfy profile hostlists
|
||||
return HostlistCheck(dp, hostname, NULL, true);
|
||||
return HostlistCheck(dp, hostname, bNoSubdom, NULL, true);
|
||||
|
||||
return false;
|
||||
}
|
||||
static struct desync_profile *dp_find(struct desync_profile_list_head *head, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto)
|
||||
static struct desync_profile *dp_find(struct desync_profile_list_head *head, const struct sockaddr *dest, const char *hostname, bool bNoSubdom, t_l7proto l7proto)
|
||||
{
|
||||
struct desync_profile_list *dpl;
|
||||
if (params.debug)
|
||||
@@ -182,7 +184,7 @@ static struct desync_profile *dp_find(struct desync_profile_list_head *head, con
|
||||
}
|
||||
LIST_FOREACH(dpl, head, next)
|
||||
{
|
||||
if (dp_match(&dpl->dp,dest,hostname,l7proto))
|
||||
if (dp_match(&dpl->dp,dest,hostname,bNoSubdom,l7proto))
|
||||
{
|
||||
VPRINT("desync profile %d matches\n",dpl->dp.n);
|
||||
return &dpl->dp;
|
||||
@@ -198,11 +200,11 @@ void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest)
|
||||
if (!ctrack->hostname)
|
||||
{
|
||||
char host[256];
|
||||
if (ipcache_get_hostname(dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL , host, sizeof(host)) && *host)
|
||||
if (ipcache_get_hostname(dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL , host, sizeof(host), &ctrack->hostname_is_ip) && *host)
|
||||
if (!(ctrack->hostname=strdup(host)))
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
}
|
||||
ctrack->dp = dp_find(¶ms.desync_profiles, dest, ctrack->hostname, ctrack->l7proto);
|
||||
ctrack->dp = dp_find(¶ms.desync_profiles, dest, ctrack->hostname, ctrack->hostname_is_ip, ctrack->l7proto);
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +215,7 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
uint8_t *p, *pp, *pHost = NULL;
|
||||
size_t method_len = 0, pos, tpos, orig_size=*size;
|
||||
const char *method;
|
||||
bool bHaveHost = false;
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
char *pc, Host[256];
|
||||
t_l7proto l7proto;
|
||||
|
||||
@@ -271,8 +273,9 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(Host);
|
||||
VPRINT("request hostname: %s\n", Host);
|
||||
if (!ipcache_put_hostname(dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL , Host))
|
||||
if (!ipcache_put_hostname(dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL , Host, bHostIsIp))
|
||||
DLOG_ERR("ipcache_put_hostname: out of memory");
|
||||
}
|
||||
|
||||
@@ -293,6 +296,7 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
DLOG_ERR("strdup hostname : out of memory\n");
|
||||
return;
|
||||
}
|
||||
ctrack->hostname_is_ip = bHostIsIp;
|
||||
ctrack->hostname_discovered = true;
|
||||
}
|
||||
|
||||
@@ -312,7 +316,7 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
if (bHaveHost && !ctrack->b_host_checked)
|
||||
{
|
||||
bool bHostExcluded;
|
||||
ctrack->b_host_matches = HostlistCheck(ctrack->dp, Host, &bHostExcluded, false);
|
||||
ctrack->b_host_matches = HostlistCheck(ctrack->dp, Host, bHostIsIp, &bHostExcluded, false);
|
||||
ctrack->b_host_checked = true;
|
||||
if (!ctrack->b_host_matches)
|
||||
ctrack->b_ah_check = !bHostExcluded;
|
||||
@@ -542,7 +546,7 @@ static void auto_hostlist_reset_fail_counter(struct desync_profile *dp, const ch
|
||||
}
|
||||
}
|
||||
|
||||
static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname, const char *client_ip_port, t_l7proto l7proto)
|
||||
static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname, bool bNoSubdom, const char *client_ip_port, t_l7proto l7proto)
|
||||
{
|
||||
hostfail_pool *fail_counter;
|
||||
|
||||
@@ -566,7 +570,7 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
||||
|
||||
VPRINT("auto hostlist (profile %d) : rechecking %s to avoid duplicates\n", dp->n, hostname);
|
||||
bool bExcluded=false;
|
||||
if (!HostlistCheck(dp, hostname, &bExcluded, false) && !bExcluded)
|
||||
if (!HostlistCheck(dp, hostname, bNoSubdom, &bExcluded, false) && !bExcluded)
|
||||
{
|
||||
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);
|
||||
@@ -626,7 +630,7 @@ void tamper_in(t_ctrack *ctrack, const struct sockaddr *client, uint8_t *segment
|
||||
// received not http reply. do not monitor this connection anymore
|
||||
VPRINT("incoming unknown HTTP data detected for hostname %s\n", ctrack->hostname);
|
||||
}
|
||||
if (bFail) auto_hostlist_failed(ctrack->dp, ctrack->hostname, client_ip_port, ctrack->l7proto);
|
||||
if (bFail) auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
}
|
||||
if (!bFail) auto_hostlist_reset_fail_counter(ctrack->dp, ctrack->hostname, client_ip_port, ctrack->l7proto);
|
||||
}
|
||||
@@ -651,7 +655,7 @@ void rst_in(t_ctrack *ctrack, const struct sockaddr *client)
|
||||
{
|
||||
VPRINT("incoming RST detected for hostname %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : client %s : proto %s : incoming RST", ctrack->hostname, ctrack->dp->n, client_ip_port, l7proto_str(ctrack->l7proto));
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, client_ip_port, ctrack->l7proto);
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -674,7 +678,7 @@ void hup_out(t_ctrack *ctrack, const struct sockaddr *client)
|
||||
// local leg dropped connection after first request. probably due to timeout.
|
||||
VPRINT("local leg closed connection after first request (timeout ?). hostname: %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : client %s : proto %s : client closed connection without server reply", ctrack->hostname, ctrack->dp->n, client_ip_port, l7proto_str(ctrack->l7proto));
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, client_ip_port, ctrack->l7proto);
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,12 +16,13 @@ typedef struct
|
||||
bool bTamperInCutoff;
|
||||
bool b_host_checked,b_host_matches,b_ah_check;
|
||||
bool hostname_discovered;
|
||||
bool hostname_is_ip;
|
||||
char *hostname;
|
||||
struct desync_profile *dp; // desync profile cache
|
||||
} t_ctrack;
|
||||
|
||||
void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest);
|
||||
bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname);
|
||||
bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname, bool hostname_is_ip);
|
||||
|
||||
void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *multisplit_pos, int *multisplit_count, uint8_t *split_flags);
|
||||
void tamper_in(t_ctrack *ctrack, const struct sockaddr *client, uint8_t *segment,size_t segment_buffer_size,size_t *size);
|
||||
|
10
tpws/tpws.c
10
tpws/tpws.c
@@ -216,7 +216,7 @@ static void exithelp(void)
|
||||
" --pidfile=<filename>\t\t\t; write pid to file\n"
|
||||
" --user=<username>\t\t\t; drop root privs\n"
|
||||
" --uid=uid[:gid1,gid2,...]\t\t; drop root privs\n"
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
" --enable-pf\t\t\t\t; enable PF redirector support. required in FreeBSD when used with PF firewall.\n"
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
@@ -711,7 +711,7 @@ enum opt_indices {
|
||||
IDX_IPSET_EXCLUDE,
|
||||
IDX_IPSET_EXCLUDE_IP,
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
IDX_ENABLE_PF,
|
||||
#elif defined(__APPLE__)
|
||||
IDX_LOCAL_TCP_USER_TIMEOUT,
|
||||
@@ -804,7 +804,7 @@ static const struct option long_options[] = {
|
||||
[IDX_IPSET_EXCLUDE] = {"ipset-exclude", required_argument, 0, 0},
|
||||
[IDX_IPSET_EXCLUDE_IP] = {"ipset-exclude-ip", required_argument, 0, 0},
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
[IDX_ENABLE_PF] = {"enable-pf", no_argument, 0, 0},
|
||||
#elif defined(__APPLE__)
|
||||
[IDX_LOCAL_TCP_USER_TIMEOUT] = {"local-tcp-user-timeout", required_argument, 0, 0},
|
||||
@@ -840,7 +840,7 @@ void parse_params(int argc, char *argv[])
|
||||
params.tcp_user_timeout_remote = DEFAULT_TCP_USER_TIMEOUT_REMOTE;
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__APPLE__)
|
||||
#if defined(__APPLE__)
|
||||
params.pf_enable = true; // OpenBSD and MacOS have no other choice
|
||||
#endif
|
||||
|
||||
@@ -1554,7 +1554,7 @@ void parse_params(int argc, char *argv[])
|
||||
params.tamper = true;
|
||||
break;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
case IDX_ENABLE_PF:
|
||||
params.pf_enable = true;
|
||||
break;
|
||||
|
@@ -495,7 +495,7 @@ static bool connect_remote_conn(tproxy_conn_t *conn)
|
||||
int mss=0;
|
||||
|
||||
if (conn->track.hostname)
|
||||
if (!ipcache_put_hostname(conn->dest.sa_family==AF_INET ? &((struct sockaddr_in*)&conn->dest)->sin_addr : NULL, conn->dest.sa_family==AF_INET6 ? &((struct sockaddr_in6*)&conn->dest)->sin6_addr : NULL , conn->track.hostname))
|
||||
if (!ipcache_put_hostname(conn->dest.sa_family==AF_INET ? &((struct sockaddr_in*)&conn->dest)->sin_addr : NULL, conn->dest.sa_family==AF_INET6 ? &((struct sockaddr_in6*)&conn->dest)->sin6_addr : NULL , conn->track.hostname, conn->track.hostname_is_ip))
|
||||
DLOG_ERR("ipcache_put_hostname: out of memory");
|
||||
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
|
||||
|
||||
@@ -507,7 +507,7 @@ static bool connect_remote_conn(tproxy_conn_t *conn)
|
||||
if (conn->track.hostname)
|
||||
{
|
||||
bool bHostExcluded;
|
||||
conn->track.b_host_matches = HostlistCheck(conn->track.dp, conn->track.hostname, &bHostExcluded, false);
|
||||
conn->track.b_host_matches = HostlistCheck(conn->track.dp, conn->track.hostname, conn->track.hostname_is_ip, &bHostExcluded, false);
|
||||
conn->track.b_host_checked = true;
|
||||
if (!conn->track.b_host_matches)
|
||||
{
|
||||
|
Reference in New Issue
Block a user