mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
Compare commits
No commits in common. "master" and "v70.6" have entirely different histories.
@ -341,12 +341,6 @@ netcat_test()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tpws_can_fix_seg()
|
|
||||||
{
|
|
||||||
# fix-seg requires kernel 4.6+
|
|
||||||
"$TPWS" --port 1 --dry-run --fix-seg >/dev/null 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
check_system()
|
check_system()
|
||||||
{
|
{
|
||||||
echo \* checking system
|
echo \* checking system
|
||||||
@ -361,14 +355,7 @@ check_system()
|
|||||||
Linux)
|
Linux)
|
||||||
PKTWS="$NFQWS"
|
PKTWS="$NFQWS"
|
||||||
PKTWSD=nfqws
|
PKTWSD=nfqws
|
||||||
if [ -x "$TPWS" ] ; then
|
|
||||||
if tpws_can_fix_seg ; then
|
|
||||||
echo tpws supports --fix-seg on this system
|
|
||||||
FIX_SEG='--fix-seg'
|
FIX_SEG='--fix-seg'
|
||||||
else
|
|
||||||
echo tpws does not support --fix-seg on this system
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
linux_fwtype
|
linux_fwtype
|
||||||
[ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || {
|
[ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || {
|
||||||
echo firewall type $FWTYPE not supported in $UNAME
|
echo firewall type $FWTYPE not supported in $UNAME
|
||||||
@ -735,11 +722,6 @@ ipt_aux_scheme()
|
|||||||
|
|
||||||
# to avoid possible INVALID state drop
|
# to avoid possible INVALID state drop
|
||||||
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn -j ACCEPT
|
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn -j ACCEPT
|
||||||
|
|
||||||
local icmp_filter="-p icmp -m icmp --icmp-type"
|
|
||||||
[ "$IPV" = 6 ] && icmp_filter="-p icmpv6 -m icmp6 --icmpv6-type"
|
|
||||||
IPT_ADD_DEL $1 INPUT $icmp_filter time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
|
||||||
|
|
||||||
# for strategies with incoming packets involved (autottl)
|
# for strategies with incoming packets involved (autottl)
|
||||||
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID -j ACCEPT
|
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID -j ACCEPT
|
||||||
if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then
|
if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then
|
||||||
@ -771,7 +753,6 @@ ipt_scheme()
|
|||||||
$IPTABLES -t mangle -A blockcheck_output -p $1 ! --dport $2 -j RETURN
|
$IPTABLES -t mangle -A blockcheck_output -p $1 ! --dport $2 -j RETURN
|
||||||
|
|
||||||
for ip in $3; do
|
for ip in $3; do
|
||||||
$IPTABLES -t mangle -A blockcheck_output -d $ip -j CONNMARK --or-mark $DESYNC_MARK
|
|
||||||
$IPTABLES -t mangle -A blockcheck_output -d $ip -j NFQUEUE --queue-num $QNUM
|
$IPTABLES -t mangle -A blockcheck_output -d $ip -j NFQUEUE --queue-num $QNUM
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -789,20 +770,12 @@ nft_scheme()
|
|||||||
|
|
||||||
nft add table inet $NFT_TABLE
|
nft add table inet $NFT_TABLE
|
||||||
nft "add chain inet $NFT_TABLE postnat { type filter hook output priority 102; }"
|
nft "add chain inet $NFT_TABLE postnat { type filter hook output priority 102; }"
|
||||||
nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK == 0 ip${ipver} daddr {$iplist} ct mark set ct mark or $DESYNC_MARK queue num $QNUM"
|
nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK != $DESYNC_MARK ip${ipver} daddr {$iplist} queue num $QNUM"
|
||||||
# for strategies with incoming packets involved (autottl)
|
# for strategies with incoming packets involved (autottl)
|
||||||
nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }"
|
nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }"
|
||||||
# enable everything generated by nfqws (works only in OUTPUT, not in FORWARD)
|
# enable everything generated by nfqws (works only in OUTPUT, not in FORWARD)
|
||||||
nft "add chain inet $NFT_TABLE predefrag { type filter hook output priority -402; }"
|
nft "add chain inet $NFT_TABLE predefrag { type filter hook output priority -402; }"
|
||||||
nft "add rule inet $NFT_TABLE predefrag meta nfproto ipv${IPV} mark and $DESYNC_MARK !=0 notrack"
|
nft "add rule inet $NFT_TABLE predefrag meta nfproto ipv${IPV} mark and $DESYNC_MARK !=0 notrack"
|
||||||
[ "$IPV" = 4 ] && {
|
|
||||||
nft "add rule inet $NFT_TABLE prenat icmp type time-exceeded ct mark and $DESYNC_MARK != 0 drop"
|
|
||||||
nft "add rule inet $NFT_TABLE prenat icmp type time-exceeded ct state invalid drop"
|
|
||||||
}
|
|
||||||
[ "$IPV" = 6 ] && {
|
|
||||||
nft "add rule inet $NFT_TABLE prenat icmpv6 type time-exceeded ct mark and $DESYNC_MARK != 0 drop"
|
|
||||||
nft "add rule inet $NFT_TABLE prenat icmpv6 type time-exceeded ct state invalid drop"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pktws_ipt_prepare()
|
pktws_ipt_prepare()
|
||||||
@ -1042,7 +1015,6 @@ curl_test()
|
|||||||
}
|
}
|
||||||
ws_curl_test()
|
ws_curl_test()
|
||||||
{
|
{
|
||||||
|
|
||||||
# $1 - ws start function
|
# $1 - ws start function
|
||||||
# $2 - test function
|
# $2 - test function
|
||||||
# $3 - domain
|
# $3 - domain
|
||||||
@ -1062,7 +1034,7 @@ tpws_curl_test()
|
|||||||
# $1 - test function
|
# $1 - test function
|
||||||
# $2 - domain
|
# $2 - domain
|
||||||
# $3,$4,$5, ... - tpws params
|
# $3,$4,$5, ... - tpws params
|
||||||
echo - $1 ipv$IPV $2 : tpws $3 $4 $5 $6 $7 $8 $9${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
|
echo - checking tpws $3 $4 $5 $6 $7 $8 $9${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
|
||||||
local ALL_PROXY="socks5://127.0.0.1:$SOCKS_PORT"
|
local ALL_PROXY="socks5://127.0.0.1:$SOCKS_PORT"
|
||||||
ws_curl_test tpws_start "$@"${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
|
ws_curl_test tpws_start "$@"${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
|
||||||
local testf=$1 dom=$2 strategy code=$?
|
local testf=$1 dom=$2 strategy code=$?
|
||||||
@ -1079,14 +1051,11 @@ pktws_curl_test()
|
|||||||
# $1 - test function
|
# $1 - test function
|
||||||
# $2 - domain
|
# $2 - domain
|
||||||
# $3,$4,$5, ... - nfqws/dvtws params
|
# $3,$4,$5, ... - nfqws/dvtws params
|
||||||
local testf=$1 dom=$2 strategy code
|
echo - checking $PKTWSD ${WF:+$WF }$3 $4 $5 $6 $7 $8 $9${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
|
||||||
|
ws_curl_test pktws_start "$@"${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
|
||||||
shift; shift;
|
local testf=$1 dom=$2 strategy code=$?
|
||||||
echo - $testf ipv$IPV $dom : $PKTWSD ${WF:+$WF }${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }$@${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
|
|
||||||
ws_curl_test pktws_start $testf $dom ${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }"$@"${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
|
|
||||||
|
|
||||||
code=$?
|
|
||||||
[ "$code" = 0 ] && {
|
[ "$code" = 0 ] && {
|
||||||
|
shift; shift;
|
||||||
strategy="$@"
|
strategy="$@"
|
||||||
strategy_append_extra_pktws
|
strategy_append_extra_pktws
|
||||||
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy"
|
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy"
|
||||||
@ -1096,11 +1065,11 @@ pktws_curl_test()
|
|||||||
|
|
||||||
strategy_append_extra_pktws()
|
strategy_append_extra_pktws()
|
||||||
{
|
{
|
||||||
strategy="${strategy:+${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }$strategy${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}}"
|
strategy="${strategy:+$strategy${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}}"
|
||||||
}
|
}
|
||||||
strategy_append_extra_tpws()
|
strategy_append_extra_tpws()
|
||||||
{
|
{
|
||||||
strategy="${strategy:+${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }$strategy${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}}"
|
strategy="${strategy:+$strategy${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}}"
|
||||||
}
|
}
|
||||||
|
|
||||||
xxxws_curl_test_update()
|
xxxws_curl_test_update()
|
||||||
@ -1193,19 +1162,15 @@ pktws_curl_test_update_vary()
|
|||||||
# $4 - desync mode
|
# $4 - desync mode
|
||||||
# $5,$6,... - strategy
|
# $5,$6,... - strategy
|
||||||
|
|
||||||
local testf=$1 sec=$2 domain=$3 desync=$4 proto splits= pos fake ret=1
|
local testf=$1 sec=$2 domain=$3 desync=$4 proto zerofake= tlsmod= splits= pos fake ret=1
|
||||||
local fake1=- fake2=- fake3=-
|
|
||||||
|
|
||||||
shift; shift; shift; shift
|
shift; shift; shift; shift
|
||||||
|
|
||||||
proto=http
|
proto=http
|
||||||
[ "$sec" = 0 ] || proto=tls
|
[ "$sec" = 0 ] || proto=tls
|
||||||
test_has_fake $desync && {
|
test_has_fake $desync && {
|
||||||
fake1="--dpi-desync-fake-$proto=0x00000000"
|
zerofake="--dpi-desync-fake-$proto=0x00000000"
|
||||||
[ "$sec" = 0 ] || {
|
[ "$sec" = 0 ] || tlsmod="--dpi-desync-fake-tls-mod=rnd,dupsid,rndsni,padencap"
|
||||||
fake2="--dpi-desync-fake-tls=0x00000000 --dpi-desync-fake-tls=! --dpi-desync-fake-tls-mod=rnd,rndsni,dupsid"
|
|
||||||
fake3="--dpi-desync-fake-tls-mod=rnd,dupsid,rndsni,padencap"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if test_has_fakedsplit $desync ; then
|
if test_has_fakedsplit $desync ; then
|
||||||
splits="method+2 midsld"
|
splits="method+2 midsld"
|
||||||
@ -1214,8 +1179,7 @@ pktws_curl_test_update_vary()
|
|||||||
splits="method+2 midsld"
|
splits="method+2 midsld"
|
||||||
[ "$sec" = 0 ] || splits="1 midsld 1,midsld"
|
[ "$sec" = 0 ] || splits="1 midsld 1,midsld"
|
||||||
fi
|
fi
|
||||||
for fake in '' "$fake1" "$fake2" "$fake3" ; do
|
for fake in '' $zerofake $tlsmod ; do
|
||||||
[ "$fake" = "-" ] && continue
|
|
||||||
if [ -n "$splits" ]; then
|
if [ -n "$splits" ]; then
|
||||||
for pos in $splits ; do
|
for pos in $splits ; do
|
||||||
pktws_curl_test_update $testf $domain --dpi-desync=$desync "$@" --dpi-desync-split-pos=$pos $fake && {
|
pktws_curl_test_update $testf $domain --dpi-desync=$desync "$@" --dpi-desync-split-pos=$pos $fake && {
|
||||||
@ -1240,14 +1204,14 @@ pktws_check_domain_http_bypass_()
|
|||||||
# $2 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
|
# $2 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
|
||||||
# $3 - domain
|
# $3 - domain
|
||||||
|
|
||||||
local ok ttls s f f2 e desync pos fooling frag sec="$2" delta orig splits
|
local ok ttls s f f2 e desync pos fooling frag sec="$2" delta splits
|
||||||
local need_split need_disorder need_fakedsplit need_fakeddisorder need_fake need_wssize
|
local need_split need_disorder need_fakedsplit need_fakeddisorder need_fake need_wssize
|
||||||
local splits_http='method+2 midsld method+2,midsld'
|
local splits_http='method+2 midsld method+2,midsld'
|
||||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||||
|
|
||||||
[ "$sec" = 0 ] && {
|
[ "$sec" = 0 ] && {
|
||||||
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase' '--methodeol'; do
|
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase' '--methodeol'; do
|
||||||
pktws_curl_test_update $1 $3 $s && [ "$SCANLEVEL" = quick ] && return
|
pktws_curl_test_update $1 $3 $s
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1312,21 +1276,10 @@ pktws_check_domain_http_bypass_()
|
|||||||
f="$f badseq datanoack md5sig"
|
f="$f badseq datanoack md5sig"
|
||||||
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
|
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
|
||||||
for fooling in $f; do
|
for fooling in $f; do
|
||||||
ok=0
|
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
|
||||||
warn_fool $fooling $desync
|
warn_fool $fooling $desync
|
||||||
[ "$SCANLEVEL" = quick ] && return
|
[ "$SCANLEVEL" = quick ] && return
|
||||||
need_wssize=0
|
need_wssize=0
|
||||||
ok=1
|
|
||||||
}
|
|
||||||
[ "$fooling" = md5sig ] && {
|
|
||||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && continue
|
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling --dup=1 --dup-cutoff=n2 --dup-fooling=md5sig $e && {
|
|
||||||
warn_fool $fooling $desync
|
|
||||||
echo "HINT ! To avoid possible 1 sec server response delay use --dup-ttl or --dup-autottl and block ICMP time exceeded"
|
|
||||||
[ "$SCANLEVEL" = quick ] && return
|
|
||||||
need_wssize=0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
@ -1389,11 +1342,8 @@ pktws_check_domain_http_bypass_()
|
|||||||
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
|
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
|
||||||
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
|
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
|
||||||
ok=0
|
ok=0
|
||||||
for orig in '' 1 2 3; do
|
|
||||||
for delta in 1 2 3 4 5; do
|
for delta in 1 2 3 4 5; do
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync ${orig:+--orig-autottl=+$orig} --dpi-desync-ttl=1 --dpi-desync-autottl=-$delta $e && ok=1
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=1 --dpi-desync-autottl=$delta $e && ok=1
|
||||||
done
|
|
||||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
|
||||||
done
|
done
|
||||||
[ "$ok" = 1 ] &&
|
[ "$ok" = 1 ] &&
|
||||||
{
|
{
|
||||||
@ -1438,16 +1388,14 @@ pktws_check_domain_http3_bypass_()
|
|||||||
# $1 - test function
|
# $1 - test function
|
||||||
# $2 - domain
|
# $2 - domain
|
||||||
|
|
||||||
local f desync frag tests rep fake
|
local f desync frag tests rep
|
||||||
|
|
||||||
for fake in '' "--dpi-desync-fake-quic=$ZAPRET_BASE/files/fake/quic_initial_www_google_com.bin"; do
|
|
||||||
for rep in '' 2 5 10 20; do
|
for rep in '' 2 5 10 20; do
|
||||||
pktws_curl_test_update $1 $2 --dpi-desync=fake ${fake:+$fake }${rep:+--dpi-desync-repeats=$rep} && [ "$SCANLEVEL" != force ] && {
|
pktws_curl_test_update $1 $2 --dpi-desync=fake ${rep:+--dpi-desync-repeats=$rep} && [ "$SCANLEVEL" != force ] && {
|
||||||
[ "$SCANLEVEL" = quick ] && return
|
[ "$SCANLEVEL" = quick ] && return
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
done
|
done
|
||||||
done
|
|
||||||
|
|
||||||
[ "$IPV" = 6 ] && {
|
[ "$IPV" = 6 ] && {
|
||||||
f="hopbyhop destopt"
|
f="hopbyhop destopt"
|
||||||
|
@ -405,14 +405,14 @@ std_ports()
|
|||||||
has_bad_ws_options()
|
has_bad_ws_options()
|
||||||
{
|
{
|
||||||
# $1 - nfqws/tpws opts
|
# $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
|
# ЕСЛИ ВАМ ХОЧЕТСЯ ЕГО УДАЛИТЬ И НАПИСАТЬ ИНСТРУКЦИЮ КАК ЕГО УДАЛЯТЬ, ВЫ ДЕЛАЕТЕ ХРЕНОВУЮ УСЛУГУ. НАПИШИТЕ ЛУЧШЕ custom script.
|
||||||
# but if all traffic is intercepted only to filter a group of ip its BAD. kernel ipset should be used.
|
# custom script - ЭТО ФАЙЛИК, КОТОРЫЙ ДОСТАТОЧНО СКОПИРОВАТЬ В НУЖНУЮ ДИРЕКТОРИЮ, ЧТОБЫ ОН СДЕЛАЛ ТОЖЕ САМОЕ, НО ЭФФЕКТИВНО.
|
||||||
# I cannot insert brain to copy-pasters, I know they will misuse. But it's their problem.
|
# ФИЛЬТРАЦИЯ ПО IPSET В ЯДРЕ НЕСРАВНИМО ЭФФЕКТИВНЕЕ, ЧЕМ ПЕРЕКИДЫВАТЬ ВСЕ ПАКЕТЫ В nfqws И ТАМ ФИЛЬТРОВАТЬ
|
||||||
# zapret is not made for newbies
|
# --ipset СУЩЕСТВУЕТ ТОЛЬКО ДЛЯ ВИНДЫ И LINUX СИСТЕМ БЕЗ ipset (НАПРИМЕР, Android).
|
||||||
#contains "$1" "--ipset"
|
# И ТОЛЬКО ПО ЭТОЙ ПРИЧИНЕ ОНО НЕ ВЫКИНУТО ПОЛНОСТЬЮ ИЗ LINUX ВЕРСИИ
|
||||||
return 1
|
contains "$1" "--ipset"
|
||||||
}
|
}
|
||||||
check_bad_ws_options()
|
check_bad_ws_options()
|
||||||
{
|
{
|
||||||
|
@ -391,27 +391,6 @@ zapret_do_firewall_rules_ipt()
|
|||||||
|
|
||||||
zapret_do_firewall_standard_rules_ipt $1
|
zapret_do_firewall_standard_rules_ipt $1
|
||||||
custom_runner zapret_custom_firewall $1
|
custom_runner zapret_custom_firewall $1
|
||||||
zapret_do_icmp_filter $1
|
|
||||||
}
|
|
||||||
|
|
||||||
zapret_do_icmp_filter()
|
|
||||||
{
|
|
||||||
# $1 - 1 - add, 0 - del
|
|
||||||
|
|
||||||
local FW_EXTRA_PRE= FW_EXTRA_POST=
|
|
||||||
|
|
||||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
|
|
||||||
[ "$DISABLE_IPV4" = 1 ] || {
|
|
||||||
ipt_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
|
|
||||||
ipt_add_del $1 INPUT -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
|
||||||
ipt_add_del $1 FORWARD -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
|
||||||
}
|
|
||||||
[ "$DISABLE_IPV6" = 1 ] || {
|
|
||||||
ipt6_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
|
|
||||||
ipt6_add_del $1 INPUT -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
|
||||||
ipt6_add_del $1 FORWARD -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zapret_do_firewall_ipt()
|
zapret_do_firewall_ipt()
|
||||||
|
@ -111,14 +111,6 @@ unprepare_route_localnet()
|
|||||||
set_route_localnet 0 "$@"
|
set_route_localnet 0 "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
get_uevent_devtype()
|
|
||||||
{
|
|
||||||
local DEVTYPE INTERFACE IFINDEX OF_NAME OF_FULLNAME OF_COMPATIBLE_N
|
|
||||||
[ -f "/sys/class/net/$1/uevent" ] && {
|
|
||||||
. "/sys/class/net/$1/uevent"
|
|
||||||
echo -n $DEVTYPE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolve_lower_devices()
|
resolve_lower_devices()
|
||||||
{
|
{
|
||||||
# $1 - bridge interface name
|
# $1 - bridge interface name
|
||||||
|
@ -106,7 +106,7 @@ cat << EOF | nft -f -
|
|||||||
flush chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
|
flush chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
|
||||||
add rule inet $ZAPRET_NFT_TABLE predefrag mark and $DESYNC_MARK !=0 jump predefrag_nfqws comment "nfqws generated : avoid drop by INVALID conntrack state"
|
add rule inet $ZAPRET_NFT_TABLE predefrag mark and $DESYNC_MARK !=0 jump predefrag_nfqws comment "nfqws generated : avoid drop by INVALID conntrack state"
|
||||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws mark and $DESYNC_MARK_POSTNAT !=0 notrack comment "postnat traffic"
|
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws mark and $DESYNC_MARK_POSTNAT !=0 notrack comment "postnat traffic"
|
||||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off & 0x1fff != 0 notrack comment "ipfrag"
|
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off != 0 notrack comment "ipfrag"
|
||||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws exthdr frag exists notrack comment "ipfrag"
|
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws exthdr frag exists notrack comment "ipfrag"
|
||||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws tcp flags ! syn,rst,ack notrack comment "datanoack"
|
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws tcp flags ! syn,rst,ack notrack comment "datanoack"
|
||||||
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; }
|
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; }
|
||||||
@ -119,20 +119,6 @@ EOF
|
|||||||
nft_flush_chain predefrag_nfqws
|
nft_flush_chain predefrag_nfqws
|
||||||
nft_add_rule predefrag_nfqws notrack comment \"do not track nfqws generated packets to avoid nat tampering and defragmentation\"
|
nft_add_rule predefrag_nfqws notrack comment \"do not track nfqws generated packets to avoid nat tampering and defragmentation\"
|
||||||
}
|
}
|
||||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
|
|
||||||
if is_postnat; then
|
|
||||||
# can be caused by untracked nfqws-generated packets
|
|
||||||
nft_add_rule prerouting icmp type time-exceeded ct state invalid drop
|
|
||||||
else
|
|
||||||
nft_add_rule postrouting_hook mark and $DESYNC_MARK != 0 ct mark set ct mark or $DESYNC_MARK comment \"nfqws related : prevent ttl expired socket errors\"
|
|
||||||
fi
|
|
||||||
[ "$DISABLE_IPV4" = "1" ] || {
|
|
||||||
nft_add_rule prerouting icmp type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
|
|
||||||
}
|
|
||||||
[ "$DISABLE_IPV6" = "1" ] || {
|
|
||||||
nft_add_rule prerouting icmpv6 type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
nft_del_chains()
|
nft_del_chains()
|
||||||
{
|
{
|
||||||
@ -334,7 +320,7 @@ nft_fill_ifsets()
|
|||||||
# $5 - space separated wan physical interface names (optional)
|
# $5 - space separated wan physical interface names (optional)
|
||||||
# $6 - space separated wan6 physical interface names (optional)
|
# $6 - space separated wan6 physical interface names (optional)
|
||||||
|
|
||||||
local script i j ALLDEVS devs b
|
local script i j ALLDEVS devs
|
||||||
|
|
||||||
# if large sets exist nft works very ineffectively
|
# if large sets exist nft works very ineffectively
|
||||||
# looks like it analyzes the whole table blob to find required data pieces
|
# looks like it analyzes the whole table blob to find required data pieces
|
||||||
@ -362,18 +348,15 @@ flush set inet $ZAPRET_NFT_TABLE lanif"
|
|||||||
nft_create_or_update_flowtable 'offload' 2>/dev/null
|
nft_create_or_update_flowtable 'offload' 2>/dev/null
|
||||||
# then add elements. some of them can cause error because unsupported
|
# then add elements. some of them can cause error because unsupported
|
||||||
for i in $ALLDEVS; do
|
for i in $ALLDEVS; do
|
||||||
|
# first try to add interface itself
|
||||||
|
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
|
||||||
# bridge members must be added instead of the bridge itself
|
# bridge members must be added instead of the bridge itself
|
||||||
# some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not
|
# some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not
|
||||||
b=
|
|
||||||
devs=$(resolve_lower_devices $i)
|
devs=$(resolve_lower_devices $i)
|
||||||
for j in $devs; do
|
for j in $devs; do
|
||||||
# do not display error if addition failed
|
# do not display error if addition failed
|
||||||
nft_create_or_update_flowtable 'offload' $j && b=1 2>/dev/null
|
nft_create_or_update_flowtable 'offload' $j 2>/dev/null
|
||||||
done
|
done
|
||||||
[ -n "$b" ] || {
|
|
||||||
# no lower devices added ? try to add interface itself
|
|
||||||
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
|
|
||||||
}
|
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -470,7 +453,7 @@ _nft_fw_nfqws_post4()
|
|||||||
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4
|
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4
|
||||||
rule="${3:+oifname @wanif }$filter ip daddr != @nozapret"
|
rule="${3:+oifname @wanif }$filter ip daddr != @nozapret"
|
||||||
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
|
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_insert_rule $chain $rule $setmark $FW_EXTRA_POST queue num $port bypass
|
||||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -485,7 +468,7 @@ _nft_fw_nfqws_post6()
|
|||||||
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6
|
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6
|
||||||
rule="${3:+oifname @wanif6 }$filter ip6 daddr != @nozapret6"
|
rule="${3:+oifname @wanif6 }$filter ip6 daddr != @nozapret6"
|
||||||
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
|
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_insert_rule $chain $rule $setmark $FW_EXTRA_POST queue num $port bypass
|
||||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -509,7 +492,7 @@ _nft_fw_nfqws_pre4()
|
|||||||
local filter="$1" port="$2" rule
|
local filter="$1" port="$2" rule
|
||||||
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 4
|
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
|
nft_insert_rule $(get_prechain) $rule $FW_EXTRA_POST queue num $port bypass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_nft_fw_nfqws_pre6()
|
_nft_fw_nfqws_pre6()
|
||||||
@ -522,7 +505,7 @@ _nft_fw_nfqws_pre6()
|
|||||||
local filter="$1" port="$2" rule
|
local filter="$1" port="$2" rule
|
||||||
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 6
|
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
|
nft_insert_rule $(get_prechain) $rule $FW_EXTRA_POST queue num $port bypass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nft_fw_nfqws_pre()
|
nft_fw_nfqws_pre()
|
||||||
@ -700,7 +683,3 @@ zapret_do_firewall_nft()
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# ctmark is not available in POSTNAT mode
|
|
||||||
CONNMARKER=
|
|
||||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && is_postnat && CONNMARKER="ct mark set ct mark or $DESYNC_MARK"
|
|
||||||
|
@ -129,11 +129,6 @@ INIT_APPLY_FW=1
|
|||||||
# do not work with ipv6
|
# do not work with ipv6
|
||||||
DISABLE_IPV6=1
|
DISABLE_IPV6=1
|
||||||
|
|
||||||
# drop icmp time exceeded messages for nfqws tampered connections
|
|
||||||
# in POSTNAT mode this can interfere with default mtr/traceroute in tcp or udp mode. use source port not redirected to nfqws
|
|
||||||
# set to 0 if you are not expecting connection breakage due to icmp in response to TCP SYN or UDP
|
|
||||||
FILTER_TTL_EXPIRED_ICMP=1
|
|
||||||
|
|
||||||
# select which init script will be used to get ip or host list
|
# select which init script will be used to get ip or host list
|
||||||
# possible values : get_user.sh get_antizapret.sh get_combined.sh get_reestr.sh get_hostlist.sh
|
# possible values : get_user.sh get_antizapret.sh get_combined.sh get_reestr.sh get_hostlist.sh
|
||||||
# comment if not required
|
# comment if not required
|
||||||
|
@ -481,24 +481,3 @@ nfqws: update default TLS ClientHello fake. firefox 136.0.4 finger, no kyber, SN
|
|||||||
nfqws: multiple mods for multiple TLS fakes
|
nfqws: multiple mods for multiple TLS fakes
|
||||||
init.d: remove 50-discord
|
init.d: remove 50-discord
|
||||||
blockcheck: use tpws --fix-seg on linux for multiple splits
|
blockcheck: use tpws --fix-seg on linux for multiple splits
|
||||||
|
|
||||||
v71
|
|
||||||
|
|
||||||
nfqws,tpws: debug tls version, alpn, ech
|
|
||||||
nfqws: --dpi-desync-fake-tls=! means default tls fake
|
|
||||||
nfqws: --dup*
|
|
||||||
nfqws: --orig*
|
|
||||||
nfqws: ipcache of hop count and host names
|
|
||||||
nfqws: --ctrack-disable
|
|
||||||
nfqws: --synack-split
|
|
||||||
nfqws: --autottl=- or --autottl=0:0-0 disable autottl. previous "0" does not work anymore.
|
|
||||||
tpws: ipcache of host names
|
|
||||||
nfqws,tpws: set 1024 repeat limit to fakes and dups
|
|
||||||
nfqws,tpws: do more before daemonize
|
|
||||||
nfqws,tpws: accept multiple gids in --gid
|
|
||||||
nfqws,tpws: display "android" in version string if built for android
|
|
||||||
init.d: remove --ipset parameter prohibition
|
|
||||||
init.d, blockcheck: drop time exceeded icmp for nfqws-related connections
|
|
||||||
blockcheck: some dup and orig-ttl mods
|
|
||||||
blockcheck: PKTWS_EXTRA_PRE
|
|
||||||
blockcheck: report test function and domain every test
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
# zapret v71
|
# zapret v70.6
|
||||||
|
|
||||||
# SCAMMER WARNING
|
# SCAMMER WARNING
|
||||||
|
|
||||||
This software is free and open source under [MIT license](./LICENSE.txt).
|
This software is free and open source under [MIT license](./LICENSE.txt).
|
||||||
If anyone demands you to download this software only from their webpage, telegram channel, forces you to delete links, videos, makes copyright claims, you are dealing with scammers.
|
If anyone demands you to download this software only from their webpage, telegram channel, forces you to delete links, videos, makes copyright claims, you are dealing with scammers.
|
||||||
However, [donations](#donations) are welcome.
|
|
||||||
|
|
||||||
# Multilanguage/Мультиязычный README
|
# Multilanguage/Мультиязычный README
|
||||||
___
|
___
|
||||||
@ -24,12 +23,9 @@ ___
|
|||||||
- [TCP segmentation](#tcp-segmentation)
|
- [TCP segmentation](#tcp-segmentation)
|
||||||
- [Sequence numbers overlap](#sequence-numbers-overlap)
|
- [Sequence numbers overlap](#sequence-numbers-overlap)
|
||||||
- [ipv6 specific modes](#ipv6-specific-modes)
|
- [ipv6 specific modes](#ipv6-specific-modes)
|
||||||
- [Original modding](#original-modding)
|
|
||||||
- [Duplicates](#duplicates)
|
|
||||||
- [Server reply reaction](#server-reply-reaction)
|
- [Server reply reaction](#server-reply-reaction)
|
||||||
- [SYNDATA mode](#syndata-mode)
|
- [SYNDATA mode](#syndata-mode)
|
||||||
- [DPI desync combos](#dpi-desync-combos)
|
- [DPI desync combos](#dpi-desync-combos)
|
||||||
- [IP cache](#ip-cache)
|
|
||||||
- [CONNTRACK](#conntrack)
|
- [CONNTRACK](#conntrack)
|
||||||
- [Reassemble](#reassemble)
|
- [Reassemble](#reassemble)
|
||||||
- [UDP support](#udp-support)
|
- [UDP support](#udp-support)
|
||||||
@ -38,8 +34,6 @@ ___
|
|||||||
- [Virtual machines](#virtual-machines)
|
- [Virtual machines](#virtual-machines)
|
||||||
- [IPTABLES for nfqws](#iptables-for-nfqws)
|
- [IPTABLES for nfqws](#iptables-for-nfqws)
|
||||||
- [NFTABLES for nfqws](#nftables-for-nfqws)
|
- [NFTABLES for nfqws](#nftables-for-nfqws)
|
||||||
- [Flow offloading](#flow-offloading)
|
|
||||||
- [Server side fooling](#server-side-fooling)
|
|
||||||
- [tpws](#tpws)
|
- [tpws](#tpws)
|
||||||
- [TCP segmentation in tpws](#tcp-segmentation-in-tpws)
|
- [TCP segmentation in tpws](#tcp-segmentation-in-tpws)
|
||||||
- [TLSREC](#tlsrec)
|
- [TLSREC](#tlsrec)
|
||||||
@ -145,45 +139,24 @@ nfqws takes the following parameters:
|
|||||||
--daemon ; daemonize
|
--daemon ; daemonize
|
||||||
--pidfile=<filename> ; write pid to file
|
--pidfile=<filename> ; write pid to file
|
||||||
--user=<username> ; drop root privs
|
--user=<username> ; drop root privs
|
||||||
--uid=uid[:gid1,gid2,...] ; drop root privs
|
--uid=uid[:gid] ; drop root privs
|
||||||
--bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets
|
--bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets
|
||||||
--bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets
|
--bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets
|
||||||
--wsize=<window_size>[:<scale_factor>] ; set window size. 0 = do not modify. OBSOLETE !
|
--wsize=<window_size>[:<scale_factor>] ; set window size. 0 = do not modify. OBSOLETE !
|
||||||
--wssize=<window_size>[:<scale_factor>] ; set window size for server. 0 = do not modify. default scale_factor = 0.
|
--wssize=<window_size>[:<scale_factor>] ; set window size for server. 0 = do not modify. default scale_factor = 0.
|
||||||
--wssize-cutoff=[n|d|s]N ; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
--wssize-cutoff=[n|d|s]N ; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
||||||
--ctrack-timeouts=S:E:F[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60
|
--ctrack-timeouts=S:E:F[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60
|
||||||
--ctrack-disable=[0|1] ; 1 or no argument disables conntrack
|
|
||||||
--ipcache-lifetime=<int> ; time in seconds to keep cached hop count and domain name (default 7200). 0 = no expiration
|
|
||||||
--ipcache-hostname=[0|1] ; 1 or no argument enables ip->hostname caching
|
|
||||||
--hostcase ; change Host: => host:
|
--hostcase ; change Host: => host:
|
||||||
--hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host"
|
--hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host"
|
||||||
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
|
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
|
||||||
--domcase ; mix domain case : Host: TeSt.cOm
|
--domcase ; mix domain case : Host: TeSt.cOm
|
||||||
--methodeol ; add '\n' before method and remove space after Host:
|
--methodeol ; add '\n' before method and remove space after Host:
|
||||||
--synack-split=[syn|synack|acksyn] ; perform TCP split handshake : send SYN only, SYN+ACK or ACK+SYN
|
|
||||||
--orig-ttl=<int> ; set TTL for original packets
|
|
||||||
--orig-ttl6=<int> ; set ipv6 hop limit for original packets. by default ttl value is used
|
|
||||||
--orig-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: +5:3-64. "0:0-0" or "-" disables autottl.
|
|
||||||
--orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --orig-autottl for ipv6 only
|
|
||||||
--orig-mod-start=[n|d|s]N ; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
|
||||||
--orig-mod-cutoff=[n|d|s]N ; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
|
||||||
--dup=<int> ; duplicate original packets. send N dups before original.
|
|
||||||
--dup-replace=[0|1] ; 1 or no argument means do not send original, only dups
|
|
||||||
--dup-ttl=<int> ; set TTL for dups
|
|
||||||
--dup-ttl6=<int> ; set ipv6 hop limit for dups. by default ttl value is used
|
|
||||||
--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-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
|
|
||||||
--dup-cutoff=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
|
||||||
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
||||||
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
|
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
|
||||||
--dpi-desync-ttl=<int> ; set ttl for desync packet
|
--dpi-desync-ttl=<int> ; set ttl for desync packet
|
||||||
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
|
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
|
||||||
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-20. "0:0-0" or "-" disables autottl.
|
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; auto ttl mode for both ipv4 and ipv6. default: 1:3-20
|
||||||
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dpi-desync-autottl for ipv6 only
|
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only
|
||||||
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
|
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
|
||||||
--dpi-desync-repeats=<N> ; send every desync packet N times
|
--dpi-desync-repeats=<N> ; send every desync packet N times
|
||||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
|
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
|
||||||
@ -200,7 +173,7 @@ nfqws takes the following parameters:
|
|||||||
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
|
--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
|
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
||||||
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request
|
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request
|
||||||
--dpi-desync-fake-tls=<filename>|0xHEX|! ; file containing fake TLS ClientHello (for https). '!' = standard fake
|
--dpi-desync-fake-tls=<filename>|0xHEX ; file containing fake TLS ClientHello (for https)
|
||||||
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
||||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
|
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
|
||||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
|
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
|
||||||
@ -284,13 +257,10 @@ 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.
|
* **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.
|
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).
|
Works with nftables properly. Likely requires external IP address (some ISPs pass these packets through their NAT).
|
||||||
* **autottl** tries to automatically guess hop count to the server and compute TTL by adding some delta value that can be positive or negative.
|
* **autottl** tries to automatically guess TTL value that allows DPI to receive fakes and does not allow them to reach the server.
|
||||||
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 values used by OS : 64,128,255. nfqws takes first incoming packet (YES, you need to redirect it too),
|
||||||
This tech relies on well known TTL default values used by OS : 64,128,255.
|
guesses path length and decreases by `delta` value (default 1). If resulting value is outside the range (min,max - default 3,20)
|
||||||
nfqws needs first incoming packet to see it's TTL. You must redirect it too.
|
then its normalized to min or max. If the path shorter than the value then autottl fails and falls back to the fixed value.
|
||||||
If resulting value TTL is outside the range (min,max) then its normalized to min or max.
|
|
||||||
If delta is negative and TTL is longer than guessed hop count or delta is positive and TTL is shorter than guessed hop count
|
|
||||||
then autottl fails and falls back to the fixed value.
|
|
||||||
This can help if multiple DPIs exists on backbone channels, not just near the ISP.
|
This can help if multiple DPIs exists on backbone channels, not just near the ISP.
|
||||||
Can fail if inbound and outbound paths are not symmetric.
|
Can fail if inbound and outbound paths are not symmetric.
|
||||||
|
|
||||||
@ -386,44 +356,6 @@ For example, `hopbyhop,multisplit` means split original tcp packet into several
|
|||||||
With `hopbyhop,ipfrag2` header sequence will be : `ipv6,hop-by-hop,fragment,tcp/udp`.
|
With `hopbyhop,ipfrag2` header sequence will be : `ipv6,hop-by-hop,fragment,tcp/udp`.
|
||||||
`ipfrag1` mode may not always work without special preparations. See "IP Fragmentation" notices.
|
`ipfrag1` mode may not always work without special preparations. See "IP Fragmentation" notices.
|
||||||
|
|
||||||
### Original modding
|
|
||||||
|
|
||||||
Parameters `--orig-ttl` and `--orig-ttl6` allow to set TTL on original packets.
|
|
||||||
All further packet manipulations, e.g. segmentation, take modded original as data source and inherit modded TTL.
|
|
||||||
|
|
||||||
`--orig-autottl` and `--orig-autottl6` work the same way as `dpi-desync-autottl`, but on original packets.
|
|
||||||
Delta should have unary `+` sign to produce TTL longer than guessed hop count. Otherwise nothing will reach the server.
|
|
||||||
Example : `--orig-autottl=+5:3-64`.
|
|
||||||
|
|
||||||
`--orig-mod-start` and `--orig-mod-cutoff` specify start and end conditions for original modding. The work the same way as
|
|
||||||
`--dpi-desync-start` and `--dpi-desync-cutoff`.
|
|
||||||
|
|
||||||
This function can be useful when DPI hunts for fakes and blocks suspicious connections.
|
|
||||||
DPI can compute TTL difference between packets and fire block trigger if it exceedes some threshold.
|
|
||||||
|
|
||||||
### Duplicates
|
|
||||||
|
|
||||||
Duplicates are copies of original packets which are sent before them. Duplicates are enabled by `--dup=N`, where N is dup count.
|
|
||||||
`--dup-replace` disables sending of original.
|
|
||||||
|
|
||||||
Dups are sent only when original would also be sent without reconstruction.
|
|
||||||
For example, if TCP segmentation happens, original is actually dropped and is being replaced by artificially constructed new packets.
|
|
||||||
Dups are not sent in this case.
|
|
||||||
|
|
||||||
All dup fooling modes are available : `--dup-ttl`. `--dup-ttl6`, `--dup-fooling`.
|
|
||||||
You decide whether these packets need to reach the server and in what form, according to the intended strategy.
|
|
||||||
|
|
||||||
`--dup-autottl` and `--dup-autottl6` work the same way as `dpi-desync-autottl`.
|
|
||||||
Delta can be preceeded by unary `+` or `-` sign.
|
|
||||||
Example : `--dup-autottl=-2:3-64`.
|
|
||||||
|
|
||||||
`--dup-start` and `--dup-cutoff` specify start and end conditions for dupping. The work the same way as
|
|
||||||
`--dpi-desync-start` and `--dpi-desync-cutoff`.
|
|
||||||
|
|
||||||
This function can help if DPI compares some characteristics of fake and original packets and block connection if they differ some way.
|
|
||||||
Fooled duplicates can convince DPI that the whole session has an anomaly.
|
|
||||||
For example, all connection is protected by MD5 signature, not individual packets.
|
|
||||||
|
|
||||||
### Server reply reaction
|
### Server reply reaction
|
||||||
|
|
||||||
There are DPIs that analyze responses from the server, particularly the certificate from the ServerHello that contain domain name(s). The ClientHello delivery confirmation is an ACK packet from the server with ACK sequence number corresponding to the length of the ClientHello+1.
|
There are DPIs that analyze responses from the server, particularly the certificate from the ServerHello that contain domain name(s). The ClientHello delivery confirmation is an ACK packet from the server with ACK sequence number corresponding to the length of the ClientHello+1.
|
||||||
@ -445,26 +377,12 @@ Without extra parameter payload is 16 zero bytes.
|
|||||||
|
|
||||||
`--dpi-desync` takes up to 3 comma separated modes.
|
`--dpi-desync` takes up to 3 comma separated modes.
|
||||||
|
|
||||||
* 0 phase modes work during the connection establishement : `synack`, `syndata` `--wsize`, `--wssize`. [hostlist](#multiple-strategies) filters are applicable only if [`--ipcache-hostname`](#ip-cache) is enabled.
|
* 0 phase modes work during the connection establishement : `synack`, `syndata` `--wsize`, `--wssize`. [hostlist](((#multiple-strategies))) filters are not applicable.
|
||||||
* In the 1st phase fakes are sent before original data : `fake`, `rst`, `rstack`.
|
* In the 1st phase fakes are sent before original data : `fake`, `rst`, `rstack`.
|
||||||
* In the 2nd phase original data is sent in a modified way (for example `fakedsplit` or `ipfrag2`).
|
* In the 2nd phase original data is sent in a modified way (for example `fakedsplit` or `ipfrag2`).
|
||||||
|
|
||||||
Modes must be specified in phase ascending order.
|
Modes must be specified in phase ascending order.
|
||||||
|
|
||||||
### IP cache
|
|
||||||
|
|
||||||
`ipcache` is the structure in the process memory that stores some information by IP address and interface name key.
|
|
||||||
This information can be used as missing data. Currently it's used in the following cases :
|
|
||||||
|
|
||||||
1. IP,interface => hop count . This is used to apply autottl at 0 phase since the first session packet. If the record is absent autottl will not be applied immediately. Second time it will be applied immediately using cached hop count.
|
|
||||||
|
|
||||||
2. IP => hostname . Hostname is cached to be used in 0 phase strategies. Mode is disabled by default and can be enabled by `ipcache-hostname` parameter.
|
|
||||||
This tech is experimental. There's no one-to-one correspondence between IP and domain name. Multiple domains can resolve to the same IP.
|
|
||||||
If collision happens hostname is replaced. On CDNs a domain can resolve to different IPs over time. `--ipcache-lifetime` limits how long cached record is valid. It's 2 hours by default.
|
|
||||||
Be prepared for unexpected results that can be explained only by reading debug logs.
|
|
||||||
|
|
||||||
SIGUSR2 forces process to output it's ipcache to stdout.
|
|
||||||
|
|
||||||
### CONNTRACK
|
### CONNTRACK
|
||||||
|
|
||||||
nfqws is equipped with minimalistic connection tracking system (conntrack)
|
nfqws is equipped with minimalistic connection tracking system (conntrack)
|
||||||
@ -751,31 +669,6 @@ In `iptables` flow offloading is controlled by openwrt proprietary extension `FL
|
|||||||
|
|
||||||
Flow offloading does not interfere with **tpws** and `OUTPUT` traffic. It only breaks nfqws that fools `FORWARD` traffic.
|
Flow offloading does not interfere with **tpws** and `OUTPUT` traffic. It only breaks nfqws that fools `FORWARD` traffic.
|
||||||
|
|
||||||
### Server side fooling
|
|
||||||
|
|
||||||
It's also possible.
|
|
||||||
nfqws is intended for client side attacks. That's why it recognizes direct and reply traffic based on role in connection establishement.
|
|
||||||
If it sees SYN then source IP is client IP. If it sees SYN,ACK then source ip is server IP.
|
|
||||||
For UDP client address is considered as source IP of the first seen packet of src_ip,src_port,dst_ip,dst_port tuple.
|
|
||||||
|
|
||||||
This does not work correctly on the server side. Client traffic is reply traffic, server traffic is direct traffic.
|
|
||||||
|
|
||||||
`--wsize` works in any case. It can be used on both client and server.
|
|
||||||
Other techs work only if nfqws treats traffic as direct traffic.
|
|
||||||
To apply them to server originated traffic disable conntrack by `--ctrack-disable` parameter.
|
|
||||||
If a packet is not found in conntrack it's treated as direct and techs like `multidisorder` will be applied.
|
|
||||||
|
|
||||||
Most of the protocols will not be recognized because protocol recognition system only reacts to client packets.
|
|
||||||
To make things working use `--dpi-desync-any-protocol` with connbytes or packet payload limiter.
|
|
||||||
start/cutoff are unavailable because they are conntrack based.
|
|
||||||
|
|
||||||
`--synack-split` removes standard SYN,ACK packet and replaces it with one SYN packet, SYN then ACK separate packets or ACK then SYN separate packets.
|
|
||||||
Client sends SYN,ACK in reply which usually only server does.
|
|
||||||
This makes some DPI's to treat connection establishement roles wrong. They stop to block.
|
|
||||||
See [split handshake](https://nmap.org/misc/split-handshake.pdf).
|
|
||||||
|
|
||||||
On server side traffic should be redirected to nfqws using source port numbers and original connbytes direction.
|
|
||||||
|
|
||||||
|
|
||||||
## tpws
|
## tpws
|
||||||
|
|
||||||
@ -812,8 +705,6 @@ tpws is transparent proxy.
|
|||||||
--local-tcp-user-timeout=<seconds> ; set tcp user timeout for local leg (default : 10, 0 = system default)
|
--local-tcp-user-timeout=<seconds> ; set tcp user timeout for local leg (default : 10, 0 = system default)
|
||||||
--remote-tcp-user-timeout=<seconds> ; set tcp user timeout for remote leg (default : 20, 0 = system default)
|
--remote-tcp-user-timeout=<seconds> ; set tcp user timeout for remote leg (default : 20, 0 = system default)
|
||||||
--fix-seg=<int> ; recover failed TCP segmentation at the cost of slowdown. wait up to N msec.
|
--fix-seg=<int> ; recover failed TCP segmentation at the cost of slowdown. wait up to N msec.
|
||||||
--ipcache-lifetime=<int> ; time in seconds to keep cached domain name (default 7200). 0 = no expiration
|
|
||||||
--ipcache-hostname=[0|1] ; 1 or no argument enables ip->hostname caching
|
|
||||||
--no-resolve ; disable socks5 remote dns
|
--no-resolve ; disable socks5 remote dns
|
||||||
--resolver-threads=<int> ; number of resolver worker threads
|
--resolver-threads=<int> ; number of resolver worker threads
|
||||||
--maxconn=<max_connections> ; max number of local legs
|
--maxconn=<max_connections> ; max number of local legs
|
||||||
@ -864,7 +755,7 @@ tpws is transparent proxy.
|
|||||||
--daemon ; daemonize
|
--daemon ; daemonize
|
||||||
--pidfile=<filename> ; write pid to file
|
--pidfile=<filename> ; write pid to file
|
||||||
--user=<username> ; drop root privs
|
--user=<username> ; drop root privs
|
||||||
--uid=uid[:gid1,gid2,...] ; drop root privs
|
--uid=uid[:gid] ; drop root privs
|
||||||
```
|
```
|
||||||
|
|
||||||
### TCP segmentation in tpws
|
### TCP segmentation in tpws
|
||||||
@ -898,7 +789,7 @@ If you're attempting to split massive transmission with `--split-any-protocol` o
|
|||||||
`--mss` sets TCP_MAXSEG socket option. Client sets this value in MSS TCP option in the SYN packet.
|
`--mss` sets TCP_MAXSEG socket option. Client sets this value in MSS TCP option in the SYN packet.
|
||||||
Server replies with it's own MSS in SYN,ACK packet. Usually servers lower their packet sizes but they still don't fit to supplied MSS. The greater MSS client sets the bigger server's packets will be.
|
Server replies with it's own MSS in SYN,ACK packet. Usually servers lower their packet sizes but they still don't fit to supplied MSS. The greater MSS client sets the bigger server's packets will be.
|
||||||
If it's enough to split TLS 1.2 ServerHello, it may fool DPI that checks certificate domain name.
|
If it's enough to split TLS 1.2 ServerHello, it may fool DPI that checks certificate domain name.
|
||||||
This scheme may significantly lower speed. Hostlist filter is possible only in socks mode if client uses remote resolving (firefox `network.proxy.socks_remote_dns`) or if `ipcache-hostname` is enabled.
|
This scheme may significantly lower speed. Hostlist filter is possible only in socks mode if client uses remote resolving (firefox `network.proxy.socks_remote_dns`).
|
||||||
`--mss` is not required for TLS1.3. If TLS1.3 is negotiable then MSS make things only worse. Use only if nothing better is available. Works only in Linux, not BSD or MacOS.
|
`--mss` is not required for TLS1.3. If TLS1.3 is negotiable then MSS make things only worse. Use only if nothing better is available. Works only in Linux, not BSD or MacOS.
|
||||||
|
|
||||||
### Other tamper options
|
### Other tamper options
|
||||||
@ -1379,10 +1270,6 @@ With other values or if the parameter is commented out, the rules will not be ap
|
|||||||
This is useful if you have a firewall management system, in the settings of which you should tie the rules.
|
This is useful if you have a firewall management system, in the settings of which you should tie the rules.
|
||||||
Not applicable to `OpenWRT` if used with `firewall3+iptables`.
|
Not applicable to `OpenWRT` if used with `firewall3+iptables`.
|
||||||
|
|
||||||
`FILTER_TTL_EXPIRED_ICMP=1` blocks icmp time exceeded messages in response to connections handled by nfqws.
|
|
||||||
Linux closes socket if it receives this icmp in response to SYN packet. Similar mechanism exists for datagram sockets.
|
|
||||||
It's better to disable this if you do not expect problems caused by icmp.
|
|
||||||
|
|
||||||
The following settings are not relevant for openwrt :
|
The following settings are not relevant for openwrt :
|
||||||
|
|
||||||
If your system works as a router, then you need to enter the names of the internal and external interfaces:
|
If your system works as a router, then you need to enter the names of the internal and external interfaces:
|
||||||
|
187
docs/readme.md
187
docs/readme.md
@ -1,10 +1,9 @@
|
|||||||
# zapret v71
|
# zapret v70.6
|
||||||
|
|
||||||
# ВНИМАНИЕ, остерегайтесь мошенников
|
# ВНИМАНИЕ, остерегайтесь мошенников
|
||||||
|
|
||||||
zapret является свободным и open source.
|
zapret является свободным и open source.
|
||||||
Всякий, кто понуждает вас скачивать zapret только с его ресурса, требует удалить ссылки, видео, файлы, обосновывая эти требования авторскими правами, сам нарушает [лицензию](./LICENSE.txt).
|
Всякий, кто понуждает вас скачивать zapret только с его ресурса, требует удалить ссылки, видео, файлы, обосновывая эти требования авторскими правами, сам нарушает [лицензию](./LICENSE.txt).
|
||||||
Однако, это не исключает [добровольные пожертвования](#поддержать-разработчика).
|
|
||||||
|
|
||||||
# Multilanguage README
|
# Multilanguage README
|
||||||
|
|
||||||
@ -26,10 +25,7 @@ zapret является свободным и open source.
|
|||||||
- [TCP СЕГМЕНТАЦИЯ](#tcp-сегментация)
|
- [TCP СЕГМЕНТАЦИЯ](#tcp-сегментация)
|
||||||
- [ПЕРЕКРЫТИЕ SEQUENCE NUMBERS](#перекрытие-sequence-numbers)
|
- [ПЕРЕКРЫТИЕ SEQUENCE NUMBERS](#перекрытие-sequence-numbers)
|
||||||
- [СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6](#специфические-режимы-ipv6)
|
- [СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6](#специфические-режимы-ipv6)
|
||||||
- [МОДИФИКАЦИЯ ОРИГИНАЛА](#модификация-оригинала)
|
|
||||||
- [ДУБЛИКАТЫ](#дубликаты)
|
|
||||||
- [КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ](#комбинирование-методов-десинхронизации)
|
- [КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ](#комбинирование-методов-десинхронизации)
|
||||||
- [КЭШ IP](#кэш-ip)
|
|
||||||
- [РЕАКЦИЯ DPI НА ОТВЕТ СЕРВЕРА](#реакция-dpi-на-ответ-сервера)
|
- [РЕАКЦИЯ DPI НА ОТВЕТ СЕРВЕРА](#реакция-dpi-на-ответ-сервера)
|
||||||
- [РЕЖИМ SYNACK](#режим-synack)
|
- [РЕЖИМ SYNACK](#режим-synack)
|
||||||
- [РЕЖИМ SYNDATA](#режим-syndata)
|
- [РЕЖИМ SYNDATA](#режим-syndata)
|
||||||
@ -42,7 +38,6 @@ zapret является свободным и open source.
|
|||||||
- [IPTABLES ДЛЯ NFQWS](#iptables-для-nfqws)
|
- [IPTABLES ДЛЯ NFQWS](#iptables-для-nfqws)
|
||||||
- [NFTABLES ДЛЯ NFQWS](#nftables-для-nfqws)
|
- [NFTABLES ДЛЯ NFQWS](#nftables-для-nfqws)
|
||||||
- [FLOW OFFLOADING](#flow-offloading)
|
- [FLOW OFFLOADING](#flow-offloading)
|
||||||
- [ДУРЕНИЕ СО СТОРОНЫ СЕРВЕРА](#дурение-со-стороны-сервера)
|
|
||||||
- [tpws](#tpws)
|
- [tpws](#tpws)
|
||||||
- [TCP СЕГМЕНТАЦИЯ В TPWS](#tcp-сегментация-в-tpws)
|
- [TCP СЕГМЕНТАЦИЯ В TPWS](#tcp-сегментация-в-tpws)
|
||||||
- [TLSREC](#tlsrec)
|
- [TLSREC](#tlsrec)
|
||||||
@ -174,31 +169,10 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
--qnum=N ; номер очереди N
|
--qnum=N ; номер очереди N
|
||||||
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
|
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
|
||||||
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
|
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
|
||||||
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
|
|
||||||
--ctrack-disable=[0|1] ; 1 или остутствие аргумента отключает conntrack
|
|
||||||
--ipcache-lifetime=<int> ; время жизни записей кэша IP в секундах. 0 - без ограничений.
|
|
||||||
--ipcache-hostname=[0|1] ; 1 или отсутствие аргумента включают кэширование имен хостов для применения в стратегиях нулевой фазы
|
|
||||||
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
|
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
|
||||||
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !)
|
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !)
|
||||||
--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
||||||
--synack-split=[syn|synack|acksyn] ; выполнить tcp split handshake. вместо SYN,ACK отсылать только SYN, SYN+ACK или ACK+SYN
|
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
|
||||||
--orig-ttl=<int> ; модифицировать TTL оригинального пакета
|
|
||||||
--orig-ttl6=<int> ; модифицировать ipv6 hop limit оригинальных пакетов. если не указано, используется значение --orig-ttl
|
|
||||||
--orig-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +5:3-64. "0:0-0" или "-" отключает функцию
|
|
||||||
--orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
|
|
||||||
--orig-mod-start=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
|
||||||
--orig-mod-cutoff=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
|
||||||
--dup=<int> ; высылать N дубликатов до оригинала
|
|
||||||
--dup-replace=[0|1] ; 1 или отсутствие аргумента блокирует отправку оригинала. отправляются только дубликаты.
|
|
||||||
--dup-ttl=<int> ; модифицировать TTL дубликатов
|
|
||||||
--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-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
|
|
||||||
--dup-cutoff=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
|
||||||
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
||||||
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
||||||
--methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
|
--methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
|
||||||
@ -207,9 +181,9 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
||||||
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
||||||
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
||||||
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение --dpi-desync-ttl
|
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
|
||||||
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. "0:0-0" или "-" отключает функцию
|
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
|
||||||
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
|
--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 hopbyhop hopbyhop2
|
||||||
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
|
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
|
||||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
||||||
@ -221,7 +195,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
||||||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||||||
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
||||||
--dpi-desync-fake-tls=<filename>|0xHEX|! ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному. '!' = стандартный фейк
|
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
|
||||||
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
||||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
||||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
||||||
@ -336,19 +310,14 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому работает даже с внутренним провайдерским IP.
|
выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому работает даже с внутренним провайдерским IP.
|
||||||
Но linux NAT оно не пройдет, так что за домашним роутером эта техника скорее всего не сработает, но может сработать с него.
|
Но linux NAT оно не пройдет, так что за домашним роутером эта техника скорее всего не сработает, но может сработать с него.
|
||||||
Может сработать и через роутер, если подключение по проводу, и на роутере включено аппаратное ускорение.
|
Может сработать и через роутер, если подключение по проводу, и на роутере включено аппаратное ускорение.
|
||||||
* `autottl`. Суть режима в автоматическом определении TTL, чтобы пакет почти наверняка прошел DPI и немного не дошел до
|
* `autottl`. Суть режима в автоматическом определении TTL, чтобы он почти наверняка прошел DPI и немного не дошел до
|
||||||
сервера (`--dpi-desync-autottl`). Или наоборот - TTL едва хватило, чтобы он все-таки дошел до сервера (см `--dup-autottl`, `--orig-autottl`).
|
сервера. Берутся базовые значения TTL 64,128,255, смотрится входящий пакет
|
||||||
Берутся базовые значения TTL 64,128,255, смотрится входящий пакет (да, требуется направить первый входящий пакет на nfqws !).
|
(да, требуется направить первый входящий пакет на nfqws !). Вычисляется длина пути, отнимается `delta` (1 по
|
||||||
Вычисляется длина пути, прибавляется `delta`. delta может быть положительной или отрицательной.
|
умолчанию). Если TTL вне диапазона (min,max - 3,20 по умолчанию), то берутся значения min,max, чтобы вписаться в
|
||||||
Чтобы задать положительную дельту, нужно указать унарный знак **+** перед числом.
|
диапазон. Если при этом полученный TTL больше длины пути, то автоматизм не сработал и берутся фиксированные значения
|
||||||
В случае его отсутствия или при наличии унарного знака **-** дельта считается отрицательной.
|
TTL для атаки. Техника позволяет решить вопрос, когда вся сеть перегорожена шлагбаумами (DPI, ТСПУ) везде где только
|
||||||
Если TTL вне диапазона min,max, то берутся значения min,max, чтобы вписаться в
|
|
||||||
диапазон. Если при этом дельта отрицательная и полученный TTL больше длины пути или дельта положительная и полученный TTL меньше длины пути,
|
|
||||||
то автоматизм не сработал и берутся фиксированные значения : `--dpi-desync-ttl`, `--orig-ttl`, `--dup-ttl`.
|
|
||||||
Техника позволяет решить вопрос, когда вся сеть перегорожена шлагбаумами (DPI, ТСПУ) везде где только
|
|
||||||
можно, включая магистралов. Но потенциально может давать сбои. Например, при асимметрии входящего и исходящего канала
|
можно, включая магистралов. Но потенциально может давать сбои. Например, при асимметрии входящего и исходящего канала
|
||||||
до конкретного сервера. Некоторые сервера выдают нестандартный TTL (google), потому на них получается полная ерунда.
|
до конкретного сервера. На каких-то провайдерах эта техника будет работать неплохо, на других доставит больше проблем,
|
||||||
Если не учитывать подобные исключения, то на каких-то провайдерах эта техника будет работать неплохо, на других доставит больше проблем,
|
|
||||||
чем пользы. Где-то может потребоваться тюнинг параметров. Лучше использовать с дополнительным ограничителем.
|
чем пользы. Где-то может потребоваться тюнинг параметров. Лучше использовать с дополнительным ограничителем.
|
||||||
|
|
||||||
Режимы дурения могут сочетаться в любых комбинациях. `--dpi-desync-fooling` берет множество значений через запятую.
|
Режимы дурения могут сочетаться в любых комбинациях. `--dpi-desync-fooling` берет множество значений через запятую.
|
||||||
@ -481,69 +450,16 @@ extension хедерам в поисках транспортного хедер
|
|||||||
При `hopbyhop,ipfrag2` последовательность хедеров будет : `ipv6,hop-by-hop`,`fragment`,`tcp/udp`.
|
При `hopbyhop,ipfrag2` последовательность хедеров будет : `ipv6,hop-by-hop`,`fragment`,`tcp/udp`.
|
||||||
Режим `ipfrag1` может срабатывать не всегда без специальной подготовки. См. раздел `IP фрагментация`.
|
Режим `ipfrag1` может срабатывать не всегда без специальной подготовки. См. раздел `IP фрагментация`.
|
||||||
|
|
||||||
### МОДИФИКАЦИЯ ОРИГИНАЛА
|
|
||||||
|
|
||||||
Параметры `--orig-ttl` и `--orig-ttl6` позволяют изменить TTL оригинальных пакетов.
|
|
||||||
Если дальнейшие манипуляции связаны с оригиналом, например, идет TCP сегментация, то исходными
|
|
||||||
данными являются измененные оригинальные пакеты. То есть в данном примере TCP сегменты пойдут с измененным TTL.
|
|
||||||
|
|
||||||
Вариант `--orig-autottl` и `--orig-autottl6` работает аналогично `dpi-desync-autottl`, но по оригинальным пакетам.
|
|
||||||
Дельту стоит указывать положительную с унарным знаком `+`, иначе оригинал не дойдет до сервера, и вы вообще ничего не получите.
|
|
||||||
Пример : `--orig-autottl=+5:3-64`.
|
|
||||||
|
|
||||||
`--orig-mod-start` и `--orig-mod-cutoff` задают ограничитель по началу и концу модификации оригинала.
|
|
||||||
Схема аналогична `--dpi-desync-start` и `--dpi-desync-cutoff`.
|
|
||||||
|
|
||||||
Функция может быть полезна, когда DPI охотится за фейками и блокирует соединение при наличии подозрительных признаков,
|
|
||||||
в частности, измененный TTL у фейка относительно оригинала.
|
|
||||||
|
|
||||||
### ДУБЛИКАТЫ
|
|
||||||
|
|
||||||
Дубликаты - это копии оригинальных пакетов, высылаемые перед ними. Включаются параметром `--dup=N`, где N - количество дублей,
|
|
||||||
не включающее оригинал. `--dup-replace` отключает отсылку оригинала.
|
|
||||||
|
|
||||||
Отсылка дублей имеет место только в тех случаях, когда высылается и оригинал без реконструкции.
|
|
||||||
Например, если случилась TCP сегментация, то оригинал фактически дропается и заменяется искусственно сконструированными сегментами.
|
|
||||||
Дубли высланы не будут. Это же касается изменения состава хедеров ipv6, режима tamper для DHT и других.
|
|
||||||
|
|
||||||
Возможно применение всех вариантов дурения, как и для desync : `--dup-ttl`. `--dup-ttl6`, `--dup-fooling`. Нужно ли, чтобы эти пакеты доходили до сервера и в каком виде, решаете вы согласно задуманной стратегии.
|
|
||||||
|
|
||||||
Вариант `--dup-autottl` и `--dup-autottl6` работает аналогично `dpi-desync-autottl`, но по дублям.
|
|
||||||
Дельту можно указывать положительную с унарным знаком `+`, а можно и отрицательную. Зависит от вашей задумки.
|
|
||||||
Пример : `--dup-autottl=-2:3-64`.
|
|
||||||
|
|
||||||
`--dup-start` и `--dup-cutoff` задают ограничитель по началу и концу применения стратегии дубликатов.
|
|
||||||
Схема аналогична `--dpi-desync-start` и `--dpi-desync-cutoff`.
|
|
||||||
|
|
||||||
Функция может помочь, когда DPI сечет разницу в характеристиках фейков и оригинала.
|
|
||||||
Дубликатами можно попытаться заставить DPI принять , что весь сеанс идет аномальным.
|
|
||||||
Например, у нас имеется TCP сеанс с MD5 сразу с первого SYN пакета. Значит последующие MD5 будут восприниматься нормально.
|
|
||||||
|
|
||||||
### КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ
|
### КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ
|
||||||
|
|
||||||
В параметре dpi-desync можно указать до 3 режимов через запятую.
|
В параметре dpi-desync можно указать до 3 режимов через запятую.
|
||||||
|
|
||||||
* 0 фаза - предполагает работу на этапе установления соединения : `synack`, `syndata`, `--wsize`, `--wssize`. На эту фазу не действуют фильтры по [hostlist](#множественные-стратегии), кроме случая, описанного [далее](#кэш-ip).
|
* 0 фаза - предполагает работу на этапе установления соединения : `synack`, `syndata`, `--wsize`, `--wssize`. На эту фазу не действуют фильтры по [hostlist](#множественные-стратегии).
|
||||||
* 1 фаза - отсылка чего-либо до оригинального пакета данных : `fake`, `rst`, `rstack`.
|
* 1 фаза - отсылка чего-либо до оригинального пакета данных : `fake`, `rst`, `rstack`.
|
||||||
* 2 фаза - отсылка в модифицированном виде оригинального пакета данных (например, `fakedsplit` или `ipfrag2`).
|
* 2 фаза - отсылка в модифицированном виде оригинального пакета данных (например, `fakedsplit` или `ipfrag2`).
|
||||||
|
|
||||||
Режимы требуют указания в порядке возрастания номеров фаз.
|
Режимы требуют указания в порядке возрастания номеров фаз.
|
||||||
|
|
||||||
### КЭШ IP
|
|
||||||
|
|
||||||
ipcache представляет собой структуру в памяти процесса, позволяющую по ключу IP адреса и имени интерфейса запоминать некоторую информацию,
|
|
||||||
которую впоследствии можно извлечь и использовать как недостающие данные. На текущий момент это применяются в следующих ситуациях :
|
|
||||||
|
|
||||||
1. IP,interface => hop count . Кэшируется количество хопов до сервера для последующего применения в autottl прямо с первого пакета, когда еще ответа не было. Пока записи в кэше нет, autottl не будет применен сразу. При повторном запросе до истечения времени жизни записи autottl будет применение сразу.
|
|
||||||
|
|
||||||
2. IP => hostname . Кэшируется имя хоста, вне привязки к интерфейсу, для последующего применения в стратегиях нулевой фазы. Режим отключен по умолчанию и включается через параметры `ipcache-hostname`.
|
|
||||||
Данная техника является экспериментальной. Ее проблема в том, что как такового нет однозначного соответствия между доменом и IP. Множество доменов могут ссылаться на тот же IP адрес.
|
|
||||||
При коллизии происходит замещение имени хоста на последний вариант.
|
|
||||||
Домен может скакать по разным IP на CDN. Сейчас один адрес, через час - другой. Эта проблема решается через время жизни записей кэша : `--ipcache-lifetime`. По умолчанию 2 часа.
|
|
||||||
Однако, может случиться и так, что в вашем случае применение техники несет больше пользы, чем проблем. Будьте готовы к непонятному на первый взгляд поведению, которое может быть исследовано только через `--debug` лог.
|
|
||||||
|
|
||||||
При подаче сигнала SIGUSR2 процесс выводит содержимое ipcache на консоль.
|
|
||||||
|
|
||||||
### РЕАКЦИЯ DPI НА ОТВЕТ СЕРВЕРА
|
### РЕАКЦИЯ DPI НА ОТВЕТ СЕРВЕРА
|
||||||
|
|
||||||
Есть DPI, которые анализируют ответы от сервера, в частности сертификат из ServerHello, где прописаны домены.
|
Есть DPI, которые анализируют ответы от сервера, в частности сертификат из ServerHello, где прописаны домены.
|
||||||
@ -887,32 +803,6 @@ iptables target `FLOWOFFLOAD` - это проприетарное изобрет
|
|||||||
Управление offload в nftables реализовано в базовом ядре linux без патчей.
|
Управление offload в nftables реализовано в базовом ядре linux без патчей.
|
||||||
nftables - единственный способ включения offload на классическом Linux.
|
nftables - единственный способ включения offload на классическом Linux.
|
||||||
|
|
||||||
### ДУРЕНИЕ СО СТОРОНЫ СЕРВЕРА
|
|
||||||
|
|
||||||
Это тоже возможно.
|
|
||||||
nfqws рассчитан на атаку со стороны клиента, поэтому он распознает прямой и обратный трафик на основании роли в установлении tcp соединения.
|
|
||||||
Если проходит SYN, то source IP - это клиент. Если проходит SYN,ACK , то source IP - это сервер.
|
|
||||||
Для UDP клиентом считается source IP первого прошедшего пакета по двум связкам ip-port.
|
|
||||||
На сервере трафиком клиента будет считаться принятый трафик, а трафиком сервера - исходящий.
|
|
||||||
|
|
||||||
`--wsize` работает в любом случае, он может использоваться как на клиенте, так и на сервере.
|
|
||||||
Остальные техники работают только если nfqws считает трафик трафиком клиента.
|
|
||||||
Поэтому для их применения по исходящему с сервера трафику conntrack нужно выключить параметром `--ctrack-disable`.
|
|
||||||
Если пакет не найден в conntrack, по нему идет работа как по пакету клиента.
|
|
||||||
|
|
||||||
Большинство протоколов опознаваться не будет, потому что система их опознавания рассчитана на содержание пакетов от клиента.
|
|
||||||
Чтобы задействовать техники типа `fake` или `multisplit` нужно использовать `--dpi-desync-any-protocol` с ограничителем connbytes или
|
|
||||||
с ограничителем на основании содержания пакета или его заголовков.
|
|
||||||
start/cutoff недоступны, поскольку завязаны на conntrack.
|
|
||||||
|
|
||||||
Техника `synack-split` позволяет разбить tcp сегмент SYN,ACK на отдельные части с SYN и с ACK.
|
|
||||||
В ответ на это клиент шлет SYN,ACK , что обычно характеризует сервер.
|
|
||||||
У некоторых DPI от этого может ломаться алгоритм, и они перестают блокировать запрещенный контент.
|
|
||||||
Здесь [подробное описание](https://nmap.org/misc/split-handshake.pdf) что есть split handshake.
|
|
||||||
|
|
||||||
Перенаправление трафика обычно идет по номеру source портов и направлению original.
|
|
||||||
original - это исходящий с системы трафик, reply - входящий.
|
|
||||||
|
|
||||||
|
|
||||||
## tpws
|
## tpws
|
||||||
|
|
||||||
@ -971,8 +861,6 @@ tpws - это transparent proxy.
|
|||||||
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
|
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
|
||||||
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
|
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
|
||||||
--fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс.
|
--fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс.
|
||||||
--ipcache-lifetime=<int> ; время жизни записей кэша IP в секундах. 0 - без ограничений.
|
|
||||||
--ipcache-hostname=[0|1] ; 1 или отсутствие аргумента включают кэширование имен хостов для применения в стратегиях нулевой фазы
|
|
||||||
|
|
||||||
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
|
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
|
||||||
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
|
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
|
||||||
@ -1094,9 +982,9 @@ tpws работает на уровне сокетов, поэтому длин
|
|||||||
шлет сервер. На TLS 1.2 если сервер разбил заброс так, чтобы домен из сертификата не попал в первый пакет,
|
шлет сервер. На TLS 1.2 если сервер разбил заброс так, чтобы домен из сертификата не попал в первый пакет,
|
||||||
это может обмануть DPI, секущий ответ сервера.
|
это может обмануть DPI, секущий ответ сервера.
|
||||||
Схема может значительно снизить скорость и сработать не на всех сайтах.
|
Схема может значительно снизить скорость и сработать не на всех сайтах.
|
||||||
|
С фильтром по hostlist совместимо только в режиме socks при включенном удаленном ресолвинге хостов.
|
||||||
С фильтром по hostlist совместимо только в [некоторых случаях](#множественные-стратегии-1), когда возможно узнать имя хоста на момент применения дурения.
|
(firefox network.proxy.socks_remote_dns). Это единственный вариант, когда tpws может узнать имя хоста
|
||||||
|
еще на этапе установления соединения.
|
||||||
Применяя данную опцию к сайтам TLS1.3, если броузер тоже поддерживает TLS1.3, то вы делаете только хуже.
|
Применяя данную опцию к сайтам TLS1.3, если броузер тоже поддерживает TLS1.3, то вы делаете только хуже.
|
||||||
Но нет способа автоматически узнать когда надо применять, когда нет, поскольку MSS идет только в
|
Но нет способа автоматически узнать когда надо применять, когда нет, поскольку MSS идет только в
|
||||||
3-way handshake еще до обмена данными, а версию TLS можно узнать только по ответу сервера, который
|
3-way handshake еще до обмена данными, а версию TLS можно узнать только по ответу сервера, который
|
||||||
@ -1120,17 +1008,14 @@ tpws работает на уровне сокетов, поэтому длин
|
|||||||
|
|
||||||
Работают аналогично **nfqws**, кроме некоторых моментов.
|
Работают аналогично **nfqws**, кроме некоторых моментов.
|
||||||
Нет параметра `--filter-udp`, поскольку **tpws** udp не поддерживает.
|
Нет параметра `--filter-udp`, поскольку **tpws** udp не поддерживает.
|
||||||
Методы нулевой фазы (`--mss`) могут работать по хостлисту только в двух случаях:
|
Методы нулевой фазы (`--mss`) могут работать по хостлисту в одном единственном случае:
|
||||||
если используется режим socks и удаленный ресолвинг хостов через прокси, либо используется система [кэша IP](#кэш-ip) для запоминания соответствия IP->hostname.
|
если используется режим socks и удаленный ресолвинг хостов через прокси.
|
||||||
Работоспособность вашей настройки в одном и том же режиме может зависеть от того,
|
То есть работоспособность вашей настройки в одном и том же режиме может зависеть от того,
|
||||||
применяет ли клиент удаленный ресолвинг. Это может быть неочевидно. В одной программе работает, в другой - нет.
|
применяет ли клиент удаленный ресолвинг. Это может быть неочевидно.
|
||||||
|
В одной программе работает, в другой - нет.
|
||||||
Если вы используете профиль с хостлистом , и вам нужен mss всегда, укажите mss в профиле с хостлистом,
|
Если вы используете профиль с хостлистом , и вам нужен mss, укажите mss в профиле с хостлистом,
|
||||||
создайте еще один профиль без хостлиста, если его еще нет, и в нем еще раз укажите mss.
|
создайте еще один профиль без хостлиста, если его еще нет, и в нем еще раз укажите mss.
|
||||||
Тогда при любом раскладе будет выполняться mss.
|
Тогда при любом раскладе будет выполняться mss.
|
||||||
|
|
||||||
Если вам нужен mss по хостлисту, указывайте `--mss` только в профиле с хостлистом и убедитесь в наличии любого из необходимых условий работы в таком режиме.
|
|
||||||
|
|
||||||
Используйте `curl --socks5` и `curl --socks5-hostname` для проверки вашей стратегии.
|
Используйте `curl --socks5` и `curl --socks5-hostname` для проверки вашей стратегии.
|
||||||
Смотрите вывод `--debug`, чтобы убедиться в правильности настроек.
|
Смотрите вывод `--debug`, чтобы убедиться в правильности настроек.
|
||||||
|
|
||||||
@ -1621,10 +1506,8 @@ SKIP_DNSCHECK=1 - отказ от проверки DNS
|
|||||||
SKIP_IPBLOCK=1 - отказ от тестов блокировки по порту или IP
|
SKIP_IPBLOCK=1 - отказ от тестов блокировки по порту или IP
|
||||||
SKIP_TPWS=1 - отказ от тестов tpws
|
SKIP_TPWS=1 - отказ от тестов tpws
|
||||||
SKIP_PKTWS=1 - отказ от тестов nfqws/dvtws/winws
|
SKIP_PKTWS=1 - отказ от тестов nfqws/dvtws/winws
|
||||||
PKTWS_EXTRA, TPWS_EXTRA - дополнительные параметры nfqws/dvtws/winws и tpws, указываемые после основной стратегии
|
PKTWS_EXTRA, TPWS_EXTRA - дополнительные параметры nfqws/dvtws/winws и tpws
|
||||||
PKTWS_EXTRA_1 .. PKTWS_EXTRA_9, TPWS_EXTRA_1 .. TPWS_EXTRA_9 - отдельно дополнительные параметры, содержащие пробелы
|
PKTWS_EXTRA_1 .. PKTWS_EXTRA_9, TPWS_EXTRA_1 .. TPWS_EXTRA_9 - отдельно дополнительные параметры, содержащие пробелы
|
||||||
PKTWS_EXTRA_PRE - дополнительные параметры для nfqws/dvtws/winws, указываемые перед основной стратегией
|
|
||||||
PKTWS_EXTRA_PRE_1 .. PKTWS_EXTRA_PRE_9 - отдельно дополнительные параметры, содержащие пробелы
|
|
||||||
SECURE_DNS=0|1 - принудительно выключить или включить DoH
|
SECURE_DNS=0|1 - принудительно выключить или включить DoH
|
||||||
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
|
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
|
||||||
DOH_SERVER - конкретный DoH URL, отказ от поиска
|
DOH_SERVER - конкретный DoH URL, отказ от поиска
|
||||||
@ -1777,16 +1660,13 @@ nfqws начнет получать адреса пакетов из локал
|
|||||||
Каждая опция предполагает запуск одного инстанса соответствующего демона. Все различия методов дурения
|
Каждая опция предполагает запуск одного инстанса соответствующего демона. Все различия методов дурения
|
||||||
для `http`, `https`, `quic` и т.д. должны быть отражены через схему мультистратегий.
|
для `http`, `https`, `quic` и т.д. должны быть отражены через схему мультистратегий.
|
||||||
В этом смысле настройка похожа на вариант `winws` на Windows, а перенос конфигов не должен представлять больших сложностей.
|
В этом смысле настройка похожа на вариант `winws` на Windows, а перенос конфигов не должен представлять больших сложностей.
|
||||||
|
|
||||||
Основное правило настройки перехвата - перехватывайте только необходимый минимум.
|
Основное правило настройки перехвата - перехватывайте только необходимый минимум.
|
||||||
Любой перехват лишнего - это бессмысленная нагрузка на вашу систему.
|
Любой перехват лишнего - это бессмысленная нагрузка на вашу систему.
|
||||||
Опции демонов `--ipset` использовать нужно с умом. Не стоит перехватывать весь трафик, чтобы потом по параметру --ipset
|
Опции демонов `--ipset` использовать запрещено. Это сделано намеренно и искусственно, чтобы не поощрять простой и
|
||||||
выделить лишь горстку IP. Это будет работать, но очень неэффективно с точки зрения нагрузки на систему.
|
работающий, но неэффективный метод на *nix системах. Используйте `ipset`-ы режима ядра.
|
||||||
Используйте `ipset`-ы режима ядра. При необходимости пишите и задействуйте `custom scripts`.
|
При необходимости пишите и задействуйте `custom scripts`.
|
||||||
Но если у вас и так идет работа по всем IP, и нужно написать небольшую специализацию по IP, то --ipset вполне уместен.
|
|
||||||
|
|
||||||
Настройки демонов можно для удобства писать на нескольких строках, используя двойные или одинарные кавычки.
|
Настройки демонов можно для удобства писать на нескольких строках, используя двойные или одинарные кавычки.
|
||||||
Чтобы задействовать стандартные обновляемые хост-листы из каталога `ipset`, используйте маркер <HOSTLIST>.
|
Чтобы задействовать стандартные обновляемые хост-листы из `ipset`, используйте маркер <HOSTLIST>.
|
||||||
Он будет заменен на параметры, соответствующие режиму MODE_FILTER, и будут подставлены реально существующие файлы.
|
Он будет заменен на параметры, соответствующие режиму MODE_FILTER, и будут подставлены реально существующие файлы.
|
||||||
Если MODE_FILTER не предполагает стандартного хостлиста, <HOSTLIST> будет заменен на пустую строку.
|
Если MODE_FILTER не предполагает стандартного хостлиста, <HOSTLIST> будет заменен на пустую строку.
|
||||||
Стандартные хостлисты следует вставлять в финальных стратегиях (стратегиях по умолчанию), закрывающих цепочки по
|
Стандартные хостлисты следует вставлять в финальных стратегиях (стратегиях по умолчанию), закрывающих цепочки по
|
||||||
@ -1880,7 +1760,7 @@ hardware: выборочное управление включено в режи
|
|||||||
```
|
```
|
||||||
`FLOWOFFLOAD=donttouch`
|
`FLOWOFFLOAD=donttouch`
|
||||||
|
|
||||||
Параметр `GETLIST` указывает инсталлятору `install_easy.sh` какой скрипт дергать
|
Параметр GETLIST указывает инсталлятору `install_easy.sh` какой скрипт дергать
|
||||||
для обновления списка заблокированных ip или хостов.
|
для обновления списка заблокированных ip или хостов.
|
||||||
Он же вызывается через `get_config.sh` из запланированных заданий (crontab или systemd timer).
|
Он же вызывается через `get_config.sh` из запланированных заданий (crontab или systemd timer).
|
||||||
Поместите сюда название скрипта, который будете использовать для обновления листов.
|
Поместите сюда название скрипта, который будете использовать для обновления листов.
|
||||||
@ -1967,18 +1847,11 @@ OPENWRT_WAN4="wan4 vpn"
|
|||||||
OPENWRT_WAN6="wan6 vpn6"
|
OPENWRT_WAN6="wan6 vpn6"
|
||||||
```
|
```
|
||||||
|
|
||||||
Параметр `INIT_APPLY_FW=1` разрешает init скрипту самостоятельно применять правила iptables.\
|
Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.\
|
||||||
При иных значениях или если параметр закомментирован, правила применены не будут.\
|
При иных значениях или если параметр закомментирован, правила применены не будут.\
|
||||||
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.\
|
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.\
|
||||||
На OpenWrt неприменимо при использовании firewall3+iptables.
|
На OpenWrt неприменимо при использовании firewall3+iptables.
|
||||||
|
|
||||||
`FILTER_TTL_EXPIRED_ICMP=1` включает механизмы блокировки пакетов icmp time exceeded, высылаемые роутерами по пути следования пакета в ответ на исчерпание TTL/HL.
|
|
||||||
В linux соединение обрывается системой, если в ответ на первый пакет (для tcp - SYN) пришел такой icmp. Аналогичная схема имеется и в datagram сокетах.
|
|
||||||
Блокировка icmp идет исключительно за счет средств iptables/nftables.
|
|
||||||
Чтобы не трогать весь трафик, в режиме PRENAT используется connmark для пометки сеансов, над которыми поработал nfqws. В режиме POSTNAT так сделать нельзя,
|
|
||||||
поэтому помечаются все сеансы, заворачиваемые на nfqws.
|
|
||||||
Настройку лучше отключить, если вы не ожидаете проблем от icmp, тк в этом случае будет меньше ненужных вмешательств в трафик.
|
|
||||||
|
|
||||||
***Следующие настройки не актуальны для openwrt:***
|
***Следующие настройки не актуальны для openwrt:***
|
||||||
|
|
||||||
Если ваша система работает как роутер, то нужно вписать названия внутренних и внешних интерфейсов:
|
Если ваша система работает как роутер, то нужно вписать названия внутренних и внешних интерфейсов:
|
||||||
|
@ -1,29 +1,19 @@
|
|||||||
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
|
# this custom script demonstrates how to launch extra nfqws instance limited by ipset. ipv4 only.
|
||||||
|
|
||||||
# can override in config :
|
# can override in config :
|
||||||
NFQWS_MY1_OPT="${NFQWS_MY1_OPT:---filter-udp=* --dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-any-protocol --new --filter-tcp=* --dpi-desync=multisplit}"
|
NFQWS_OPT_DESYNC_NFQWS_MY1="${NFQWS_OPT_DESYNC_NFQWS_MY1:---dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-any-protocol}"
|
||||||
NFQWS_MY1_SUBNETS4="${NFQWS_MY1_SUBNETS4:-173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 64.233.160.0/19 172.217.0.0/16}"
|
NFQWS_MY1_PORTS=${NFQWS_MY1_PORTS:-6000-6009}
|
||||||
NFQWS_MY1_SUBNETS6="${NFQWS_MY1_SUBNETS6:-2a00:1450::/29}"
|
NFQWS_MY1_SUBNETS="${NFQWS_MY1_SUBNETS:-34.0.48.0/21 34.0.56.0/23 34.0.59.0/24 34.0.60.0/24 34.0.62.0/23}"
|
||||||
NFQWS_MY1_PORTS_TCP=${NFQWS_MY1_PORTS_TCP:-$NFQWS_PORTS_TCP}
|
|
||||||
NFQWS_MY1_PORTS_UDP=${NFQWS_MY1_PORTS_UDP:-$NFQWS_PORTS_UDP}
|
|
||||||
NFQWS_MY1_TCP_PKT_OUT=${NFQWS_MY1_TCP_PKT_OUT:-$NFQWS_TCP_PKT_OUT}
|
|
||||||
NFQWS_MY1_UDP_PKT_OUT=${NFQWS_MY1_UDP_PKT_OUT:-$NFQWS_UDP_PKT_OUT}
|
|
||||||
NFQWS_MY1_TCP_PKT_IN=${NFQWS_MY1_TCP_PKT_IN:-$NFQWS_TCP_PKT_IN}
|
|
||||||
NFQWS_MY1_UDP_PKT_IN=${NFQWS_MY1_UDP_PKT_IN:-$NFQWS_UDP_PKT_IN}
|
|
||||||
|
|
||||||
NFQWS_MY1_IPSET_SIZE=${NFQWS_MY1_IPSET_SIZE:-4096}
|
|
||||||
NFQWS_MY1_IPSET_OPT="${NFQWS_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS_MY1_IPSET_SIZE}"
|
|
||||||
|
|
||||||
alloc_dnum DNUM_NFQWS_MY1
|
alloc_dnum DNUM_NFQWS_MY1
|
||||||
alloc_qnum QNUM_NFQWS_MY1
|
alloc_qnum QNUM_NFQWS_MY1
|
||||||
NFQWS_MY1_NAME4=my1nfqws4
|
NFQWS_MY1_SET_NAME=my1nfqws4
|
||||||
NFQWS_MY1_NAME6=my1nfqws6
|
|
||||||
|
|
||||||
zapret_custom_daemons()
|
zapret_custom_daemons()
|
||||||
{
|
{
|
||||||
# $1 - 1 - run, 0 - stop
|
# $1 - 1 - run, 0 - stop
|
||||||
|
|
||||||
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_MY1_OPT"
|
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_OPT_DESYNC_NFQWS_MY1"
|
||||||
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
|
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,114 +21,54 @@ zapret_custom_firewall()
|
|||||||
{
|
{
|
||||||
# $1 - 1 - run, 0 - stop
|
# $1 - 1 - run, 0 - stop
|
||||||
|
|
||||||
local f4 f6 subnet
|
local f
|
||||||
local NFQWS_MY1_PORTS_TCP=$(replace_char - : $NFQWS_MY1_PORTS_TCP)
|
local first_packets_only="$ipt_connbytes 1:3"
|
||||||
local NFQWS_MY1_PORTS_UDP=$(replace_char - : $NFQWS_MY1_PORTS_UDP)
|
local NFQWS_MY1_PORTS_IPT=$(replace_char - : $NFQWS_MY1_PORTS)
|
||||||
|
local dest_set="-m set --match-set $NFQWS_MY1_SET_NAME dst"
|
||||||
|
local subnet
|
||||||
|
|
||||||
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
|
local DISABLE_IPV6=1
|
||||||
ipset create $NFQWS_MY1_NAME4 $NFQWS_MY1_IPSET_OPT family inet 2>/dev/null
|
|
||||||
ipset flush $NFQWS_MY1_NAME4
|
[ "$1" = 1 ] && {
|
||||||
for subnet in $NFQWS_MY1_SUBNETS4; do
|
ipset create $NFQWS_MY1_SET_NAME hash:net hashsize 8192 maxelem 4096 2>/dev/null
|
||||||
echo add $NFQWS_MY1_NAME4 $subnet
|
ipset flush $NFQWS_MY1_SET_NAME
|
||||||
done | ipset -! restore
|
for subnet in $NFQWS_MY1_SUBNETS; do
|
||||||
}
|
echo add $NFQWS_MY1_SET_NAME $subnet
|
||||||
[ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && {
|
|
||||||
ipset create $NFQWS_MY1_NAME6 $NFQWS_MY1_IPSET_OPT family inet6 2>/dev/null
|
|
||||||
ipset flush $NFQWS_MY1_NAME6
|
|
||||||
for subnet in $NFQWS_MY1_SUBNETS6; do
|
|
||||||
echo add $NFQWS_MY1_NAME6 $subnet
|
|
||||||
done | ipset -! restore
|
done | ipset -! restore
|
||||||
}
|
}
|
||||||
|
|
||||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
f="-p udp -m multiport --dports $NFQWS_MY1_PORTS_IPT"
|
||||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
fw_nfqws_post $1 "$f $first_packets_only $dest_set" "" $QNUM_NFQWS_MY1
|
||||||
f4="-p tcp -m multiport --dports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_OUT -m set --match-set"
|
|
||||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
|
||||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
|
||||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
|
||||||
}
|
|
||||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
|
||||||
f4="-p tcp -m multiport --sports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_IN -m set --match-set"
|
|
||||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
|
||||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
|
||||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
|
||||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
|
||||||
f4="-p udp -m multiport --dports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_OUT -m set --match-set"
|
|
||||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
|
||||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
|
||||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
|
||||||
}
|
|
||||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
|
||||||
f4="-p udp -m multiport --sports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_IN -m set --match-set"
|
|
||||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
|
||||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
|
||||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ "$1" = 1 ] || {
|
[ "$1" = 1 ] || {
|
||||||
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null
|
ipset destroy $NFQWS_MY1_SET_NAME 2>/dev/null
|
||||||
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zapret_custom_firewall_nft()
|
zapret_custom_firewall_nft()
|
||||||
{
|
{
|
||||||
local f4 f6 subnets
|
# stop logic is not required
|
||||||
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
|
|
||||||
|
|
||||||
[ "$DISABLE_IPV4" != 1 ] && {
|
local f
|
||||||
make_comma_list subnets $NFQWS_MY1_SUBNETS4
|
local first_packets_only="$nft_connbytes 1-3"
|
||||||
nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
local dest_set="ip daddr @$NFQWS_MY1_SET_NAME"
|
||||||
nft_flush_set $NFQWS_MY1_NAME4
|
local subnets
|
||||||
nft_add_set_element $NFQWS_MY1_NAME4 "$subnets"
|
|
||||||
}
|
|
||||||
[ "$DISABLE_IPV6" != 1 ] && {
|
|
||||||
make_comma_list subnets $NFQWS_MY1_SUBNETS6
|
|
||||||
nft_create_set $NFQWS_MY1_NAME6 "type ipv6_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
|
||||||
nft_flush_set $NFQWS_MY1_NAME6
|
|
||||||
nft_add_set_element $NFQWS_MY1_NAME6 "$subnets"
|
|
||||||
}
|
|
||||||
|
|
||||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
local DISABLE_IPV6=1
|
||||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
|
||||||
f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)"
|
|
||||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
|
||||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
|
||||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
|
||||||
}
|
|
||||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
|
||||||
f4="tcp sport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_IN)"
|
|
||||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
|
||||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
|
||||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
|
||||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
|
||||||
f4="udp dport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_OUT)"
|
|
||||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
|
||||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
|
||||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
|
||||||
}
|
|
||||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
|
||||||
f4="udp sport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_IN)"
|
|
||||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
|
||||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
|
||||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
make_comma_list subnets $NFQWS_MY1_SUBNETS
|
||||||
|
nft_create_set $NFQWS_MY1_SET_NAME "type ipv4_addr; size 4096; auto-merge; flags interval;"
|
||||||
|
nft_flush_set $NFQWS_MY1_SET_NAME
|
||||||
|
nft_add_set_element $NFQWS_MY1_SET_NAME "$subnets"
|
||||||
|
|
||||||
|
f="udp dport {$NFQWS_MY1_PORTS}"
|
||||||
|
nft_fw_nfqws_post "$f $first_packets_only $dest_set" "" $QNUM_NFQWS_MY1
|
||||||
|
}
|
||||||
|
|
||||||
zapret_custom_firewall_nft_flush()
|
zapret_custom_firewall_nft_flush()
|
||||||
{
|
{
|
||||||
# this function is called after all nft fw rules are deleted
|
# this function is called after all nft fw rules are deleted
|
||||||
# however sets are not deleted. it's desired to clear sets here.
|
# however sets are not deleted. it's desired to clear sets here.
|
||||||
|
|
||||||
nft_del_set $NFQWS_MY1_NAME4 2>/dev/null
|
nft_del_set $NFQWS_MY1_SET_NAME 2>/dev/null
|
||||||
nft_del_set $NFQWS_MY1_NAME6 2>/dev/null
|
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ zapret_custom_firewall()
|
|||||||
|
|
||||||
local f4 f6 subnet
|
local f4 f6 subnet
|
||||||
local PORTS_IPT=$(replace_char - : $TPWS_MY1_PORTS)
|
local PORTS_IPT=$(replace_char - : $TPWS_MY1_PORTS)
|
||||||
|
local dest_set="-m set --match-set $TPWS_MY1_NAME4 dst"
|
||||||
|
|
||||||
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
|
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
|
||||||
ipset create $TPWS_MY1_NAME4 $TPWS_MY1_IPSET_OPT family inet 2>/dev/null
|
ipset create $TPWS_MY1_NAME4 $TPWS_MY1_IPSET_OPT family inet 2>/dev/null
|
||||||
@ -57,7 +58,7 @@ zapret_custom_firewall()
|
|||||||
|
|
||||||
zapret_custom_firewall_nft()
|
zapret_custom_firewall_nft()
|
||||||
{
|
{
|
||||||
local f4 f6 subnets
|
local f4 f6 subnet
|
||||||
|
|
||||||
[ "$DISABLE_IPV4" != 1 ] && {
|
[ "$DISABLE_IPV4" != 1 ] && {
|
||||||
make_comma_list subnets $TPWS_MY1_SUBNETS4
|
make_comma_list subnets $TPWS_MY1_SUBNETS4
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Example systemd service unit for nfqws. Adjust for your installation.
|
# Example systemd service unit for nfqws. Adjust for your installation.
|
||||||
|
|
||||||
# WARNING ! This unit requires to compile nfqws using `make systemd`
|
# WARNING ! This unit requires to compile nfqws using `make systemd`
|
||||||
# WARNING ! This makefile target enables special systemd notify support.
|
# WARNING ! This makefile target enabled special systemd notify support.
|
||||||
|
|
||||||
# PREPARE
|
# PREPARE
|
||||||
# install build depends
|
# install build depends
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Example systemd service unit for tpws. Adjust for your installation.
|
# Example systemd service unit for tpws. Adjust for your installation.
|
||||||
|
|
||||||
# WARNING ! This unit requires to compile tpws using `make systemd`
|
# WARNING ! This unit requires to compile tpws using `make systemd`
|
||||||
# WARNING ! This makefile target enables special systemd notify support.
|
# WARNING ! This makefile target enabled special systemd notify support.
|
||||||
|
|
||||||
# PREPARE
|
# PREPARE
|
||||||
# install build depends
|
# install build depends
|
||||||
|
@ -225,28 +225,6 @@ static void exithelp(void)
|
|||||||
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum opt_indices {
|
|
||||||
IDX_HELP,
|
|
||||||
IDX_H,
|
|
||||||
IDX_4,
|
|
||||||
IDX_6,
|
|
||||||
IDX_PREFIX_LENGTH,
|
|
||||||
IDX_V4_THRESHOLD,
|
|
||||||
IDX_V6_THRESHOLD,
|
|
||||||
IDX_LAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct option long_options[] = {
|
|
||||||
[IDX_HELP] = {"help", no_argument, 0, 0},
|
|
||||||
[IDX_H] = {"h", no_argument, 0, 0},
|
|
||||||
[IDX_4] = {"4", no_argument, 0, 0},
|
|
||||||
[IDX_6] = {"6", no_argument, 0, 0},
|
|
||||||
[IDX_PREFIX_LENGTH] = {"prefix-length", required_argument, 0, 0},
|
|
||||||
[IDX_V4_THRESHOLD] = {"v4-threshold", required_argument, 0, 0},
|
|
||||||
[IDX_V6_THRESHOLD] = {"v6-threshold", required_argument, 0, 0},
|
|
||||||
[IDX_LAST] = {NULL, 0, NULL, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
static void parse_params(int argc, char *argv[])
|
static void parse_params(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
@ -258,23 +236,33 @@ static void parse_params(int argc, char *argv[])
|
|||||||
params.pctdiv = DEFAULT_PCTDIV;
|
params.pctdiv = DEFAULT_PCTDIV;
|
||||||
params.v6_threshold = DEFAULT_V6_THRESHOLD;
|
params.v6_threshold = DEFAULT_V6_THRESHOLD;
|
||||||
|
|
||||||
|
const struct option long_options[] = {
|
||||||
|
{ "help",no_argument,0,0 },// optidx=0
|
||||||
|
{ "h",no_argument,0,0 },// optidx=1
|
||||||
|
{ "4",no_argument,0,0 },// optidx=2
|
||||||
|
{ "6",no_argument,0,0 },// optidx=3
|
||||||
|
{ "prefix-length",required_argument,0,0 },// optidx=4
|
||||||
|
{ "v4-threshold",required_argument,0,0 },// optidx=5
|
||||||
|
{ "v6-threshold",required_argument,0,0 },// optidx=6
|
||||||
|
{ NULL,0,NULL,0 }
|
||||||
|
};
|
||||||
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
|
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
|
||||||
{
|
{
|
||||||
if (v) exithelp();
|
if (v) exithelp();
|
||||||
switch (option_index)
|
switch (option_index)
|
||||||
{
|
{
|
||||||
case IDX_HELP:
|
case 0:
|
||||||
case IDX_H:
|
case 1:
|
||||||
PRINT_VER;
|
PRINT_VER;
|
||||||
exithelp();
|
exithelp();
|
||||||
break;
|
break;
|
||||||
case IDX_4:
|
case 2:
|
||||||
params.ipv6 = false;
|
params.ipv6 = false;
|
||||||
break;
|
break;
|
||||||
case IDX_6:
|
case 3:
|
||||||
params.ipv6 = true;
|
params.ipv6 = true;
|
||||||
break;
|
break;
|
||||||
case IDX_PREFIX_LENGTH:
|
case 4:
|
||||||
i = sscanf(optarg,"%u-%u",&plen1,&plen2);
|
i = sscanf(optarg,"%u-%u",&plen1,&plen2);
|
||||||
if (i == 1) plen2 = plen1;
|
if (i == 1) plen2 = plen1;
|
||||||
if (i<=0 || plen2<plen1 || !plen1 || !plen2)
|
if (i<=0 || plen2<plen1 || !plen1 || !plen2)
|
||||||
@ -283,7 +271,7 @@ static void parse_params(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDX_V4_THRESHOLD:
|
case 5:
|
||||||
i = sscanf(optarg, "%u/%u", ¶ms.pctmult, ¶ms.pctdiv);
|
i = sscanf(optarg, "%u/%u", ¶ms.pctmult, ¶ms.pctdiv);
|
||||||
if (i!=2 || params.pctdiv<2 || params.pctmult<1 || params.pctmult>=params.pctdiv)
|
if (i!=2 || params.pctdiv<2 || params.pctmult<1 || params.pctmult>=params.pctdiv)
|
||||||
{
|
{
|
||||||
@ -291,7 +279,7 @@ static void parse_params(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDX_V6_THRESHOLD:
|
case 6:
|
||||||
i = sscanf(optarg, "%u", ¶ms.v6_threshold);
|
i = sscanf(optarg, "%u", ¶ms.v6_threshold);
|
||||||
if (i != 1 || params.v6_threshold<1)
|
if (i != 1 || params.v6_threshold<1)
|
||||||
{
|
{
|
||||||
|
57
mdig/mdig.c
57
mdig/mdig.c
@ -467,38 +467,25 @@ static void exithelp(void)
|
|||||||
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum opt_indices {
|
|
||||||
IDX_HELP,
|
|
||||||
IDX_THREADS,
|
|
||||||
IDX_FAMILY,
|
|
||||||
IDX_VERBOSE,
|
|
||||||
IDX_STATS,
|
|
||||||
IDX_LOG_RESOLVED,
|
|
||||||
IDX_LOG_FAILED,
|
|
||||||
IDX_DNS_MAKE_QUERY,
|
|
||||||
IDX_DNS_PARSE_QUERY,
|
|
||||||
IDX_LAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct option long_options[] = {
|
|
||||||
[IDX_HELP] = {"help", no_argument, 0, 0},
|
|
||||||
[IDX_THREADS] = {"threads", required_argument, 0, 0},
|
|
||||||
[IDX_FAMILY] = {"family", required_argument, 0, 0},
|
|
||||||
[IDX_VERBOSE] = {"verbose", no_argument, 0, 0},
|
|
||||||
[IDX_STATS] = {"stats", required_argument, 0, 0},
|
|
||||||
[IDX_LOG_RESOLVED] = {"log-resolved", required_argument, 0, 0},
|
|
||||||
[IDX_LOG_FAILED] = {"log-failed", required_argument, 0, 0},
|
|
||||||
[IDX_DNS_MAKE_QUERY] = {"dns-make-query", required_argument, 0, 0},
|
|
||||||
[IDX_DNS_PARSE_QUERY] = {"dns-parse-query", no_argument, 0, 0},
|
|
||||||
[IDX_LAST] = {NULL, 0, NULL, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int r, v, option_index = 0;
|
int r, v, option_index = 0;
|
||||||
char fn1[256],fn2[256];
|
char fn1[256],fn2[256];
|
||||||
char dom[256];
|
char dom[256];
|
||||||
|
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
{"help",no_argument,0,0}, // optidx=0
|
||||||
|
{"threads",required_argument,0,0}, // optidx=1
|
||||||
|
{"family",required_argument,0,0}, // optidx=2
|
||||||
|
{"verbose",no_argument,0,0}, // optidx=3
|
||||||
|
{"stats",required_argument,0,0}, // optidx=4
|
||||||
|
{"log-resolved",required_argument,0,0}, // optidx=5
|
||||||
|
{"log-failed",required_argument,0,0}, // optidx=6
|
||||||
|
{"dns-make-query",required_argument,0,0}, // optidx=7
|
||||||
|
{"dns-parse-query",no_argument,0,0}, // optidx=8
|
||||||
|
{NULL,0,NULL,0}
|
||||||
|
};
|
||||||
|
|
||||||
memset(&glob, 0, sizeof(glob));
|
memset(&glob, 0, sizeof(glob));
|
||||||
*fn1 = *fn2 = *dom = 0;
|
*fn1 = *fn2 = *dom = 0;
|
||||||
glob.family = FAMILY4;
|
glob.family = FAMILY4;
|
||||||
@ -508,11 +495,11 @@ int main(int argc, char **argv)
|
|||||||
if (v) exithelp();
|
if (v) exithelp();
|
||||||
switch (option_index)
|
switch (option_index)
|
||||||
{
|
{
|
||||||
case IDX_HELP:
|
case 0: /* help */
|
||||||
PRINT_VER;
|
PRINT_VER;
|
||||||
exithelp();
|
exithelp();
|
||||||
break;
|
break;
|
||||||
case IDX_THREADS:
|
case 1: /* threads */
|
||||||
glob.threads = optarg ? atoi(optarg) : 0;
|
glob.threads = optarg ? atoi(optarg) : 0;
|
||||||
if (glob.threads <= 0 || glob.threads > 100)
|
if (glob.threads <= 0 || glob.threads > 100)
|
||||||
{
|
{
|
||||||
@ -520,7 +507,7 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDX_FAMILY:
|
case 2: /* family */
|
||||||
if (!strcmp(optarg, "4"))
|
if (!strcmp(optarg, "4"))
|
||||||
glob.family = FAMILY4;
|
glob.family = FAMILY4;
|
||||||
else if (!strcmp(optarg, "6"))
|
else if (!strcmp(optarg, "6"))
|
||||||
@ -533,25 +520,25 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDX_VERBOSE:
|
case 3: /* verbose */
|
||||||
glob.verbose = '\1';
|
glob.verbose = '\1';
|
||||||
break;
|
break;
|
||||||
case IDX_STATS:
|
case 4: /* stats */
|
||||||
glob.stats_every = optarg ? atoi(optarg) : 0;
|
glob.stats_every = optarg ? atoi(optarg) : 0;
|
||||||
break;
|
break;
|
||||||
case IDX_LOG_RESOLVED:
|
case 5: /* log-resolved */
|
||||||
strncpy(fn1,optarg,sizeof(fn1));
|
strncpy(fn1,optarg,sizeof(fn1));
|
||||||
fn1[sizeof(fn1)-1] = 0;
|
fn1[sizeof(fn1)-1] = 0;
|
||||||
break;
|
break;
|
||||||
case IDX_LOG_FAILED:
|
case 6: /* log-failed */
|
||||||
strncpy(fn2,optarg,sizeof(fn2));
|
strncpy(fn2,optarg,sizeof(fn2));
|
||||||
fn2[sizeof(fn2)-1] = 0;
|
fn2[sizeof(fn2)-1] = 0;
|
||||||
break;
|
break;
|
||||||
case IDX_DNS_MAKE_QUERY:
|
case 7: /* dns-make-query */
|
||||||
strncpy(dom,optarg,sizeof(dom));
|
strncpy(dom,optarg,sizeof(dom));
|
||||||
dom[sizeof(dom)-1] = 0;
|
dom[sizeof(dom)-1] = 0;
|
||||||
break;
|
break;
|
||||||
case IDX_DNS_PARSE_QUERY:
|
case 8: /* dns-parse-query */
|
||||||
return dns_parse_query();
|
return dns_parse_query();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,11 +143,8 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
}
|
}
|
||||||
else if (tcp_synack_segment(tcphdr))
|
else if (tcp_synack_segment(tcphdr))
|
||||||
{
|
{
|
||||||
// ignore SA dups
|
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
||||||
uint32_t seq0 = ntohl(tcphdr->th_ack)-1;
|
if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
|
||||||
if (t->state!=SYN && t->seq0!=seq0)
|
|
||||||
ConntrackReInitTrack(t); // erase current entry
|
|
||||||
if (!t->seq0) t->seq0 = seq0;
|
|
||||||
t->ack0 = ntohl(tcphdr->th_seq);
|
t->ack0 = ntohl(tcphdr->th_seq);
|
||||||
}
|
}
|
||||||
else if (tcphdr->th_flags & (TH_FIN|TH_RST))
|
else if (tcphdr->th_flags & (TH_FIN|TH_RST))
|
||||||
@ -341,8 +338,8 @@ void ConntrackPoolDump(const t_conntrack *p)
|
|||||||
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
|
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
|
||||||
t->track.seq_last, t->track.pos_orig,
|
t->track.seq_last, t->track.pos_orig,
|
||||||
t->track.ack_last, t->track.pos_reply);
|
t->track.ack_last, t->track.pos_reply);
|
||||||
printf(" req_retrans=%u cutoff=%u wss_cutoff=%u desync_cutoff=%u dup_cutoff=%u orig_cutoff=%u hostname=%s l7proto=%s\n",
|
printf(" req_retrans=%u cutoff=%u wss_cutoff=%u d_cutoff=%u hostname=%s l7proto=%s\n",
|
||||||
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff, t->track.b_dup_cutoff, t->track.b_orig_mod_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
|
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,16 +77,14 @@ typedef struct
|
|||||||
bool req_seq_present,req_seq_finalized,req_seq_abandoned;
|
bool req_seq_present,req_seq_finalized,req_seq_abandoned;
|
||||||
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
|
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
|
||||||
|
|
||||||
uint8_t incoming_ttl, desync_autottl, orig_autottl, dup_autottl;
|
uint8_t incoming_ttl, autottl;
|
||||||
bool b_autottl_discovered;
|
|
||||||
|
|
||||||
bool b_cutoff; // mark for deletion
|
bool b_cutoff; // mark for deletion
|
||||||
bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff;
|
bool b_wssize_cutoff, b_desync_cutoff;
|
||||||
|
|
||||||
t_l7proto l7proto;
|
t_l7proto l7proto;
|
||||||
bool l7proto_discovered;
|
bool l7proto_discovered;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
bool hostname_discovered;
|
|
||||||
bool hostname_ah_check; // should perform autohostlist checks
|
bool hostname_ah_check; // should perform autohostlist checks
|
||||||
|
|
||||||
t_reassemble reasm_orig;
|
t_reassemble reasm_orig;
|
||||||
|
153
nfq/darkmagic.c
153
nfq/darkmagic.c
@ -38,11 +38,6 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
|
|||||||
return htons(ntohs(netorder_value)+cpuorder_increment);
|
return htons(ntohs(netorder_value)+cpuorder_increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ip_has_df(const struct ip *ip)
|
|
||||||
{
|
|
||||||
return ip && !!(ntohs(ip->ip_off) & IP_DF);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
|
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
|
||||||
{
|
{
|
||||||
uint8_t *t = (uint8_t*)(tcp+1);
|
uint8_t *t = (uint8_t*)(tcp+1);
|
||||||
@ -88,22 +83,10 @@ bool tcp_has_fastopen(const struct tcphdr *tcp)
|
|||||||
opt = tcp_find_option((struct tcphdr*)tcp, 254);
|
opt = tcp_find_option((struct tcphdr*)tcp, 254);
|
||||||
return opt && opt[1]>=4 && opt[2]==0xF9 && opt[3]==0x89;
|
return opt && opt[1]>=4 && opt[2]==0xF9 && opt[3]==0x89;
|
||||||
}
|
}
|
||||||
uint16_t tcp_find_mss(struct tcphdr *tcp)
|
|
||||||
{
|
|
||||||
uint8_t *t = tcp_find_option(tcp,2);
|
|
||||||
return (t && t[1]==4) ? *(uint16_t*)(t+2) : 0;
|
|
||||||
}
|
|
||||||
bool tcp_has_sack(struct tcphdr *tcp)
|
|
||||||
{
|
|
||||||
uint8_t *t = tcp_find_option(tcp,4);
|
|
||||||
return !!t;
|
|
||||||
}
|
|
||||||
|
|
||||||
// n prefix (nsport, nwsize) means network byte order
|
// n prefix (nsport, nwsize) means network byte order
|
||||||
static void fill_tcphdr(
|
static void fill_tcphdr(
|
||||||
struct tcphdr *tcp, uint32_t fooling, uint8_t tcp_flags,
|
struct tcphdr *tcp, uint32_t fooling, uint8_t tcp_flags,
|
||||||
bool sack,
|
|
||||||
uint16_t nmss,
|
|
||||||
uint32_t nseq, uint32_t nack_seq,
|
uint32_t nseq, uint32_t nack_seq,
|
||||||
uint16_t nsport, uint16_t ndport,
|
uint16_t nsport, uint16_t ndport,
|
||||||
uint16_t nwsize, uint8_t scale_factor,
|
uint16_t nwsize, uint8_t scale_factor,
|
||||||
@ -133,27 +116,15 @@ static void fill_tcphdr(
|
|||||||
tcp_flags &= ~TH_ACK;
|
tcp_flags &= ~TH_ACK;
|
||||||
*((uint8_t*)tcp+13)= tcp_flags;
|
*((uint8_t*)tcp+13)= tcp_flags;
|
||||||
tcp->th_win = nwsize;
|
tcp->th_win = nwsize;
|
||||||
if (nmss)
|
|
||||||
{
|
|
||||||
tcpopt[t++] = 2; // kind
|
|
||||||
tcpopt[t++] = 4; // len
|
|
||||||
*(uint16_t*)(tcpopt+t) = nmss;
|
|
||||||
t+=2;
|
|
||||||
}
|
|
||||||
if (sack)
|
|
||||||
{
|
|
||||||
tcpopt[t++] = 4; // kind
|
|
||||||
tcpopt[t++] = 2; // len
|
|
||||||
}
|
|
||||||
if (fooling & FOOL_MD5SIG)
|
if (fooling & FOOL_MD5SIG)
|
||||||
{
|
{
|
||||||
tcpopt[t] = 19; // kind
|
tcpopt[0] = 19; // kind
|
||||||
tcpopt[t+1] = 18; // len
|
tcpopt[1] = 18; // len
|
||||||
*(uint32_t*)(tcpopt+t+2)=random();
|
*(uint32_t*)(tcpopt+2)=random();
|
||||||
*(uint32_t*)(tcpopt+t+6)=random();
|
*(uint32_t*)(tcpopt+6)=random();
|
||||||
*(uint32_t*)(tcpopt+t+10)=random();
|
*(uint32_t*)(tcpopt+10)=random();
|
||||||
*(uint32_t*)(tcpopt+t+14)=random();
|
*(uint32_t*)(tcpopt+14)=random();
|
||||||
t+=18;
|
t=18;
|
||||||
}
|
}
|
||||||
if (timestamps || (fooling & FOOL_TS))
|
if (timestamps || (fooling & FOOL_TS))
|
||||||
{
|
{
|
||||||
@ -174,12 +145,10 @@ static void fill_tcphdr(
|
|||||||
tcp->th_off += t>>2;
|
tcp->th_off += t>>2;
|
||||||
tcp->th_sum = 0;
|
tcp->th_sum = 0;
|
||||||
}
|
}
|
||||||
static uint16_t tcpopt_len(bool sack, bool mss, uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
|
static uint16_t tcpopt_len(uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
|
||||||
{
|
{
|
||||||
uint16_t t=0;
|
uint16_t t=0;
|
||||||
if (sack) t+=2;
|
if (fooling & FOOL_MD5SIG) t=18;
|
||||||
if (mss) t+=4;
|
|
||||||
if (fooling & FOOL_MD5SIG) t+=18;
|
|
||||||
if ((fooling & FOOL_TS) || timestamps) t+=10;
|
if ((fooling & FOOL_TS) || timestamps) t+=10;
|
||||||
if (scale_factor!=SCALE_NONE) t+=3;
|
if (scale_factor!=SCALE_NONE) t+=3;
|
||||||
return (t+3)&~3;
|
return (t+3)&~3;
|
||||||
@ -194,11 +163,11 @@ static void fill_udphdr(struct udphdr *udp, uint16_t nsport, uint16_t ndport, ui
|
|||||||
udp->uh_sum = 0;
|
udp->uh_sum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, bool DF, uint8_t ttl, uint8_t tos, uint16_t ip_id)
|
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl, uint8_t tos, uint16_t ip_id)
|
||||||
{
|
{
|
||||||
ip->ip_tos = tos;
|
ip->ip_tos = tos;
|
||||||
ip->ip_sum = 0;
|
ip->ip_sum = 0;
|
||||||
ip->ip_off = DF ? htons(IP_DF) : 0;
|
ip->ip_off = 0;
|
||||||
ip->ip_v = 4;
|
ip->ip_v = 4;
|
||||||
ip->ip_hl = 5;
|
ip->ip_hl = 5;
|
||||||
ip->ip_len = htons(pktlen);
|
ip->ip_len = htons(pktlen);
|
||||||
@ -221,13 +190,10 @@ static void fill_ip6hdr(struct ip6_hdr *ip6, const struct in6_addr *src, const s
|
|||||||
bool prepare_tcp_segment4(
|
bool prepare_tcp_segment4(
|
||||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
bool sack,
|
|
||||||
uint16_t nmss,
|
|
||||||
uint32_t nseq, uint32_t nack_seq,
|
uint32_t nseq, uint32_t nack_seq,
|
||||||
uint16_t nwsize,
|
uint16_t nwsize,
|
||||||
uint8_t scale_factor,
|
uint8_t scale_factor,
|
||||||
uint32_t *timestamps,
|
uint32_t *timestamps,
|
||||||
bool DF,
|
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
uint8_t tos,
|
uint8_t tos,
|
||||||
uint16_t ip_id,
|
uint16_t ip_id,
|
||||||
@ -237,7 +203,7 @@ bool prepare_tcp_segment4(
|
|||||||
const void *data, uint16_t len,
|
const void *data, uint16_t len,
|
||||||
uint8_t *buf, size_t *buflen)
|
uint8_t *buf, size_t *buflen)
|
||||||
{
|
{
|
||||||
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,fooling,timestamps,scale_factor);
|
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
|
||||||
uint16_t ip_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
|
uint16_t ip_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
|
||||||
uint16_t pktlen = sizeof(struct ip) + ip_payload_len;
|
uint16_t pktlen = sizeof(struct ip) + ip_payload_len;
|
||||||
if (pktlen>*buflen) return false;
|
if (pktlen>*buflen) return false;
|
||||||
@ -246,12 +212,12 @@ bool prepare_tcp_segment4(
|
|||||||
struct tcphdr *tcp = (struct tcphdr*)(ip+1);
|
struct tcphdr *tcp = (struct tcphdr*)(ip+1);
|
||||||
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
|
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_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, 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,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
|
||||||
|
|
||||||
memcpy(payload,data,len);
|
memcpy(payload,data,len);
|
||||||
tcp4_fix_checksum(tcp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
|
tcp4_fix_checksum(tcp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
|
||||||
if (fooling & FOOL_BADSUM) tcp->th_sum^=(uint16_t)(1+random()%0xFFFF);
|
if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
@ -260,8 +226,6 @@ bool prepare_tcp_segment4(
|
|||||||
bool prepare_tcp_segment6(
|
bool prepare_tcp_segment6(
|
||||||
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
|
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
|
||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
bool sack,
|
|
||||||
uint16_t nmss,
|
|
||||||
uint32_t nseq, uint32_t nack_seq,
|
uint32_t nseq, uint32_t nack_seq,
|
||||||
uint16_t nwsize,
|
uint16_t nwsize,
|
||||||
uint8_t scale_factor,
|
uint8_t scale_factor,
|
||||||
@ -274,7 +238,7 @@ bool prepare_tcp_segment6(
|
|||||||
const void *data, uint16_t len,
|
const void *data, uint16_t len,
|
||||||
uint8_t *buf, size_t *buflen)
|
uint8_t *buf, size_t *buflen)
|
||||||
{
|
{
|
||||||
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,fooling,timestamps,scale_factor);
|
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
|
||||||
uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
|
uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
|
||||||
uint16_t ip_payload_len = transport_payload_len +
|
uint16_t ip_payload_len = transport_payload_len +
|
||||||
8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) +
|
8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) +
|
||||||
@ -333,11 +297,11 @@ bool prepare_tcp_segment6(
|
|||||||
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
|
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_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,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
|
||||||
|
|
||||||
memcpy(payload,data,len);
|
memcpy(payload,data,len);
|
||||||
tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
|
tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
|
||||||
if (fooling & FOOL_BADSUM) tcp->th_sum^=(1+random()%0xFFFF);
|
if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
@ -346,13 +310,10 @@ bool prepare_tcp_segment6(
|
|||||||
bool prepare_tcp_segment(
|
bool prepare_tcp_segment(
|
||||||
const struct sockaddr *src, const struct sockaddr *dst,
|
const struct sockaddr *src, const struct sockaddr *dst,
|
||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
bool sack,
|
|
||||||
uint16_t nmss,
|
|
||||||
uint32_t nseq, uint32_t nack_seq,
|
uint32_t nseq, uint32_t nack_seq,
|
||||||
uint16_t nwsize,
|
uint16_t nwsize,
|
||||||
uint8_t scale_factor,
|
uint8_t scale_factor,
|
||||||
uint32_t *timestamps,
|
uint32_t *timestamps,
|
||||||
bool DF,
|
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
uint8_t tos,
|
uint8_t tos,
|
||||||
uint16_t ip_id,
|
uint16_t ip_id,
|
||||||
@ -364,9 +325,9 @@ bool prepare_tcp_segment(
|
|||||||
uint8_t *buf, size_t *buflen)
|
uint8_t *buf, size_t *buflen)
|
||||||
{
|
{
|
||||||
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
|
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,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
||||||
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
|
(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,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
||||||
false;
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,7 +335,6 @@ bool prepare_tcp_segment(
|
|||||||
// padlen<0 means payload shrinking
|
// padlen<0 means payload shrinking
|
||||||
bool prepare_udp_segment4(
|
bool prepare_udp_segment4(
|
||||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||||
bool DF,
|
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
uint8_t tos,
|
uint8_t tos,
|
||||||
uint16_t ip_id,
|
uint16_t ip_id,
|
||||||
@ -401,7 +361,7 @@ bool prepare_udp_segment4(
|
|||||||
uint8_t *payload = (uint8_t*)(udp+1);
|
uint8_t *payload = (uint8_t*)(udp+1);
|
||||||
|
|
||||||
|
|
||||||
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, DF, ttl, tos, ip_id);
|
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl, tos, ip_id);
|
||||||
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
|
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
|
||||||
|
|
||||||
memcpy(payload,data,len);
|
memcpy(payload,data,len);
|
||||||
@ -410,7 +370,7 @@ bool prepare_udp_segment4(
|
|||||||
else
|
else
|
||||||
memset(payload+len,0,padlen);
|
memset(payload+len,0,padlen);
|
||||||
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
|
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
|
||||||
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF);
|
if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
@ -499,14 +459,13 @@ bool prepare_udp_segment6(
|
|||||||
else
|
else
|
||||||
memset(payload+len,0,padlen);
|
memset(payload+len,0,padlen);
|
||||||
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
|
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
|
||||||
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF);
|
if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool prepare_udp_segment(
|
bool prepare_udp_segment(
|
||||||
const struct sockaddr *src, const struct sockaddr *dst,
|
const struct sockaddr *src, const struct sockaddr *dst,
|
||||||
bool DF,
|
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
uint8_t tos,
|
uint8_t tos,
|
||||||
uint16_t ip_id,
|
uint16_t ip_id,
|
||||||
@ -518,7 +477,7 @@ bool prepare_udp_segment(
|
|||||||
uint8_t *buf, size_t *buflen)
|
uint8_t *buf, size_t *buflen)
|
||||||
{
|
{
|
||||||
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
|
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
|
||||||
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,DF,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
|
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
|
||||||
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
|
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
|
||||||
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
|
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
|
||||||
false;
|
false;
|
||||||
@ -642,29 +601,10 @@ bool ip_frag(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
|
void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
|
||||||
{
|
{
|
||||||
if (ttl)
|
if (ip) ip->ip_ttl = ttl;
|
||||||
{
|
if (ip6) ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
|
||||||
if (ip)
|
|
||||||
{
|
|
||||||
if (ip->ip_ttl!=ttl)
|
|
||||||
{
|
|
||||||
ip->ip_ttl = ttl;
|
|
||||||
ip4_fix_checksum(ip);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ip6)
|
|
||||||
{
|
|
||||||
if (ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim!=ttl)
|
|
||||||
{
|
|
||||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1832,15 +1772,16 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t hop_count_guess(uint8_t ttl)
|
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
|
||||||
|
// ttl = TTL of incoming packet
|
||||||
|
uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
|
||||||
{
|
{
|
||||||
|
uint8_t orig, path, fake;
|
||||||
|
|
||||||
// 18.65.168.125 ( cloudfront ) 255
|
// 18.65.168.125 ( cloudfront ) 255
|
||||||
// 157.254.246.178 128
|
// 157.254.246.178 128
|
||||||
// 1.1.1.1 64
|
// 1.1.1.1 64
|
||||||
// guess original ttl. consider path lengths less than 32 hops
|
// guess original ttl. consider path lengths less than 32 hops
|
||||||
|
|
||||||
uint8_t orig;
|
|
||||||
|
|
||||||
if (ttl>223)
|
if (ttl>223)
|
||||||
orig=255;
|
orig=255;
|
||||||
else if (ttl<128 && ttl>96)
|
else if (ttl<128 && ttl>96)
|
||||||
@ -1850,21 +1791,13 @@ uint8_t hop_count_guess(uint8_t ttl)
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return orig - ttl;
|
path = orig - ttl;
|
||||||
}
|
|
||||||
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
|
|
||||||
uint8_t autottl_eval(uint8_t hop_count, const autottl *attl)
|
|
||||||
{
|
|
||||||
uint8_t fake;
|
|
||||||
int d;
|
|
||||||
|
|
||||||
d = (int)hop_count + attl->delta;
|
fake = path > attl->delta ? path - attl->delta : attl->min;
|
||||||
if (d<attl->min) fake=attl->min;
|
if (fake<attl->min) fake=attl->min;
|
||||||
else if (d>attl->max) fake=attl->max;
|
else if (fake>attl->max) fake=attl->max;
|
||||||
else fake=(uint8_t)d;
|
|
||||||
|
|
||||||
if (attl->delta<0 && fake>=hop_count || attl->delta>=0 && fake<hop_count)
|
if (fake>=path) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
return fake;
|
return fake;
|
||||||
}
|
}
|
||||||
@ -1916,15 +1849,15 @@ void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transpo
|
|||||||
{
|
{
|
||||||
if (!(verdict & VERDICT_NOCSUM))
|
if (!(verdict & VERDICT_NOCSUM))
|
||||||
{
|
{
|
||||||
#ifdef __CYGWIN__
|
|
||||||
// always fix csum for windivert. original can be partial or bad
|
// always fix csum for windivert. original can be partial or bad
|
||||||
if ((verdict & VERDICT_MASK)!=VERDICT_DROP)
|
#ifndef __CYGWIN__
|
||||||
#elif defined(__FreeBSD__)
|
#ifdef __FreeBSD__
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||||
#else
|
#else
|
||||||
// if original packet was tampered earlier it needs checksum fixed
|
// if original packet was tampered earlier it needs checksum fixed
|
||||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
|
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
|
||||||
}
|
}
|
||||||
@ -1933,15 +1866,15 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
|
|||||||
{
|
{
|
||||||
if (!(verdict & VERDICT_NOCSUM))
|
if (!(verdict & VERDICT_NOCSUM))
|
||||||
{
|
{
|
||||||
#ifdef __CYGWIN__
|
|
||||||
// always fix csum for windivert. original can be partial or bad
|
// always fix csum for windivert. original can be partial or bad
|
||||||
if ((verdict & VERDICT_MASK)!=VERDICT_DROP)
|
#ifndef __CYGWIN__
|
||||||
#elif defined(__FreeBSD__)
|
#ifdef __FreeBSD__
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||||
#else
|
#else
|
||||||
// if original packet was tampered earlier it needs checksum fixed
|
// if original packet was tampered earlier it needs checksum fixed
|
||||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
|
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
|
|||||||
#define VERDICT_DROP 2
|
#define VERDICT_DROP 2
|
||||||
#define VERDICT_MASK 3
|
#define VERDICT_MASK 3
|
||||||
#define VERDICT_NOCSUM 4
|
#define VERDICT_NOCSUM 4
|
||||||
#define VERDICT_GARBAGE 8
|
|
||||||
|
|
||||||
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
|
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
|
||||||
#define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
|
#define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
|
||||||
@ -69,13 +68,10 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
|
|||||||
bool prepare_tcp_segment4(
|
bool prepare_tcp_segment4(
|
||||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
bool sack,
|
|
||||||
uint16_t nmss,
|
|
||||||
uint32_t nseq, uint32_t nack_seq,
|
uint32_t nseq, uint32_t nack_seq,
|
||||||
uint16_t nwsize,
|
uint16_t nwsize,
|
||||||
uint8_t scale_factor,
|
uint8_t scale_factor,
|
||||||
uint32_t *timestamps,
|
uint32_t *timestamps,
|
||||||
bool DF,
|
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
uint8_t tos,
|
uint8_t tos,
|
||||||
uint16_t ip_id,
|
uint16_t ip_id,
|
||||||
@ -87,8 +83,6 @@ bool prepare_tcp_segment4(
|
|||||||
bool prepare_tcp_segment6(
|
bool prepare_tcp_segment6(
|
||||||
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
|
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
|
||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
bool sack,
|
|
||||||
uint16_t nmss,
|
|
||||||
uint32_t nseq, uint32_t nack_seq,
|
uint32_t nseq, uint32_t nack_seq,
|
||||||
uint16_t nwsize,
|
uint16_t nwsize,
|
||||||
uint8_t scale_factor,
|
uint8_t scale_factor,
|
||||||
@ -103,13 +97,10 @@ bool prepare_tcp_segment6(
|
|||||||
bool prepare_tcp_segment(
|
bool prepare_tcp_segment(
|
||||||
const struct sockaddr *src, const struct sockaddr *dst,
|
const struct sockaddr *src, const struct sockaddr *dst,
|
||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
bool sack,
|
|
||||||
uint16_t nmss,
|
|
||||||
uint32_t nseq, uint32_t nack_seq,
|
uint32_t nseq, uint32_t nack_seq,
|
||||||
uint16_t nwsize,
|
uint16_t nwsize,
|
||||||
uint8_t scale_factor,
|
uint8_t scale_factor,
|
||||||
uint32_t *timestamps,
|
uint32_t *timestamps,
|
||||||
bool DF,
|
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
uint8_t tos,
|
uint8_t tos,
|
||||||
uint16_t ip_id,
|
uint16_t ip_id,
|
||||||
@ -123,7 +114,6 @@ bool prepare_tcp_segment(
|
|||||||
|
|
||||||
bool prepare_udp_segment4(
|
bool prepare_udp_segment4(
|
||||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||||
bool DF,
|
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
uint8_t tos,
|
uint8_t tos,
|
||||||
uint16_t ip_id,
|
uint16_t ip_id,
|
||||||
@ -143,7 +133,6 @@ bool prepare_udp_segment6(
|
|||||||
uint8_t *buf, size_t *buflen);
|
uint8_t *buf, size_t *buflen);
|
||||||
bool prepare_udp_segment(
|
bool prepare_udp_segment(
|
||||||
const struct sockaddr *src, const struct sockaddr *dst,
|
const struct sockaddr *src, const struct sockaddr *dst,
|
||||||
bool DF,
|
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
uint8_t tos,
|
uint8_t tos,
|
||||||
uint16_t ip_id,
|
uint16_t ip_id,
|
||||||
@ -173,20 +162,15 @@ bool ip_frag(
|
|||||||
uint8_t *pkt1, size_t *pkt1_size,
|
uint8_t *pkt1, size_t *pkt1_size,
|
||||||
uint8_t *pkt2, size_t *pkt2_size);
|
uint8_t *pkt2, size_t *pkt2_size);
|
||||||
|
|
||||||
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl);
|
void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl);
|
||||||
|
|
||||||
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport);
|
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport);
|
||||||
void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
|
void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
|
||||||
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
|
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
|
||||||
uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
|
uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
|
||||||
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
|
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
|
||||||
uint16_t tcp_find_mss(struct tcphdr *tcp);
|
|
||||||
bool tcp_has_sack(struct tcphdr *tcp);
|
|
||||||
|
|
||||||
bool tcp_has_fastopen(const struct tcphdr *tcp);
|
bool tcp_has_fastopen(const struct tcphdr *tcp);
|
||||||
|
|
||||||
bool ip_has_df(const struct ip *ip);
|
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
extern uint32_t w_win32_error;
|
extern uint32_t w_win32_error;
|
||||||
|
|
||||||
@ -258,13 +242,15 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int8_t delta;
|
uint8_t delta, min, max;
|
||||||
uint8_t min, max;
|
|
||||||
} autottl;
|
} autottl;
|
||||||
#define AUTOTTL_ENABLED(a) ((a).delta || (a).min || (a).max)
|
#define AUTOTTL_DEFAULT_DELTA 1
|
||||||
|
#define AUTOTTL_DEFAULT_MIN 3
|
||||||
|
#define AUTOTTL_DEFAULT_MAX 20
|
||||||
|
#define AUTOTTL_ENABLED(a) (!!(a).delta)
|
||||||
|
#define AUTOTTL_SET_DEFAULT(a) {(a).delta=AUTOTTL_DEFAULT_DELTA; (a).min=AUTOTTL_DEFAULT_MIN; (a).max=AUTOTTL_DEFAULT_MAX;}
|
||||||
|
|
||||||
uint8_t hop_count_guess(uint8_t ttl);
|
uint8_t autottl_guess(uint8_t ttl, const autottl *attl);
|
||||||
uint8_t autottl_eval(uint8_t hop_count, const autottl *attl);
|
|
||||||
void do_nat(bool bOutbound, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *tcphdr, struct udphdr *udphdr, const struct sockaddr_in *target4, const struct sockaddr_in6 *target6);
|
void do_nat(bool bOutbound, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *tcphdr, struct udphdr *udphdr, const struct sockaddr_in *target4, const struct sockaddr_in6 *target6);
|
||||||
|
|
||||||
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
|
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
|
||||||
|
1024
nfq/desync.c
1024
nfq/desync.c
File diff suppressed because it is too large
Load Diff
@ -52,4 +52,4 @@ bool desync_valid_second_stage(enum dpi_desync_mode mode);
|
|||||||
bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode);
|
bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode);
|
||||||
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
|
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
|
||||||
|
|
||||||
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, uint8_t *data_pkt, size_t *len_pkt);
|
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt);
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define UNARY_PLUS(v) (v>0 ? "+" : "")
|
|
||||||
|
|
||||||
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
|
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
|
||||||
typedef union
|
typedef union
|
||||||
{
|
{
|
||||||
|
@ -287,13 +287,11 @@ static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostl
|
|||||||
}
|
}
|
||||||
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
|
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
if (filename && !file_mod_time(filename))
|
if (filename && !file_mod_time(filename))
|
||||||
{
|
{
|
||||||
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
|
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
return RegisterHostlist_(
|
return RegisterHostlist_(
|
||||||
¶ms.hostlists,
|
¶ms.hostlists,
|
||||||
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,
|
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,
|
||||||
|
1250
nfq/nfqws.c
1250
nfq/nfqws.c
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "packet_queue.h"
|
#include "packet_queue.h"
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
|
|||||||
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
|
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload)
|
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len,size_t len_payload)
|
||||||
{
|
{
|
||||||
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
|
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
|
||||||
if (!rp) return NULL;
|
if (!rp) return NULL;
|
||||||
@ -40,14 +39,13 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
|
|||||||
|
|
||||||
rp->dst = *dst;
|
rp->dst = *dst;
|
||||||
rp->fwmark = fwmark;
|
rp->fwmark = fwmark;
|
||||||
if (ifin)
|
|
||||||
snprintf(rp->ifin,sizeof(rp->ifin),"%s",ifin);
|
|
||||||
else
|
|
||||||
*rp->ifin = 0;
|
|
||||||
if (ifout)
|
if (ifout)
|
||||||
snprintf(rp->ifout,sizeof(rp->ifout),"%s",ifout);
|
{
|
||||||
|
strncpy(rp->ifout,ifout,sizeof(rp->ifout));
|
||||||
|
rp->ifout[sizeof(rp->ifout)-1]=0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
*rp->ifout = 0;
|
rp->ifout[0]=0;
|
||||||
memcpy(rp->packet,data,len);
|
memcpy(rp->packet,data,len);
|
||||||
rp->len=len;
|
rp->len=len;
|
||||||
rp->len_payload=len_payload;
|
rp->len_payload=len_payload;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
struct rawpacket
|
struct rawpacket
|
||||||
{
|
{
|
||||||
struct sockaddr_storage dst;
|
struct sockaddr_storage dst;
|
||||||
char ifin[IFNAMSIZ], ifout[IFNAMSIZ];
|
char ifout[IFNAMSIZ+1];
|
||||||
uint32_t fwmark;
|
uint32_t fwmark;
|
||||||
size_t len, len_payload;
|
size_t len, len_payload;
|
||||||
uint8_t *packet;
|
uint8_t *packet;
|
||||||
@ -21,6 +21,6 @@ void rawpacket_queue_init(struct rawpacket_tailhead *q);
|
|||||||
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
|
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
|
||||||
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
|
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
|
||||||
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
|
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
|
||||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload);
|
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len,size_t len_payload);
|
||||||
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
|
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
|
||||||
void rawpacket_free(struct rawpacket *rp);
|
void rawpacket_free(struct rawpacket *rp);
|
||||||
|
17
nfq/params.c
17
nfq/params.c
@ -187,10 +187,10 @@ void dp_init(struct desync_profile *dp)
|
|||||||
dp->desync_repeats = 1;
|
dp->desync_repeats = 1;
|
||||||
dp->fake_syndata_size = 16;
|
dp->fake_syndata_size = 16;
|
||||||
dp->wscale=-1; // default - dont change scale factor (client)
|
dp->wscale=-1; // default - dont change scale factor (client)
|
||||||
dp->desync_ttl6 = dp->dup_ttl6 = dp->orig_mod_ttl6 = 0xFF; // unused
|
dp->desync_ttl6 = 0xFF; // unused
|
||||||
dp->desync_badseq_increment = dp->dup_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
|
dp->desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
|
||||||
dp->desync_badseq_ack_increment = dp->dup_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
|
dp->desync_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
|
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = 'n'; // packet number by default
|
||||||
dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT;
|
dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT;
|
||||||
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||||
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||||
@ -294,12 +294,3 @@ bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// check if we need empty outgoing ACK
|
|
||||||
bool dp_list_need_all_out(struct desync_profile_list_head *head)
|
|
||||||
{
|
|
||||||
struct desync_profile_list *dpl;
|
|
||||||
LIST_FOREACH(dpl, head, next)
|
|
||||||
if (dpl->dp.dup_repeats || PROFILE_HAS_ORIG_MOD(&dpl->dp))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
52
nfq/params.h
52
nfq/params.h
@ -36,19 +36,6 @@
|
|||||||
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
||||||
#define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3
|
#define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3
|
||||||
|
|
||||||
#define IPCACHE_LIFETIME 7200
|
|
||||||
|
|
||||||
#define AUTOTTL_DEFAULT_DESYNC_DELTA -1
|
|
||||||
#define AUTOTTL_DEFAULT_DESYNC_MIN 3
|
|
||||||
#define AUTOTTL_DEFAULT_DESYNC_MAX 20
|
|
||||||
#define AUTOTTL_DEFAULT_ORIG_DELTA +5
|
|
||||||
#define AUTOTTL_DEFAULT_ORIG_MIN 3
|
|
||||||
#define AUTOTTL_DEFAULT_ORIG_MAX 64
|
|
||||||
#define AUTOTTL_DEFAULT_DUP_DELTA -1
|
|
||||||
#define AUTOTTL_DEFAULT_DUP_MIN 3
|
|
||||||
#define AUTOTTL_DEFAULT_DUP_MAX 64
|
|
||||||
|
|
||||||
|
|
||||||
#define MAX_SPLITS 64
|
#define MAX_SPLITS 64
|
||||||
|
|
||||||
#define FAKE_TLS_MOD_SAVE_MASK 0x0F
|
#define FAKE_TLS_MOD_SAVE_MASK 0x0F
|
||||||
@ -63,8 +50,6 @@
|
|||||||
#define FAKE_MAX_TCP 1460
|
#define FAKE_MAX_TCP 1460
|
||||||
#define FAKE_MAX_UDP 1472
|
#define FAKE_MAX_UDP 1472
|
||||||
|
|
||||||
#define MAX_GIDS 64
|
|
||||||
|
|
||||||
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
|
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
|
||||||
|
|
||||||
struct fake_tls_mod_cache
|
struct fake_tls_mod_cache
|
||||||
@ -77,8 +62,6 @@ struct fake_tls_mod
|
|||||||
uint32_t mod;
|
uint32_t mod;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {SS_NONE=0,SS_SYN,SS_SYNACK,SS_ACKSYN} t_synack_split;
|
|
||||||
|
|
||||||
struct desync_profile
|
struct desync_profile
|
||||||
{
|
{
|
||||||
int n; // number of the profile
|
int n; // number of the profile
|
||||||
@ -88,8 +71,6 @@ struct desync_profile
|
|||||||
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
||||||
unsigned int wssize_cutoff;
|
unsigned int wssize_cutoff;
|
||||||
|
|
||||||
t_synack_split synack_split;
|
|
||||||
|
|
||||||
bool hostcase, hostnospace, domcase, methodeol;
|
bool hostcase, hostnospace, domcase, methodeol;
|
||||||
char hostspell[4];
|
char hostspell[4];
|
||||||
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
|
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
|
||||||
@ -101,20 +82,6 @@ struct desync_profile
|
|||||||
int split_count;
|
int split_count;
|
||||||
struct proto_pos seqovl;
|
struct proto_pos seqovl;
|
||||||
|
|
||||||
char dup_start_mode, dup_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
|
||||||
bool dup_replace;
|
|
||||||
unsigned int dup_start, dup_cutoff;
|
|
||||||
unsigned int dup_repeats;
|
|
||||||
uint8_t dup_ttl, dup_ttl6;
|
|
||||||
uint32_t dup_fooling_mode;
|
|
||||||
uint32_t 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
|
|
||||||
unsigned int orig_mod_start, orig_mod_cutoff;
|
|
||||||
uint8_t orig_mod_ttl, orig_mod_ttl6;
|
|
||||||
autottl orig_autottl, orig_autottl6;
|
|
||||||
|
|
||||||
char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
||||||
unsigned int desync_start, desync_cutoff;
|
unsigned int desync_start, desync_cutoff;
|
||||||
uint8_t desync_ttl, desync_ttl6;
|
uint8_t desync_ttl, desync_ttl6;
|
||||||
@ -147,10 +114,9 @@ struct desync_profile
|
|||||||
hostfail_pool *hostlist_auto_fail_counters;
|
hostfail_pool *hostlist_auto_fail_counters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude))
|
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&dp->ips_collection) && !LIST_FIRST(&dp->ips_collection_exclude))
|
||||||
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude))
|
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&dp->ips_collection) && ipset_collection_is_empty(&dp->ips_collection_exclude))
|
||||||
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&(dp)->hl_collection) && hostlist_collection_is_empty(&(dp)->hl_collection_exclude))
|
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&dp->hl_collection) && hostlist_collection_is_empty(&dp->hl_collection_exclude))
|
||||||
#define PROFILE_HAS_ORIG_MOD(dp) ((dp)->orig_mod_ttl || (dp)->orig_mod_ttl6)
|
|
||||||
|
|
||||||
struct desync_profile_list {
|
struct desync_profile_list {
|
||||||
struct desync_profile dp;
|
struct desync_profile dp;
|
||||||
@ -161,7 +127,6 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
|||||||
void dp_entry_destroy(struct desync_profile_list *entry);
|
void dp_entry_destroy(struct desync_profile_list *entry);
|
||||||
void dp_list_destroy(struct desync_profile_list_head *head);
|
void dp_list_destroy(struct desync_profile_list_head *head);
|
||||||
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
|
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
|
||||||
bool dp_list_need_all_out(struct desync_profile_list_head *head);
|
|
||||||
void dp_init(struct desync_profile *dp);
|
void dp_init(struct desync_profile *dp);
|
||||||
bool dp_fake_defaults(struct desync_profile *dp);
|
bool dp_fake_defaults(struct desync_profile *dp);
|
||||||
void dp_clear(struct desync_profile *dp);
|
void dp_clear(struct desync_profile *dp);
|
||||||
@ -176,8 +141,6 @@ struct params_s
|
|||||||
char debug_logfile[PATH_MAX];
|
char debug_logfile[PATH_MAX];
|
||||||
bool debug;
|
bool debug;
|
||||||
|
|
||||||
bool daemon;
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int qnum;
|
int qnum;
|
||||||
#elif defined(BSD)
|
#elif defined(BSD)
|
||||||
@ -193,10 +156,8 @@ struct params_s
|
|||||||
#else
|
#else
|
||||||
bool droproot;
|
bool droproot;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid[MAX_GIDS];
|
gid_t gid;
|
||||||
int gid_count;
|
|
||||||
#endif
|
#endif
|
||||||
char pidfile[PATH_MAX];
|
|
||||||
|
|
||||||
char hostlist_auto_debuglog[PATH_MAX];
|
char hostlist_auto_debuglog[PATH_MAX];
|
||||||
|
|
||||||
@ -207,11 +168,6 @@ struct params_s
|
|||||||
|
|
||||||
unsigned int ctrack_t_syn, ctrack_t_est, ctrack_t_fin, ctrack_t_udp;
|
unsigned int ctrack_t_syn, ctrack_t_est, ctrack_t_fin, ctrack_t_udp;
|
||||||
t_conntrack conntrack;
|
t_conntrack conntrack;
|
||||||
bool ctrack_disable;
|
|
||||||
|
|
||||||
bool autottl_present,cache_hostname;
|
|
||||||
unsigned int ipcache_lifetime;
|
|
||||||
ip_cache ipcache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct params_s params;
|
extern struct params_s params;
|
||||||
|
217
nfq/pools.c
217
nfq/pools.c
@ -3,7 +3,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#define DESTROY_STR_POOL(etype, ppool) \
|
#define DESTROY_STR_POOL(etype, ppool) \
|
||||||
etype *elem, *tmp; \
|
etype *elem, *tmp; \
|
||||||
@ -580,219 +579,3 @@ bool blob_collection_empty(const struct blob_collection_head *head)
|
|||||||
{
|
{
|
||||||
return !LIST_FIRST(head);
|
return !LIST_FIRST(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ipcache_item_touch(ip_cache_item *item)
|
|
||||||
{
|
|
||||||
time(&item->last);
|
|
||||||
}
|
|
||||||
static void ipcache_item_init(ip_cache_item *item)
|
|
||||||
{
|
|
||||||
ipcache_item_touch(item);
|
|
||||||
item->hostname = NULL;
|
|
||||||
item->hops = 0;
|
|
||||||
}
|
|
||||||
static void ipcache_item_destroy(ip_cache_item *item)
|
|
||||||
{
|
|
||||||
free(item->hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ipcache4Destroy(ip_cache4 **ipcache)
|
|
||||||
{
|
|
||||||
ip_cache4 *elem, *tmp;
|
|
||||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
|
||||||
{
|
|
||||||
HASH_DEL(*ipcache, elem);
|
|
||||||
ipcache_item_destroy(&elem->data);
|
|
||||||
free(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ipcache4Key(ip4if *key, const struct in_addr *a, const char *iface)
|
|
||||||
{
|
|
||||||
memset(key,0,sizeof(*key)); // make sure everything is zero
|
|
||||||
key->addr = *a;
|
|
||||||
if (iface) snprintf(key->iface,sizeof(key->iface),"%s",iface);
|
|
||||||
}
|
|
||||||
static ip_cache4 *ipcache4Find(ip_cache4 *ipcache, const struct in_addr *a, const char *iface)
|
|
||||||
{
|
|
||||||
ip_cache4 *entry;
|
|
||||||
struct ip4if key;
|
|
||||||
|
|
||||||
ipcache4Key(&key,a,iface);
|
|
||||||
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a, const char *iface)
|
|
||||||
{
|
|
||||||
// avoid dups
|
|
||||||
ip_cache4 *entry = ipcache4Find(*ipcache,a,iface);
|
|
||||||
if (entry) return entry; // already included
|
|
||||||
|
|
||||||
entry = malloc(sizeof(ip_cache4));
|
|
||||||
if (!entry) return NULL;
|
|
||||||
ipcache4Key(&entry->key,a,iface);
|
|
||||||
|
|
||||||
oom = false;
|
|
||||||
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
|
|
||||||
if (oom) { free(entry); return NULL; }
|
|
||||||
|
|
||||||
ipcache_item_init(&entry->data);
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
static void ipcache4Print(ip_cache4 *ipcache)
|
|
||||||
{
|
|
||||||
char s_ip[16];
|
|
||||||
time_t now;
|
|
||||||
ip_cache4 *ipc, *tmp;
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
HASH_ITER(hh, ipcache , ipc, tmp)
|
|
||||||
{
|
|
||||||
*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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ipcache6Destroy(ip_cache6 **ipcache)
|
|
||||||
{
|
|
||||||
ip_cache6 *elem, *tmp;
|
|
||||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
|
||||||
{
|
|
||||||
HASH_DEL(*ipcache, elem);
|
|
||||||
ipcache_item_destroy(&elem->data);
|
|
||||||
free(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ipcache6Key(ip6if *key, const struct in6_addr *a, const char *iface)
|
|
||||||
{
|
|
||||||
memset(key,0,sizeof(*key)); // make sure everything is zero
|
|
||||||
key->addr = *a;
|
|
||||||
if (iface) snprintf(key->iface,sizeof(key->iface),"%s",iface);
|
|
||||||
}
|
|
||||||
static ip_cache6 *ipcache6Find(ip_cache6 *ipcache, const struct in6_addr *a, const char *iface)
|
|
||||||
{
|
|
||||||
ip_cache6 *entry;
|
|
||||||
ip6if key;
|
|
||||||
|
|
||||||
ipcache6Key(&key,a,iface);
|
|
||||||
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
static ip_cache6 *ipcache6Add(ip_cache6 **ipcache, const struct in6_addr *a, const char *iface)
|
|
||||||
{
|
|
||||||
// avoid dups
|
|
||||||
ip_cache6 *entry = ipcache6Find(*ipcache,a,iface);
|
|
||||||
if (entry) return entry; // already included
|
|
||||||
|
|
||||||
entry = malloc(sizeof(ip_cache6));
|
|
||||||
if (!entry) return NULL;
|
|
||||||
ipcache6Key(&entry->key,a,iface);
|
|
||||||
|
|
||||||
oom = false;
|
|
||||||
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
|
|
||||||
if (oom) { free(entry); return NULL; }
|
|
||||||
|
|
||||||
ipcache_item_init(&entry->data);
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
static void ipcache6Print(ip_cache6 *ipcache)
|
|
||||||
{
|
|
||||||
char s_ip[40];
|
|
||||||
time_t now;
|
|
||||||
ip_cache6 *ipc, *tmp;
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
HASH_ITER(hh, ipcache , ipc, tmp)
|
|
||||||
{
|
|
||||||
*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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ipcacheDestroy(ip_cache *ipcache)
|
|
||||||
{
|
|
||||||
ipcache4Destroy(&ipcache->ipcache4);
|
|
||||||
ipcache6Destroy(&ipcache->ipcache6);
|
|
||||||
}
|
|
||||||
void ipcachePrint(ip_cache *ipcache)
|
|
||||||
{
|
|
||||||
ipcache4Print(ipcache->ipcache4);
|
|
||||||
ipcache6Print(ipcache->ipcache6);
|
|
||||||
}
|
|
||||||
|
|
||||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
|
|
||||||
{
|
|
||||||
ip_cache4 *ipcache4;
|
|
||||||
ip_cache6 *ipcache6;
|
|
||||||
if (a4)
|
|
||||||
{
|
|
||||||
if ((ipcache4 = ipcache4Add(&ipcache->ipcache4,a4,iface)))
|
|
||||||
{
|
|
||||||
ipcache_item_touch(&ipcache4->data);
|
|
||||||
return &ipcache4->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (a6)
|
|
||||||
{
|
|
||||||
if ((ipcache6 = ipcache6Add(&ipcache->ipcache6,a6,iface)))
|
|
||||||
{
|
|
||||||
ipcache_item_touch(&ipcache6->data);
|
|
||||||
return &ipcache6->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
|
|
||||||
{
|
|
||||||
ip_cache4 *elem, *tmp;
|
|
||||||
time_t now = time(NULL);
|
|
||||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
|
||||||
{
|
|
||||||
if (now >= (elem->data.last + lifetime))
|
|
||||||
{
|
|
||||||
HASH_DEL(*ipcache, elem);
|
|
||||||
ipcache_item_destroy(&elem->data);
|
|
||||||
free(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ipcache6_purge(ip_cache6 **ipcache, time_t lifetime)
|
|
||||||
{
|
|
||||||
ip_cache6 *elem, *tmp;
|
|
||||||
time_t now = time(NULL);
|
|
||||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
|
||||||
{
|
|
||||||
if (now >= (elem->data.last + lifetime))
|
|
||||||
{
|
|
||||||
HASH_DEL(*ipcache, elem);
|
|
||||||
ipcache_item_destroy(&elem->data);
|
|
||||||
free(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ipcache_purge(ip_cache *ipcache, time_t lifetime)
|
|
||||||
{
|
|
||||||
if (lifetime) // 0 = no expire
|
|
||||||
{
|
|
||||||
ipcache4_purge(&ipcache->ipcache4, lifetime);
|
|
||||||
ipcache6_purge(&ipcache->ipcache6, lifetime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static time_t ipcache_purge_prev=0;
|
|
||||||
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime)
|
|
||||||
{
|
|
||||||
time_t now = time(NULL);
|
|
||||||
// do not purge too often to save resources
|
|
||||||
if (ipcache_purge_prev != now)
|
|
||||||
{
|
|
||||||
ipcache_purge(ipcache, lifetime);
|
|
||||||
ipcache_purge_prev = now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
41
nfq/pools.h
41
nfq/pools.h
@ -3,7 +3,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <net/if.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@ -162,43 +161,3 @@ struct blob_item *blob_collection_add(struct blob_collection_head *head);
|
|||||||
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve);
|
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve);
|
||||||
void blob_collection_destroy(struct blob_collection_head *head);
|
void blob_collection_destroy(struct blob_collection_head *head);
|
||||||
bool blob_collection_empty(const struct blob_collection_head *head);
|
bool blob_collection_empty(const struct blob_collection_head *head);
|
||||||
|
|
||||||
|
|
||||||
typedef struct ip4if
|
|
||||||
{
|
|
||||||
char iface[IFNAMSIZ];
|
|
||||||
struct in_addr addr;
|
|
||||||
} ip4if;
|
|
||||||
typedef struct ip6if
|
|
||||||
{
|
|
||||||
char iface[IFNAMSIZ];
|
|
||||||
struct in6_addr addr;
|
|
||||||
} ip6if;
|
|
||||||
typedef struct ip_cache_item
|
|
||||||
{
|
|
||||||
time_t last;
|
|
||||||
char *hostname;
|
|
||||||
uint8_t hops;
|
|
||||||
} ip_cache_item;
|
|
||||||
typedef struct ip_cache4
|
|
||||||
{
|
|
||||||
ip4if key;
|
|
||||||
ip_cache_item data;
|
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
|
||||||
} ip_cache4;
|
|
||||||
typedef struct ip_cache6
|
|
||||||
{
|
|
||||||
ip6if key;
|
|
||||||
ip_cache_item data;
|
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
|
||||||
} ip_cache6;
|
|
||||||
typedef struct ip_cache
|
|
||||||
{
|
|
||||||
ip_cache4 *ipcache4;
|
|
||||||
ip_cache6 *ipcache6;
|
|
||||||
} ip_cache;
|
|
||||||
|
|
||||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
|
|
||||||
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime);
|
|
||||||
void ipcacheDestroy(ip_cache *ipcache);
|
|
||||||
void ipcachePrint(ip_cache *ipcache);
|
|
||||||
|
@ -345,19 +345,6 @@ size_t HttpPos(uint8_t posmarker, int16_t pos, const uint8_t *data, size_t sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *TLSVersionStr(uint16_t tlsver)
|
|
||||||
{
|
|
||||||
switch(tlsver)
|
|
||||||
{
|
|
||||||
case 0x0301: return "TLS 1.0";
|
|
||||||
case 0x0302: return "TLS 1.1";
|
|
||||||
case 0x0303: return "TLS 1.2";
|
|
||||||
case 0x0304: return "TLS 1.3";
|
|
||||||
default:
|
|
||||||
// 0x0a0a, 0x1a1a, ..., 0xfafa
|
|
||||||
return (((tlsver & 0x0F0F) == 0x0A0A) && ((tlsver>>12)==((tlsver>>4)&0xF))) ? "GREASE" : "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t TLSRecordDataLen(const uint8_t *data)
|
uint16_t TLSRecordDataLen(const uint8_t *data)
|
||||||
{
|
{
|
||||||
@ -1028,8 +1015,7 @@ bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len)
|
|||||||
return len==74 &&
|
return len==74 &&
|
||||||
data[0]==0 && data[1]==1 &&
|
data[0]==0 && data[1]==1 &&
|
||||||
data[2]==0 && data[3]==70 &&
|
data[2]==0 && data[3]==70 &&
|
||||||
!memcmp(data+8,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",64);
|
data[8]==0 && memcmp(&data[8],&data[9],63)==0; // address is not set in requests
|
||||||
// address is not set in request
|
|
||||||
}
|
}
|
||||||
bool IsStunMessage(const uint8_t *data, size_t len)
|
bool IsStunMessage(const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -57,7 +57,6 @@ int HttpReplyCode(const uint8_t *data, size_t len);
|
|||||||
// must be pre-checked by IsHttpReply
|
// must be pre-checked by IsHttpReply
|
||||||
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
|
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
|
||||||
|
|
||||||
const char *TLSVersionStr(uint16_t tlsver);
|
|
||||||
uint16_t TLSRecordDataLen(const uint8_t *data);
|
uint16_t TLSRecordDataLen(const uint8_t *data);
|
||||||
size_t TLSRecordLen(const uint8_t *data);
|
size_t TLSRecordLen(const uint8_t *data);
|
||||||
bool IsTLSRecordFull(const uint8_t *data, size_t len);
|
bool IsTLSRecordFull(const uint8_t *data, size_t len);
|
||||||
|
26
nfq/sec.c
26
nfq/sec.c
@ -192,21 +192,20 @@ static bool set_seccomp(void)
|
|||||||
|
|
||||||
bool sec_harden(void)
|
bool sec_harden(void)
|
||||||
{
|
{
|
||||||
bool bRes = true;
|
|
||||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
|
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
|
||||||
{
|
{
|
||||||
DLOG_PERROR("PR_SET_NO_NEW_PRIVS(prctl)");
|
DLOG_PERROR("PR_SET_NO_NEW_PRIVS(prctl)");
|
||||||
bRes = false;
|
return false;
|
||||||
}
|
}
|
||||||
#if ARCH_NR!=0
|
#if ARCH_NR!=0
|
||||||
if (!set_seccomp())
|
if (!set_seccomp())
|
||||||
{
|
{
|
||||||
DLOG_PERROR("seccomp");
|
DLOG_PERROR("seccomp");
|
||||||
if (errno==EINVAL) DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
|
if (errno==EINVAL) DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
|
||||||
bRes = false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return bRes;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -295,13 +294,8 @@ bool can_drop_root(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool droproot(uid_t uid, gid_t *gid, int gid_count)
|
bool droproot(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
if (gid_count<1)
|
|
||||||
{
|
|
||||||
DLOG_ERR("droproot: no groups specified");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (prctl(PR_SET_KEEPCAPS, 1L))
|
if (prctl(PR_SET_KEEPCAPS, 1L))
|
||||||
{
|
{
|
||||||
@ -310,12 +304,12 @@ bool droproot(uid_t uid, gid_t *gid, int gid_count)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// drop all SGIDs
|
// drop all SGIDs
|
||||||
if (setgroups(gid_count,gid))
|
if (setgroups(0,NULL))
|
||||||
{
|
{
|
||||||
DLOG_PERROR("setgroups");
|
DLOG_PERROR("setgroups");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (setgid(gid[0]))
|
if (setgid(gid))
|
||||||
{
|
{
|
||||||
DLOG_PERROR("setgid");
|
DLOG_PERROR("setgid");
|
||||||
return false;
|
return false;
|
||||||
@ -348,13 +342,9 @@ void print_id(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void daemonize(void)
|
void daemonize(void)
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
#ifdef __CYGWIN__
|
|
||||||
char *cwd = get_current_dir_name();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
@ -365,10 +355,6 @@ void daemonize(void)
|
|||||||
else if (pid != 0)
|
else if (pid != 0)
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
|
||||||
chdir(get_current_dir_name());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (setsid() == -1)
|
if (setsid() == -1)
|
||||||
exit(2);
|
exit(2);
|
||||||
if (chdir("/") == -1)
|
if (chdir("/") == -1)
|
||||||
|
@ -84,7 +84,7 @@ bool dropcaps(void);
|
|||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
bool sec_harden(void);
|
bool sec_harden(void);
|
||||||
bool can_drop_root(void);
|
bool can_drop_root(void);
|
||||||
bool droproot(uid_t uid, gid_t *gid, int gid_count);
|
bool droproot(uid_t uid, gid_t gid);
|
||||||
void print_id(void);
|
void print_id(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
|
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
|
||||||
typedef union
|
typedef union
|
||||||
{
|
{
|
||||||
sa_family_t sa_family;
|
|
||||||
struct sockaddr_in sa4; // size 16
|
struct sockaddr_in sa4; // size 16
|
||||||
struct sockaddr_in6 sa6; // size 28
|
struct sockaddr_in6 sa6; // size 28
|
||||||
} sockaddr_in46;
|
} sockaddr_in46;
|
||||||
|
@ -287,13 +287,11 @@ static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostl
|
|||||||
}
|
}
|
||||||
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
|
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
if (filename && !file_mod_time(filename))
|
if (filename && !file_mod_time(filename))
|
||||||
{
|
{
|
||||||
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
|
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
return RegisterHostlist_(
|
return RegisterHostlist_(
|
||||||
¶ms.hostlists,
|
¶ms.hostlists,
|
||||||
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,
|
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
||||||
@ -21,10 +20,6 @@
|
|||||||
|
|
||||||
#define FIX_SEG_DEFAULT_MAX_WAIT 50
|
#define FIX_SEG_DEFAULT_MAX_WAIT 50
|
||||||
|
|
||||||
#define IPCACHE_LIFETIME 7200
|
|
||||||
|
|
||||||
#define MAX_GIDS 64
|
|
||||||
|
|
||||||
enum bindll { unwanted=0, no, prefer, force };
|
enum bindll { unwanted=0, no, prefer, force };
|
||||||
|
|
||||||
#define MAX_BINDS 32
|
#define MAX_BINDS 32
|
||||||
@ -119,9 +114,8 @@ struct params_s
|
|||||||
bool droproot;
|
bool droproot;
|
||||||
bool daemon;
|
bool daemon;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid[MAX_GIDS];
|
gid_t gid;
|
||||||
int gid_count;
|
char pidfile[256];
|
||||||
char pidfile[PATH_MAX];
|
|
||||||
int maxconn,resolver_threads,maxfiles,max_orphan_time;
|
int maxconn,resolver_threads,maxfiles,max_orphan_time;
|
||||||
int local_rcvbuf,local_sndbuf,remote_rcvbuf,remote_sndbuf;
|
int local_rcvbuf,local_sndbuf,remote_rcvbuf,remote_sndbuf;
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
@ -146,10 +140,6 @@ struct params_s
|
|||||||
bool tamper; // any tamper option is set
|
bool tamper; // any tamper option is set
|
||||||
bool tamper_lim; // tamper-start or tamper-cutoff set in any profile
|
bool tamper_lim; // tamper-start or tamper-cutoff set in any profile
|
||||||
struct desync_profile_list_head desync_profiles;
|
struct desync_profile_list_head desync_profiles;
|
||||||
|
|
||||||
unsigned int ipcache_lifetime;
|
|
||||||
bool cache_hostname;
|
|
||||||
ip_cache ipcache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct params_s params;
|
extern struct params_s params;
|
||||||
|
275
tpws/pools.c
275
tpws/pools.c
@ -3,7 +3,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#define DESTROY_STR_POOL(etype, ppool) \
|
#define DESTROY_STR_POOL(etype, ppool) \
|
||||||
etype *elem, *tmp; \
|
etype *elem, *tmp; \
|
||||||
@ -518,277 +517,3 @@ bool port_filters_deny_if_empty(struct port_filters_head *head)
|
|||||||
if (LIST_FIRST(head)) return true;
|
if (LIST_FIRST(head)) return true;
|
||||||
return pf_parse("0",&pf) && port_filter_add(head,&pf);
|
return pf_parse("0",&pf) && port_filter_add(head,&pf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct blob_item *blob_collection_add(struct blob_collection_head *head)
|
|
||||||
{
|
|
||||||
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
|
||||||
if (entry)
|
|
||||||
{
|
|
||||||
// insert to the end
|
|
||||||
struct blob_item *itemc,*iteml=LIST_FIRST(head);
|
|
||||||
if (iteml)
|
|
||||||
{
|
|
||||||
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
|
|
||||||
LIST_INSERT_AFTER(iteml, entry, next);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LIST_INSERT_HEAD(head, entry, next);
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve)
|
|
||||||
{
|
|
||||||
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
|
||||||
if (!entry) return NULL;
|
|
||||||
if (!(entry->data = malloc(size+size_reserve)))
|
|
||||||
{
|
|
||||||
free(entry);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (data) memcpy(entry->data,data,size);
|
|
||||||
entry->size = size;
|
|
||||||
entry->size_buf = size+size_reserve;
|
|
||||||
|
|
||||||
// insert to the end
|
|
||||||
struct blob_item *itemc,*iteml=LIST_FIRST(head);
|
|
||||||
if (iteml)
|
|
||||||
{
|
|
||||||
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
|
|
||||||
LIST_INSERT_AFTER(iteml, entry, next);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LIST_INSERT_HEAD(head, entry, next);
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void blob_collection_destroy(struct blob_collection_head *head)
|
|
||||||
{
|
|
||||||
struct blob_item *entry;
|
|
||||||
while ((entry = LIST_FIRST(head)))
|
|
||||||
{
|
|
||||||
LIST_REMOVE(entry, next);
|
|
||||||
free(entry->extra);
|
|
||||||
free(entry->extra2);
|
|
||||||
free(entry->data);
|
|
||||||
free(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool blob_collection_empty(const struct blob_collection_head *head)
|
|
||||||
{
|
|
||||||
return !LIST_FIRST(head);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ipcache_item_touch(ip_cache_item *item)
|
|
||||||
{
|
|
||||||
time(&item->last);
|
|
||||||
}
|
|
||||||
static void ipcache_item_init(ip_cache_item *item)
|
|
||||||
{
|
|
||||||
ipcache_item_touch(item);
|
|
||||||
item->hostname = NULL;
|
|
||||||
}
|
|
||||||
static void ipcache_item_destroy(ip_cache_item *item)
|
|
||||||
{
|
|
||||||
free(item->hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ipcache4Destroy(ip_cache4 **ipcache)
|
|
||||||
{
|
|
||||||
ip_cache4 *elem, *tmp;
|
|
||||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
|
||||||
{
|
|
||||||
HASH_DEL(*ipcache, elem);
|
|
||||||
ipcache_item_destroy(&elem->data);
|
|
||||||
free(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ipcache4Key(ip4if *key, const struct in_addr *a)
|
|
||||||
{
|
|
||||||
memset(key,0,sizeof(*key)); // make sure everything is zero
|
|
||||||
key->addr = *a;
|
|
||||||
}
|
|
||||||
static ip_cache4 *ipcache4Find(ip_cache4 *ipcache, const struct in_addr *a)
|
|
||||||
{
|
|
||||||
ip_cache4 *entry;
|
|
||||||
struct ip4if key;
|
|
||||||
|
|
||||||
ipcache4Key(&key,a);
|
|
||||||
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a)
|
|
||||||
{
|
|
||||||
// avoid dups
|
|
||||||
ip_cache4 *entry = ipcache4Find(*ipcache,a);
|
|
||||||
if (entry) return entry; // already included
|
|
||||||
|
|
||||||
entry = malloc(sizeof(ip_cache4));
|
|
||||||
if (!entry) return NULL;
|
|
||||||
ipcache4Key(&entry->key,a);
|
|
||||||
|
|
||||||
oom = false;
|
|
||||||
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
|
|
||||||
if (oom) { free(entry); return NULL; }
|
|
||||||
|
|
||||||
ipcache_item_init(&entry->data);
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
static void ipcache4Print(ip_cache4 *ipcache)
|
|
||||||
{
|
|
||||||
char s_ip[16];
|
|
||||||
time_t now;
|
|
||||||
ip_cache4 *ipc, *tmp;
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
HASH_ITER(hh, ipcache , ipc, tmp)
|
|
||||||
{
|
|
||||||
*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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ipcache6Destroy(ip_cache6 **ipcache)
|
|
||||||
{
|
|
||||||
ip_cache6 *elem, *tmp;
|
|
||||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
|
||||||
{
|
|
||||||
HASH_DEL(*ipcache, elem);
|
|
||||||
ipcache_item_destroy(&elem->data);
|
|
||||||
free(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ipcache6Key(ip6if *key, const struct in6_addr *a)
|
|
||||||
{
|
|
||||||
memset(key,0,sizeof(*key)); // make sure everything is zero
|
|
||||||
key->addr = *a;
|
|
||||||
}
|
|
||||||
static ip_cache6 *ipcache6Find(ip_cache6 *ipcache, const struct in6_addr *a)
|
|
||||||
{
|
|
||||||
ip_cache6 *entry;
|
|
||||||
ip6if key;
|
|
||||||
|
|
||||||
ipcache6Key(&key,a);
|
|
||||||
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
static ip_cache6 *ipcache6Add(ip_cache6 **ipcache, const struct in6_addr *a)
|
|
||||||
{
|
|
||||||
// avoid dups
|
|
||||||
ip_cache6 *entry = ipcache6Find(*ipcache,a);
|
|
||||||
if (entry) return entry; // already included
|
|
||||||
|
|
||||||
entry = malloc(sizeof(ip_cache6));
|
|
||||||
if (!entry) return NULL;
|
|
||||||
ipcache6Key(&entry->key,a);
|
|
||||||
|
|
||||||
oom = false;
|
|
||||||
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
|
|
||||||
if (oom) { free(entry); return NULL; }
|
|
||||||
|
|
||||||
ipcache_item_init(&entry->data);
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
static void ipcache6Print(ip_cache6 *ipcache)
|
|
||||||
{
|
|
||||||
char s_ip[40];
|
|
||||||
time_t now;
|
|
||||||
ip_cache6 *ipc, *tmp;
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
HASH_ITER(hh, ipcache , ipc, tmp)
|
|
||||||
{
|
|
||||||
*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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ipcacheDestroy(ip_cache *ipcache)
|
|
||||||
{
|
|
||||||
ipcache4Destroy(&ipcache->ipcache4);
|
|
||||||
ipcache6Destroy(&ipcache->ipcache6);
|
|
||||||
}
|
|
||||||
void ipcachePrint(ip_cache *ipcache)
|
|
||||||
{
|
|
||||||
ipcache4Print(ipcache->ipcache4);
|
|
||||||
ipcache6Print(ipcache->ipcache6);
|
|
||||||
}
|
|
||||||
|
|
||||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6)
|
|
||||||
{
|
|
||||||
ip_cache4 *ipcache4;
|
|
||||||
ip_cache6 *ipcache6;
|
|
||||||
if (a4)
|
|
||||||
{
|
|
||||||
if ((ipcache4 = ipcache4Add(&ipcache->ipcache4,a4)))
|
|
||||||
{
|
|
||||||
ipcache_item_touch(&ipcache4->data);
|
|
||||||
return &ipcache4->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (a6)
|
|
||||||
{
|
|
||||||
if ((ipcache6 = ipcache6Add(&ipcache->ipcache6,a6)))
|
|
||||||
{
|
|
||||||
ipcache_item_touch(&ipcache6->data);
|
|
||||||
return &ipcache6->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
|
|
||||||
{
|
|
||||||
ip_cache4 *elem, *tmp;
|
|
||||||
time_t now = time(NULL);
|
|
||||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
|
||||||
{
|
|
||||||
if (now >= (elem->data.last + lifetime))
|
|
||||||
{
|
|
||||||
HASH_DEL(*ipcache, elem);
|
|
||||||
ipcache_item_destroy(&elem->data);
|
|
||||||
free(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ipcache6_purge(ip_cache6 **ipcache, time_t lifetime)
|
|
||||||
{
|
|
||||||
ip_cache6 *elem, *tmp;
|
|
||||||
time_t now = time(NULL);
|
|
||||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
|
||||||
{
|
|
||||||
if (now >= (elem->data.last + lifetime))
|
|
||||||
{
|
|
||||||
HASH_DEL(*ipcache, elem);
|
|
||||||
ipcache_item_destroy(&elem->data);
|
|
||||||
free(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ipcache_purge(ip_cache *ipcache, time_t lifetime)
|
|
||||||
{
|
|
||||||
if (lifetime) // 0 = no expire
|
|
||||||
{
|
|
||||||
ipcache4_purge(&ipcache->ipcache4, lifetime);
|
|
||||||
ipcache6_purge(&ipcache->ipcache6, lifetime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static time_t ipcache_purge_prev=0;
|
|
||||||
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime)
|
|
||||||
{
|
|
||||||
time_t now = time(NULL);
|
|
||||||
// do not purge too often to save resources
|
|
||||||
if (ipcache_purge_prev != now)
|
|
||||||
{
|
|
||||||
ipcache_purge(ipcache, lifetime);
|
|
||||||
ipcache_purge_prev = now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
53
tpws/pools.h
53
tpws/pools.h
@ -3,7 +3,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <net/if.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@ -147,55 +146,3 @@ bool port_filter_add(struct port_filters_head *head, const port_filter *pf);
|
|||||||
void port_filters_destroy(struct port_filters_head *head);
|
void port_filters_destroy(struct port_filters_head *head);
|
||||||
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
|
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
|
||||||
bool port_filters_deny_if_empty(struct port_filters_head *head);
|
bool port_filters_deny_if_empty(struct port_filters_head *head);
|
||||||
|
|
||||||
|
|
||||||
struct blob_item {
|
|
||||||
uint8_t *data; // main data blob
|
|
||||||
size_t size; // main data blob size
|
|
||||||
size_t size_buf;// main data blob allocated size
|
|
||||||
void *extra; // any data without size
|
|
||||||
void *extra2; // any data without size
|
|
||||||
LIST_ENTRY(blob_item) next;
|
|
||||||
};
|
|
||||||
LIST_HEAD(blob_collection_head, blob_item);
|
|
||||||
struct blob_item *blob_collection_add(struct blob_collection_head *head);
|
|
||||||
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve);
|
|
||||||
void blob_collection_destroy(struct blob_collection_head *head);
|
|
||||||
bool blob_collection_empty(const struct blob_collection_head *head);
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct ip4if
|
|
||||||
{
|
|
||||||
struct in_addr addr;
|
|
||||||
} ip4if;
|
|
||||||
typedef struct ip6if
|
|
||||||
{
|
|
||||||
struct in6_addr addr;
|
|
||||||
} ip6if;
|
|
||||||
typedef struct ip_cache_item
|
|
||||||
{
|
|
||||||
time_t last;
|
|
||||||
char *hostname;
|
|
||||||
} ip_cache_item;
|
|
||||||
typedef struct ip_cache4
|
|
||||||
{
|
|
||||||
ip4if key;
|
|
||||||
ip_cache_item data;
|
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
|
||||||
} ip_cache4;
|
|
||||||
typedef struct ip_cache6
|
|
||||||
{
|
|
||||||
ip6if key;
|
|
||||||
ip_cache_item data;
|
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
|
||||||
} ip_cache6;
|
|
||||||
typedef struct ip_cache
|
|
||||||
{
|
|
||||||
ip_cache4 *ipcache4;
|
|
||||||
ip_cache6 *ipcache6;
|
|
||||||
} ip_cache;
|
|
||||||
|
|
||||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6);
|
|
||||||
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime);
|
|
||||||
void ipcacheDestroy(ip_cache *ipcache);
|
|
||||||
void ipcachePrint(ip_cache *ipcache);
|
|
||||||
|
@ -339,20 +339,6 @@ size_t HttpPos(uint8_t posmarker, int16_t pos, const uint8_t *data, size_t sz)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char *TLSVersionStr(uint16_t tlsver)
|
|
||||||
{
|
|
||||||
switch(tlsver)
|
|
||||||
{
|
|
||||||
case 0x0301: return "TLS 1.0";
|
|
||||||
case 0x0302: return "TLS 1.1";
|
|
||||||
case 0x0303: return "TLS 1.2";
|
|
||||||
case 0x0304: return "TLS 1.3";
|
|
||||||
default:
|
|
||||||
// 0x0a0a, 0x1a1a, ..., 0xfafa
|
|
||||||
return (((tlsver & 0x0F0F) == 0x0A0A) && ((tlsver>>12)==((tlsver>>4)&0xF))) ? "GREASE" : "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t TLSRecordDataLen(const uint8_t *data)
|
uint16_t TLSRecordDataLen(const uint8_t *data)
|
||||||
{
|
{
|
||||||
return pntoh16(data + 3);
|
return pntoh16(data + 3);
|
||||||
|
@ -53,7 +53,6 @@ int HttpReplyCode(const uint8_t *data, size_t len);
|
|||||||
// must be pre-checked by IsHttpReply
|
// must be pre-checked by IsHttpReply
|
||||||
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
|
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
|
||||||
|
|
||||||
const char *TLSVersionStr(uint16_t tlsver);
|
|
||||||
uint16_t TLSRecordDataLen(const uint8_t *data);
|
uint16_t TLSRecordDataLen(const uint8_t *data);
|
||||||
size_t TLSRecordLen(const uint8_t *data);
|
size_t TLSRecordLen(const uint8_t *data);
|
||||||
bool IsTLSRecordFull(const uint8_t *data, size_t len);
|
bool IsTLSRecordFull(const uint8_t *data, size_t len);
|
||||||
|
20
tpws/sec.c
20
tpws/sec.c
@ -169,24 +169,25 @@ static bool set_seccomp(void)
|
|||||||
|
|
||||||
bool sec_harden(void)
|
bool sec_harden(void)
|
||||||
{
|
{
|
||||||
bool bRes = true;
|
|
||||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
|
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
|
||||||
{
|
{
|
||||||
DLOG_PERROR("PR_SET_NO_NEW_PRIVS(prctl)");
|
DLOG_PERROR("PR_SET_NO_NEW_PRIVS(prctl)");
|
||||||
bRes = false;
|
return false;
|
||||||
}
|
}
|
||||||
#if ARCH_NR!=0
|
#if ARCH_NR!=0
|
||||||
if (!set_seccomp())
|
if (!set_seccomp())
|
||||||
{
|
{
|
||||||
DLOG_PERROR("seccomp");
|
DLOG_PERROR("seccomp");
|
||||||
if (errno==EINVAL) DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
|
if (errno==EINVAL) DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
|
||||||
bRes = false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return bRes;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool checkpcap(uint64_t caps)
|
bool checkpcap(uint64_t caps)
|
||||||
{
|
{
|
||||||
if (!caps) return true; // no special caps reqd
|
if (!caps) return true; // no special caps reqd
|
||||||
@ -269,13 +270,8 @@ bool can_drop_root(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool droproot(uid_t uid, gid_t *gid, int gid_count)
|
bool droproot(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
if (gid_count<1)
|
|
||||||
{
|
|
||||||
DLOG_ERR("droproot: no groups specified");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (prctl(PR_SET_KEEPCAPS, 1L))
|
if (prctl(PR_SET_KEEPCAPS, 1L))
|
||||||
{
|
{
|
||||||
@ -284,12 +280,12 @@ bool droproot(uid_t uid, gid_t *gid, int gid_count)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// drop all SGIDs
|
// drop all SGIDs
|
||||||
if (setgroups(gid_count,gid))
|
if (setgroups(0,NULL))
|
||||||
{
|
{
|
||||||
DLOG_PERROR("setgroups");
|
DLOG_PERROR("setgroups");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (setgid(gid[0]))
|
if (setgid(gid))
|
||||||
{
|
{
|
||||||
DLOG_PERROR("setgid");
|
DLOG_PERROR("setgid");
|
||||||
return false;
|
return false;
|
||||||
|
@ -84,7 +84,7 @@ bool dropcaps(void);
|
|||||||
|
|
||||||
bool sec_harden(void);
|
bool sec_harden(void);
|
||||||
bool can_drop_root();
|
bool can_drop_root();
|
||||||
bool droproot(uid_t uid, gid_t *gid, int gid_count);
|
bool droproot(uid_t uid, gid_t gid);
|
||||||
void print_id(void);
|
void print_id(void);
|
||||||
void daemonize(void);
|
void daemonize(void);
|
||||||
bool writepid(const char *filename);
|
bool writepid(const char *filename);
|
||||||
|
139
tpws/tamper.c
139
tpws/tamper.c
@ -7,7 +7,6 @@
|
|||||||
#include "ipset.h"
|
#include "ipset.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "pools.h"
|
|
||||||
|
|
||||||
#define PKTDATA_MAXDUMP 32
|
#define PKTDATA_MAXDUMP 32
|
||||||
|
|
||||||
@ -16,126 +15,6 @@ void packet_debug(const uint8_t *data, size_t sz)
|
|||||||
hexdump_limited_dlog(data, sz, PKTDATA_MAXDUMP); VPRINT("\n");
|
hexdump_limited_dlog(data, sz, PKTDATA_MAXDUMP); VPRINT("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TLSDebugHandshake(const uint8_t *tls,size_t sz)
|
|
||||||
{
|
|
||||||
if (!params.debug) return;
|
|
||||||
|
|
||||||
if (sz<6) return;
|
|
||||||
|
|
||||||
const uint8_t *ext;
|
|
||||||
size_t len,len2;
|
|
||||||
|
|
||||||
uint16_t v_handshake=pntoh16(tls+4), v, v2;
|
|
||||||
VPRINT("TLS handshake version : %s\n",TLSVersionStr(v_handshake));
|
|
||||||
|
|
||||||
if (TLSFindExtInHandshake(tls,sz,43,&ext,&len,false))
|
|
||||||
{
|
|
||||||
if (len)
|
|
||||||
{
|
|
||||||
len2 = ext[0];
|
|
||||||
if (len2<len)
|
|
||||||
{
|
|
||||||
for(ext++,len2&=~1 ; len2 ; len2-=2,ext+=2)
|
|
||||||
{
|
|
||||||
v = pntoh16(ext);
|
|
||||||
VPRINT("TLS supported versions ext : %s\n",TLSVersionStr(v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
VPRINT("TLS supported versions ext : not present\n");
|
|
||||||
|
|
||||||
if (TLSFindExtInHandshake(tls,sz,16,&ext,&len,false))
|
|
||||||
{
|
|
||||||
if (len>=2)
|
|
||||||
{
|
|
||||||
len2 = pntoh16(ext);
|
|
||||||
if (len2<=(len-2))
|
|
||||||
{
|
|
||||||
char s[32];
|
|
||||||
for(ext+=2; len2 ;)
|
|
||||||
{
|
|
||||||
v = *ext; ext++; len2--;
|
|
||||||
if (v<=len2)
|
|
||||||
{
|
|
||||||
v2 = v<sizeof(s) ? v : sizeof(s)-1;
|
|
||||||
memcpy(s,ext,v2);
|
|
||||||
s[v2]=0;
|
|
||||||
VPRINT("TLS ALPN ext : %s\n",s);
|
|
||||||
len2-=v;
|
|
||||||
ext+=v;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
VPRINT("TLS ALPN ext : not present\n");
|
|
||||||
|
|
||||||
VPRINT("TLS ECH ext : %s\n",TLSFindExtInHandshake(tls,sz,65037,NULL,NULL,false) ? "present" : "not present");
|
|
||||||
}
|
|
||||||
static void TLSDebug(const uint8_t *tls,size_t sz)
|
|
||||||
{
|
|
||||||
if (!params.debug) return;
|
|
||||||
|
|
||||||
if (sz<11) return;
|
|
||||||
|
|
||||||
VPRINT("TLS record layer version : %s\n",TLSVersionStr(pntoh16(tls+1)));
|
|
||||||
|
|
||||||
size_t reclen=TLSRecordLen(tls);
|
|
||||||
if (reclen<sz) sz=reclen; // correct len if it has more data than the first tls record has
|
|
||||||
|
|
||||||
TLSDebugHandshake(tls+5,sz-5);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname)
|
|
||||||
{
|
|
||||||
if (!params.cache_hostname) return true;
|
|
||||||
|
|
||||||
ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache,a4,a6);
|
|
||||||
if (!ipc)
|
|
||||||
{
|
|
||||||
DLOG_ERR("ipcache_put_hostname: out of memory\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!ipc->hostname || strcmp(ipc->hostname,hostname))
|
|
||||||
{
|
|
||||||
free(ipc->hostname);
|
|
||||||
if (!(ipc->hostname = strdup(hostname)))
|
|
||||||
{
|
|
||||||
DLOG_ERR("ipcache_put_hostname: out of memory\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
VPRINT("hostname cached: %s\n", 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)
|
|
||||||
{
|
|
||||||
if (!params.cache_hostname)
|
|
||||||
{
|
|
||||||
*hostname = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache,a4,a6);
|
|
||||||
if (!ipc)
|
|
||||||
{
|
|
||||||
DLOG_ERR("ipcache_get_hostname: out of memory\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (ipc->hostname)
|
|
||||||
{
|
|
||||||
VPRINT("got cached hostname: %s\n", ipc->hostname);
|
|
||||||
snprintf(hostname,hostname_buf_len,"%s",ipc->hostname);
|
|
||||||
}
|
|
||||||
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, t_l7proto l7proto)
|
||||||
{
|
{
|
||||||
bool bHostlistsEmpty;
|
bool bHostlistsEmpty;
|
||||||
@ -191,17 +70,8 @@ static struct desync_profile *dp_find(struct desync_profile_list_head *head, con
|
|||||||
VPRINT("desync profile not found\n");
|
VPRINT("desync profile not found\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest)
|
void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest)
|
||||||
{
|
{
|
||||||
ipcachePurgeRateLimited(¶ms.ipcache, params.ipcache_lifetime);
|
|
||||||
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 (!(ctrack->hostname=strdup(host)))
|
|
||||||
DLOG_ERR("hostname dup : out of memory");
|
|
||||||
}
|
|
||||||
ctrack->dp = dp_find(¶ms.desync_profiles, dest, ctrack->hostname, ctrack->l7proto);
|
ctrack->dp = dp_find(¶ms.desync_profiles, dest, ctrack->hostname, ctrack->l7proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +130,6 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
{
|
{
|
||||||
VPRINT("Data block contains TLS ClientHello\n");
|
VPRINT("Data block contains TLS ClientHello\n");
|
||||||
l7proto=TLS;
|
l7proto=TLS;
|
||||||
TLSDebug(segment,*size);
|
|
||||||
bHaveHost=TLSHelloExtractHost((uint8_t*)segment,*size,Host,sizeof(Host),false);
|
bHaveHost=TLSHelloExtractHost((uint8_t*)segment,*size,Host,sizeof(Host),false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -270,11 +139,7 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bHaveHost)
|
if (bHaveHost)
|
||||||
{
|
|
||||||
VPRINT("request hostname: %s\n", 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))
|
|
||||||
DLOG_ERR("ipcache_put_hostname: out of memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bDiscoveredL7 = ctrack->l7proto==UNKNOWN && l7proto!=UNKNOWN;
|
bool bDiscoveredL7 = ctrack->l7proto==UNKNOWN && l7proto!=UNKNOWN;
|
||||||
if (bDiscoveredL7)
|
if (bDiscoveredL7)
|
||||||
@ -283,17 +148,15 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
ctrack->l7proto=l7proto;
|
ctrack->l7proto=l7proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bDiscoveredHostname = bHaveHost && !ctrack->hostname_discovered;
|
bool bDiscoveredHostname = bHaveHost && !ctrack->hostname;
|
||||||
if (bDiscoveredHostname)
|
if (bDiscoveredHostname)
|
||||||
{
|
{
|
||||||
VPRINT("discovered hostname\n");
|
VPRINT("discovered hostname\n");
|
||||||
free(ctrack->hostname);
|
|
||||||
if (!(ctrack->hostname=strdup(Host)))
|
if (!(ctrack->hostname=strdup(Host)))
|
||||||
{
|
{
|
||||||
DLOG_ERR("strdup hostname : out of memory\n");
|
DLOG_ERR("strdup hostname : out of memory\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctrack->hostname_discovered = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||||
|
@ -15,13 +15,11 @@ typedef struct
|
|||||||
t_l7proto l7proto;
|
t_l7proto l7proto;
|
||||||
bool bTamperInCutoff;
|
bool bTamperInCutoff;
|
||||||
bool b_host_checked,b_host_matches,b_ah_check;
|
bool b_host_checked,b_host_matches,b_ah_check;
|
||||||
bool hostname_discovered;
|
|
||||||
char *hostname;
|
char *hostname;
|
||||||
struct desync_profile *dp; // desync profile cache
|
struct desync_profile *dp; // desync profile cache
|
||||||
} t_ctrack;
|
} t_ctrack;
|
||||||
|
|
||||||
void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest);
|
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);
|
|
||||||
|
|
||||||
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_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);
|
void tamper_in(t_ctrack *ctrack, const struct sockaddr *client, uint8_t *segment,size_t segment_buffer_size,size_t *size);
|
||||||
|
566
tpws/tpws.c
566
tpws/tpws.c
File diff suppressed because it is too large
Load Diff
@ -494,9 +494,6 @@ static bool connect_remote_conn(tproxy_conn_t *conn)
|
|||||||
{
|
{
|
||||||
int mss=0;
|
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))
|
|
||||||
DLOG_ERR("ipcache_put_hostname: out of memory");
|
|
||||||
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
|
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
|
||||||
|
|
||||||
if (conn->track.dp && conn->track.dp->mss)
|
if (conn->track.dp && conn->track.dp->mss)
|
||||||
@ -1090,8 +1087,7 @@ static bool resolve_complete(struct resolve_item *ri, struct tailhead *conn_list
|
|||||||
if (!conn->track.hostname)
|
if (!conn->track.hostname)
|
||||||
{
|
{
|
||||||
DBGPRINT("resolve_complete put hostname : %s\n", ri->dom);
|
DBGPRINT("resolve_complete put hostname : %s\n", ri->dom);
|
||||||
if (!(conn->track.hostname = strdup(ri->dom)))
|
conn->track.hostname = strdup(ri->dom);
|
||||||
DLOG_ERR("dup hostname: out of memory\n");
|
|
||||||
}
|
}
|
||||||
sa46copy(&conn->dest, (struct sockaddr *)&ri->ss);
|
sa46copy(&conn->dest, (struct sockaddr *)&ri->ss);
|
||||||
return proxy_mode_connect_remote(conn,conn_list);
|
return proxy_mode_connect_remote(conn,conn_list);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user