48 Commits

Author SHA1 Message Date
bol-van
56456c1e0c nfqws,tpws: fix possible crashes or high memory usage if hostlist has duplicate hostnames 2025-08-08 11:35:13 +03:00
bol-van
d6a8d1dc33 lame issue warning in english 2025-08-06 08:25:23 +03:00
bol-van
04b3b6abcb update issue warning 2025-08-04 10:59:41 +03:00
bol-van
fd58ecf8a5 update issue warning 2025-08-04 10:58:41 +03:00
bol-van
a560e251a1 update changes.txt 2025-08-01 13:28:19 +03:00
bol-van
2ff0f9c0ff tpws: minor update 2025-08-01 13:23:05 +03:00
bol-van
4dbd673eaa update changes.txt 2025-08-01 12:52:06 +03:00
bol-van
497810ab4e tpws: special case for ip looking hostnames 2025-08-01 12:48:16 +03:00
bol-van
4cfed1db7e nfqws: print hostname_is_ip in ipv6 ipcache 2025-08-01 12:12:24 +03:00
bol-van
fd6b7a2b7f nfqws: optimize code 2025-08-01 12:03:53 +03:00
bol-van
6d865ad790 nfqws: comment 2025-08-01 11:31:48 +03:00
bol-van
dfe36aee4c nfqws: special case for ip looking hostnames 2025-08-01 11:21:23 +03:00
bol-van
2d704a859d blockcheck: display timestamp enable message 2025-07-31 13:57:13 +03:00
bol-van
8026d11f71 blockcheck: test ts fooling, silently enable timestamps in windows 2025-07-31 13:49:30 +03:00
bol-van
2f77cec863 doc works 2025-07-31 13:11:18 +03:00
bol-van
ba7954f068 doc works 2025-07-31 13:09:44 +03:00
bol-van
8b5c951451 nfqws: ts fooling 2025-07-31 12:51:31 +03:00
bol-van
84e75b0f28 doc works 2025-07-30 15:08:09 +03:00
bol-van
c4e5db309f doc works 2025-07-30 15:06:24 +03:00
bol-van
769f7b60c8 doc works 2025-07-30 15:02:08 +03:00
bol-van
b0578c5e9f doc works 2025-07-30 15:00:41 +03:00
bol-van
40362bfb5b doc works 2025-07-30 15:00:05 +03:00
bol-van
10eb9050a1 doc works 2025-07-30 14:59:28 +03:00
bol-van
b63e598085 FILTER_MARK support 2025-07-30 14:42:30 +03:00
bol-van
c60f9c9027 doc update ver 2025-07-08 10:01:58 +03:00
bol-van
951c980bec typo 2025-07-07 17:33:36 +03:00
bol-van
5eaec085dd install_easy: warn about --ipset 2025-07-07 15:53:46 +03:00
bol-van
721b353776 doc works 2025-07-07 15:38:51 +03:00
bol-van
e6d2051c87 doc works 2025-07-07 15:37:40 +03:00
bol-van
e665794ac4 doc works 2025-07-07 15:33:41 +03:00
bol-van
7db14a07c5 tpws: openbsd no more inits /dev/pf by default 2025-07-07 15:33:02 +03:00
bol-van
c14554c1f3 Merge pull request #1585 from artur-intech/patch-1
Fix filename
2025-06-30 07:46:10 +03:00
Artur
ced1682003 Fix filename 2025-06-29 21:45:50 +03:00
Artur
4701f27372 Fix filename
It is `zapret-hosts-user.txt`, not `*-users*`.
2025-06-29 20:18:37 +03:00
bol-van
a1699067b3 Merge pull request #1575 from dass79zh/ipv6less-curl-fix
Support curl compiled without IPv6 support.
2025-06-27 21:57:08 +03:00
Andrew Danshin
643fc0c456 Support curl compiled without IPv6 support.
modified:   blockcheck.sh
2025-06-27 21:07:32 +03:00
bol-van
09c07f6d21 winws: decrease wf-save buf 2025-06-23 08:17:52 +03:00
bol-van
dd72c68ae6 winws: increase windivert filter buffers 2025-06-23 08:14:36 +03:00
bol-van
9c1a3e77cc Makefiles: CC=cc 2025-06-22 21:39:27 +03:00
bol-van
ae957e9a73 doc fix 2025-06-22 19:27:20 +03:00
bol-van
bc47a13ba4 install_bin: no help text if getarch 2025-06-16 09:13:40 +03:00
bol-van
20b69cb63d install_bin: minor improve help text 2025-06-16 07:15:08 +03:00
bol-van
ef4f8a2b86 install_bin: display help text if no bins found 2025-06-16 07:11:59 +03:00
bol-van
d00d341505 blockcheck: display kernel ver 2025-06-15 16:22:38 +03:00
bol-van
0738d3980f blockcheck: curl version display 2025-06-15 15:56:25 +03:00
bol-van
34ff4630bf blockcheck: curl version display 2025-06-15 15:55:03 +03:00
bol-van
f8b5f602a4 nfqws: allow desync of replayed udp with reasm offset !=0 2025-06-15 09:18:25 +03:00
bol-van
8dacb57a86 OPTIMIZE in makefiles 2025-06-13 22:17:32 +03:00
45 changed files with 569 additions and 185 deletions

View File

@@ -7,13 +7,19 @@ assignees: ''
---
1. Здесь не место для вопросов, касающихся компьютерной грамотности и навыков использования ОС
2. Здесь не место для вопросов "у меня не работает" без технических подробностей
3. Здесь не место для вопросов "как мне открыть ютуб", "что писать в ...", "перестало открываться".
4. Здесь не место для обсуждения сборок
5. Вирусов здесь нет. У вас либо чья-то сборка, либо ваш антивирус давно пора отправить на покой. Антивирусы в основном жалуются на upx и windivert, которые убраны НЕ будут. upx - это паковщик для сокращения требуемого места на openwrt, windivert - замена iptables для windows, потенциальный инструмент хакера или компонент зловредной программы, но сам по себе вирусом не является. Не согласны - удаляйте софт. За агрессивные наезды "почему автор распространяет вирусы" молча схватите бан.
Issues - это место для обращений к разработчику.
Discussions - место для обсуждения вопросов между пользователями.
Не тратье время разработчика на ерунду. Вам не будут здесь обьяснять как скопировать, что "писать в", почему сразу же закрывается окно, почему не открывается сайт или госуслуги. Здесь не место обсуждению любых шаманств , т.е. манипуляций без понимания, в стиле 4pda.
Пишите только конкретные проблемы на техническом уровне в оригинальном zapret (не в сборках), которые вы заметили, и которые являются или могут являться багами в софте.
Или если вы считаете, что ваше обращение обосновано, технически грамотно и по адресу.
Все, что будет нарушать эти критерии, может быть молча удалено, закрыто или перенесено в дискуссии на усмотрение разработчика.
Если сомневаетесь - пишите лучше сразу в дискуссии.
Все означенное обсуждать в дискуссиях или на форумах.
При нарушении будет закрываться или конвертироваться в дискуссии.
Issue только для обсуждения проблем самого софта. Неработа стратегии или ваше неумение настроить - это ваша проблема, а не проблема софта.
Однокнопочные решения дают только сборщики, поэтому "открытие сайта" не является функцией программы, и нет смысла жаловаться, что он не открывается. Но можно это обсудить в дискуссиях. Не захламляйте issues !
Прочитайте для начала docs/quick_start.md или docs/quick_start_windows.md.
Там обьясняется для кого этот софт, какие требуются знания, почему это не простая волшебная таблетка.
Вирусов здесь нет. У вас либо чья-то сборка, либо ваш антивирус давно пора отправить на покой. Антивирусы в основном жалуются на upx и windivert, которые убраны НЕ будут. upx - это паковщик для сокращения требуемого места на openwrt, windivert - замена iptables для windows, потенциальный инструмент хакера или компонент зловредной программы, но сам по себе вирусом не является. Не согласны - удаляйте софт. За агрессивные наезды "почему автор распространяет вирусы" молча схватите бан.
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.
There're also no viruses here. All virus claims and everyting non-technical and non-bugs will be instantly deleted, closed or moved to Discussions.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -514,6 +514,27 @@ 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
v71.4
nfqws,tpws: fix possible crashes or high memory usage if hostlist has duplicate hostnames

View File

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

View File

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

View File

@@ -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** с разными стратегиями. Однако, не следует делать пересекающиеся фильтры.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
dp = ctrack_replay->dp = dp_find(&params.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(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, ssid, NULL, NULL, NULL);
dp = dp_find(&params.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(&params.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(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
dp = ctrack_replay->dp = dp_find(&params.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(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, ssid, NULL, NULL, NULL);
dp = dp_find(&params.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(&params.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:

View File

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

View File

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

View File

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

View File

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

View File

@@ -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(&params.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(&params.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);

View File

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

View File

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

View File

@@ -12,7 +12,7 @@
HASH_DEL(*ppool, elem); \
free(elem); \
}
#define ADD_STR_POOL(etype, ppool, keystr, keystr_len) \
etype *elem; \
if (!(elem = (etype*)malloc(sizeof(etype)))) \
@@ -25,7 +25,7 @@
memcpy(elem->str, keystr, keystr_len); \
elem->str[keystr_len] = 0; \
oom = false; \
HASH_ADD_KEYPTR(hh, *ppool, elem->str, strlen(elem->str), elem); \
HASH_ADD_KEYPTR(hh, *ppool, elem->str, keystr_len, elem); \
if (oom) \
{ \
free(elem->str); \
@@ -33,9 +33,12 @@
return false; \
}
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
elem->flags = flg;
etype *elem_find; \
HASH_FIND(hh, *ppool, keystr, keystr_len, elem_find); \
if (!elem_find) { \
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
elem->flags = flg; \
}
#undef uthash_nonfatal_oom
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
@@ -629,6 +632,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 +694,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 +752,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));
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,7 @@
memcpy(elem->str, keystr, keystr_len); \
elem->str[keystr_len] = 0; \
oom = false; \
HASH_ADD_KEYPTR(hh, *ppool, elem->str, strlen(elem->str), elem); \
HASH_ADD_KEYPTR(hh, *ppool, elem->str, keystr_len, elem); \
if (oom) \
{ \
free(elem->str); \
@@ -33,9 +33,12 @@
return false; \
}
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
elem->flags = flg;
etype *elem_find; \
HASH_FIND(hh, *ppool, keystr, keystr_len, elem_find); \
if (!elem_find) { \
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
elem->flags = flg; \
}
#undef uthash_nonfatal_oom
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
@@ -616,6 +619,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 +679,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 +736,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));
}
}

View File

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

View File

@@ -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(&params.desync_profiles, dest, ctrack->hostname, ctrack->l7proto);
ctrack->dp = dp_find(&params.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);
}
}
}

View File

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

View File

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

View File

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