mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-06 18:50:51 +05:00
Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5c63cb43e7 | ||
![]() |
7f24f82002 | ||
![]() |
b0c7af789a | ||
![]() |
a426ea6dad | ||
![]() |
bda4226162 | ||
![]() |
dc1dc5c876 | ||
![]() |
3ca682e25a | ||
![]() |
9629ce5cb7 | ||
![]() |
c626d88f54 | ||
![]() |
c91ddf4a54 | ||
![]() |
6f1286b5b9 | ||
![]() |
c96bc62d3b | ||
![]() |
8432388b37 | ||
![]() |
7efa83e61e | ||
![]() |
abe91a4bfa | ||
![]() |
43173e6396 | ||
![]() |
5cc888cd2c | ||
![]() |
5b625fa709 | ||
![]() |
0a8135b2de | ||
![]() |
d21175b4a3 | ||
![]() |
68a538daed | ||
![]() |
d2c9ff50cd | ||
![]() |
50539d6cbf | ||
![]() |
8b5dfcfae1 | ||
![]() |
ccc60b5f07 | ||
![]() |
7f94f42b1d | ||
![]() |
1c1f259b39 | ||
![]() |
6ef6c8ee5a | ||
![]() |
581badfb73 | ||
![]() |
8fce75daa4 | ||
![]() |
c1e2e56576 | ||
![]() |
e16ec69922 | ||
![]() |
63256a142f | ||
![]() |
4a9a8bd48e | ||
![]() |
b996abd5ce | ||
![]() |
12461de3b0 | ||
![]() |
7dab497b57 | ||
![]() |
41dbba1c4c | ||
![]() |
d19f6c19a4 | ||
![]() |
b12b1a5a17 | ||
![]() |
8022e2576d | ||
![]() |
f4ea264ba9 | ||
![]() |
061acb27e4 | ||
![]() |
8eb830d304 | ||
![]() |
2fb93c6add | ||
![]() |
ad5c246629 |
@ -341,6 +341,12 @@ 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
|
||||||
@ -355,7 +361,14 @@ 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
|
||||||
@ -722,6 +735,11 @@ 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
|
||||||
@ -753,6 +771,7 @@ 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
|
||||||
|
|
||||||
@ -770,12 +789,20 @@ 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 != $DESYNC_MARK ip${ipver} daddr {$iplist} queue num $QNUM"
|
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"
|
||||||
# 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()
|
||||||
|
@ -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
|
||||||
# ЕСЛИ ВАМ ХОЧЕТСЯ ЕГО УДАЛИТЬ И НАПИСАТЬ ИНСТРУКЦИЮ КАК ЕГО УДАЛЯТЬ, ВЫ ДЕЛАЕТЕ ХРЕНОВУЮ УСЛУГУ. НАПИШИТЕ ЛУЧШЕ custom script.
|
# 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.
|
||||||
# ФИЛЬТРАЦИЯ ПО IPSET В ЯДРЕ НЕСРАВНИМО ЭФФЕКТИВНЕЕ, ЧЕМ ПЕРЕКИДЫВАТЬ ВСЕ ПАКЕТЫ В nfqws И ТАМ ФИЛЬТРОВАТЬ
|
# I cannot insert brain to copy-pasters, I know they will misuse. But it's their problem.
|
||||||
# --ipset СУЩЕСТВУЕТ ТОЛЬКО ДЛЯ ВИНДЫ И LINUX СИСТЕМ БЕЗ ipset (НАПРИМЕР, Android).
|
# zapret is not made for newbies
|
||||||
# И ТОЛЬКО ПО ЭТОЙ ПРИЧИНЕ ОНО НЕ ВЫКИНУТО ПОЛНОСТЬЮ ИЗ LINUX ВЕРСИИ
|
#contains "$1" "--ipset"
|
||||||
contains "$1" "--ipset"
|
return 1
|
||||||
}
|
}
|
||||||
check_bad_ws_options()
|
check_bad_ws_options()
|
||||||
{
|
{
|
||||||
|
@ -391,6 +391,27 @@ 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,6 +111,14 @@ 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 != 0 notrack comment "ipfrag"
|
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off & 0x1fff != 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,6 +119,20 @@ 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()
|
||||||
{
|
{
|
||||||
@ -320,7 +334,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
|
local script i j ALLDEVS devs b
|
||||||
|
|
||||||
# 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
|
||||||
@ -348,15 +362,18 @@ 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 2>/dev/null
|
nft_create_or_update_flowtable 'offload' $j && b=1 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
|
||||||
@ -453,7 +470,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 $FW_EXTRA_POST queue num $port bypass
|
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,7 +485,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 $FW_EXTRA_POST queue num $port bypass
|
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,7 +509,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 $FW_EXTRA_POST queue num $port bypass
|
nft_insert_rule $(get_prechain) $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_nft_fw_nfqws_pre6()
|
_nft_fw_nfqws_pre6()
|
||||||
@ -505,7 +522,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 $FW_EXTRA_POST queue num $port bypass
|
nft_insert_rule $(get_prechain) $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nft_fw_nfqws_pre()
|
nft_fw_nfqws_pre()
|
||||||
@ -683,3 +700,7 @@ 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,6 +129,11 @@ 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,3 +481,15 @@ 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
|
||||||
|
tpws: ipcache of host names
|
||||||
|
nfqws,tpws: set 1024 repeat limit to fakes and dups
|
||||||
|
init.d: remove --ipset parameter prohibition
|
||||||
|
init.d, blockcheck: drop time exceeded icmp for nfqws-related connections
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# zapret v70.6
|
# zapret v70.7
|
||||||
|
|
||||||
# SCAMMER WARNING
|
# SCAMMER WARNING
|
||||||
|
|
||||||
@ -173,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)
|
--dpi-desync-fake-tls=<filename>|0xHEX|! ; file containing fake TLS ClientHello (for https). '!' = standard fake
|
||||||
--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
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# zapret v70.6
|
# zapret v70.7
|
||||||
|
|
||||||
# ВНИМАНИЕ, остерегайтесь мошенников
|
# ВНИМАНИЕ, остерегайтесь мошенников
|
||||||
|
|
||||||
@ -195,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
|
||||||
@ -2334,38 +2334,32 @@ OpenWrt является одной из немногих относительн
|
|||||||
VPS — это виртуальный сервер. Существует огромное множество датацентров, предлагающих данную услугу.
|
VPS — это виртуальный сервер. Существует огромное множество датацентров, предлагающих данную услугу.
|
||||||
На VPS могут выполняться какие угодно задачи. От простого веб-сайта до навороченной системы собственной разработки.
|
На VPS могут выполняться какие угодно задачи. От простого веб-сайта до навороченной системы собственной разработки.
|
||||||
Можно использовать VPS и для поднятия собственного VPN или прокси.
|
Можно использовать VPS и для поднятия собственного VPN или прокси.
|
||||||
Сама широта возможных способов применения и распространенность услуги сводят к минимуму возможности
|
Сама широта возможных способов применения и распространенность услуги ограничивают возможности регуляторов
|
||||||
регуляторов по бану сервисов такого типа. Да, если введут белые списки, то решение загнется, но это будет уже другая
|
по бану сервисов такого типа. Да, если введут белые списки, то решение загнется, но это будет уже другая
|
||||||
реальность, в которой придется изобретать иные решения.
|
реальность, в которой придется изобретать иные решения.
|
||||||
Пока этого не сделали, никто не будет банить хостинги просто потому, что они предоставляют хостинг услуги.
|
Пока этого не сделали. Однако, уже наблюдаются попытки гасить некоторые протоколы на диапазонах VPS провайдеров.
|
||||||
Вы, как индивидуум, скорее всего, никому не нужны. Подумайте чем вы отличаетесь от известного VPN провайдера.
|
Вплоть до TLS. Как следствие не работают ни средства обхода типа VLESS, ни обычные сайты.
|
||||||
|
Пока это делается еще точечно, не на всех провайдерах. Не стоит сразу оплачивать VPS надолго. Сначала проверьте
|
||||||
|
все ли работает из того, что вам нужно. Или может быть стоит найти другой VPS.
|
||||||
|
|
||||||
|
VPS имеет преимущество над VPN провайдером.
|
||||||
VPN-провайдер предоставляет _простую_ и _доступную_ услугу по обходу блокировок для масс.
|
VPN-провайдер предоставляет _простую_ и _доступную_ услугу по обходу блокировок для масс.
|
||||||
Этот факт делает его первоочередной целью блокировки. РКН направит уведомление, после отказа сотрудничать
|
Все, что просто и доступно, первым делом идет под блок.
|
||||||
заблокирует VPN. Предоплаченная сумма пропадет.
|
|
||||||
У регуляторов нет и никогда не будет ресурсов для тотальной проверки каждого сервера в сети.
|
|
||||||
Возможен китайский расклад, при котором DPI выявляет VPN-протоколы и динамически банит IP серверов,
|
Возможен китайский расклад, при котором DPI выявляет VPN-протоколы и динамически банит IP серверов,
|
||||||
предоставляющих нелицензированный VPN. Но имея знания, голову, вы всегда можете обфусцировать
|
предоставляющих нелицензированный VPN. Но имея знания, голову, вы всегда можете обфусцировать
|
||||||
VPN трафик или применить другие типы VPN, более устойчивые к анализу на DPI, или просто менее широкоизвестные,
|
VPN трафик или применить другие типы VPN, более устойчивые к анализу на DPI, или просто менее широкоизвестные,
|
||||||
а следовательно с меньшей вероятностью обнаруживаемые регулятором.
|
а следовательно с меньшей вероятностью обнаруживаемые регулятором.
|
||||||
У вас есть свобода делать на вашем VPS все что вы захотите, адаптируясь к новым условиям.
|
У вас есть свобода делать на вашем VPS все что вы захотите, адаптируясь к новым условиям.
|
||||||
Да, это потребует знаний. Вам выбирать учиться и держать ситуацию под контролем, когда вам ничего запретить
|
Да, это потребует знаний. Вам выбирать учиться и держать ситуацию под контролем, когда вам ничего запретить
|
||||||
не могут, или покориться системе.
|
не могут, или покориться системе. Порог необходимых знаний и возможностей для самостоятельного входа в обход блокировок будет только возрастать.
|
||||||
|
|
||||||
VPS можно приобрести в множестве мест. Существуют специализированные на поиске предложений VPS порталы.\
|
VPS можно приобрести в множестве мест. Существуют специализированные на поиске предложений VPS порталы.\
|
||||||
Например, [вот этот](https://vps.today).
|
Например, [вот этот](https://vps.today). Для персонального VPN сервера обычно достаточно самой минимальной конфигурации, но с безлимитным трафиком или
|
||||||
Для персонального VPN сервера обычно достаточно самой минимальной конфигурации, но с безлимитным трафиком или
|
|
||||||
с большим лимитом по трафику (терабайты). Важен и тип VPS. OpenVZ подойдёт для OpenVPN, но
|
с большим лимитом по трафику (терабайты). Важен и тип VPS. OpenVZ подойдёт для OpenVPN, но
|
||||||
вы не поднимете на нем WireGuard, IPsec, то есть все, что требует kernel mode.
|
вы не поднимете на нем WireGuard, IPsec, то есть все, что требует kernel mode.
|
||||||
Для kernel mode требуется тип виртуализации, предполагающий запуск полноценного экземпляра ОС linux
|
Для kernel mode требуется тип виртуализации, предполагающий запуск полноценного экземпляра ОС linux
|
||||||
вместе с ядром. Подойдут KVM, Xen, Hyper-V, VMware.
|
вместе с ядром. Подойдут KVM, Xen, Hyper-V, VMware.
|
||||||
|
|
||||||
По цене можно найти предложения, которые будут дешевле готовой VPN услуги, но при этом вы сам хозяин в своей лавке
|
|
||||||
и не рискуете попасть под бан регулятора, разве что «заодно» — под ковровую бомбардировку с баном миллионов IP.
|
|
||||||
Кроме того, если вам совсем все кажется сложным, прочитанное вызывает ступор и вы точно знаете, что ничего
|
|
||||||
из описанного сделать не сможете, то вы сможете хотя бы использовать динамическое перенаправление портов SSH
|
|
||||||
для получения шифрованного SOCKS-прокси и прописать его в браузер. Знания linux не нужны совсем.
|
|
||||||
Это вариант наименее напряжный для чайников, хотя и не самый удобный в использовании.
|
|
||||||
|
|
||||||
## Поддержать разработчика
|
## Поддержать разработчика
|
||||||
|
|
||||||
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
|
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
# this custom script demonstrates how to launch extra nfqws instance limited by ipset. ipv4 only.
|
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
|
||||||
|
|
||||||
# can override in config :
|
# can override in config :
|
||||||
NFQWS_OPT_DESYNC_NFQWS_MY1="${NFQWS_OPT_DESYNC_NFQWS_MY1:---dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-any-protocol}"
|
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_MY1_PORTS=${NFQWS_MY1_PORTS:-6000-6009}
|
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_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_SUBNETS6="${NFQWS_MY1_SUBNETS6:-2a00:1450::/29}"
|
||||||
|
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_SET_NAME=my1nfqws4
|
NFQWS_MY1_NAME4=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_OPT_DESYNC_NFQWS_MY1"
|
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_MY1_OPT"
|
||||||
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
|
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,54 +31,114 @@ zapret_custom_firewall()
|
|||||||
{
|
{
|
||||||
# $1 - 1 - run, 0 - stop
|
# $1 - 1 - run, 0 - stop
|
||||||
|
|
||||||
local f
|
local f4 f6 subnet
|
||||||
local first_packets_only="$ipt_connbytes 1:3"
|
local NFQWS_MY1_PORTS_TCP=$(replace_char - : $NFQWS_MY1_PORTS_TCP)
|
||||||
local NFQWS_MY1_PORTS_IPT=$(replace_char - : $NFQWS_MY1_PORTS)
|
local NFQWS_MY1_PORTS_UDP=$(replace_char - : $NFQWS_MY1_PORTS_UDP)
|
||||||
local dest_set="-m set --match-set $NFQWS_MY1_SET_NAME dst"
|
|
||||||
local subnet
|
|
||||||
|
|
||||||
local DISABLE_IPV6=1
|
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
|
||||||
|
ipset create $NFQWS_MY1_NAME4 $NFQWS_MY1_IPSET_OPT family inet 2>/dev/null
|
||||||
[ "$1" = 1 ] && {
|
ipset flush $NFQWS_MY1_NAME4
|
||||||
ipset create $NFQWS_MY1_SET_NAME hash:net hashsize 8192 maxelem 4096 2>/dev/null
|
for subnet in $NFQWS_MY1_SUBNETS4; do
|
||||||
ipset flush $NFQWS_MY1_SET_NAME
|
echo add $NFQWS_MY1_NAME4 $subnet
|
||||||
for subnet in $NFQWS_MY1_SUBNETS; do
|
done | ipset -! restore
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
f="-p udp -m multiport --dports $NFQWS_MY1_PORTS_IPT"
|
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||||
fw_nfqws_post $1 "$f $first_packets_only $dest_set" "" $QNUM_NFQWS_MY1
|
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||||
|
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_SET_NAME 2>/dev/null
|
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null
|
||||||
|
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zapret_custom_firewall_nft()
|
zapret_custom_firewall_nft()
|
||||||
{
|
{
|
||||||
# stop logic is not required
|
local f4 f6 subnets
|
||||||
|
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
|
||||||
|
|
||||||
local f
|
[ "$DISABLE_IPV4" != 1 ] && {
|
||||||
local first_packets_only="$nft_connbytes 1-3"
|
make_comma_list subnets $NFQWS_MY1_SUBNETS4
|
||||||
local dest_set="ip daddr @$NFQWS_MY1_SET_NAME"
|
nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||||
local subnets
|
nft_flush_set $NFQWS_MY1_NAME4
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
local DISABLE_IPV6=1
|
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||||
|
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||||
make_comma_list subnets $NFQWS_MY1_SUBNETS
|
f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)"
|
||||||
nft_create_set $NFQWS_MY1_SET_NAME "type ipv4_addr; size 4096; auto-merge; flags interval;"
|
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||||
nft_flush_set $NFQWS_MY1_SET_NAME
|
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||||
nft_add_set_element $NFQWS_MY1_SET_NAME "$subnets"
|
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||||
|
}
|
||||||
f="udp dport {$NFQWS_MY1_PORTS}"
|
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||||
nft_fw_nfqws_post "$f $first_packets_only $dest_set" "" $QNUM_NFQWS_MY1
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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_SET_NAME 2>/dev/null
|
nft_del_set $NFQWS_MY1_NAME4 2>/dev/null
|
||||||
|
nft_del_set $NFQWS_MY1_NAME6 2>/dev/null
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ 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
|
||||||
@ -58,7 +57,7 @@ zapret_custom_firewall()
|
|||||||
|
|
||||||
zapret_custom_firewall_nft()
|
zapret_custom_firewall_nft()
|
||||||
{
|
{
|
||||||
local f4 f6 subnet
|
local f4 f6 subnets
|
||||||
|
|
||||||
[ "$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 enabled special systemd notify support.
|
# WARNING ! This makefile target enables 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 enabled special systemd notify support.
|
# WARNING ! This makefile target enables special systemd notify support.
|
||||||
|
|
||||||
# PREPARE
|
# PREPARE
|
||||||
# install build depends
|
# install build depends
|
||||||
|
@ -225,6 +225,28 @@ 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;
|
||||||
@ -236,33 +258,23 @@ 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 0:
|
case IDX_HELP:
|
||||||
case 1:
|
case IDX_H:
|
||||||
PRINT_VER;
|
PRINT_VER;
|
||||||
exithelp();
|
exithelp();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case IDX_4:
|
||||||
params.ipv6 = false;
|
params.ipv6 = false;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case IDX_6:
|
||||||
params.ipv6 = true;
|
params.ipv6 = true;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case IDX_PREFIX_LENGTH:
|
||||||
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)
|
||||||
@ -271,7 +283,7 @@ static void parse_params(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case IDX_V4_THRESHOLD:
|
||||||
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)
|
||||||
{
|
{
|
||||||
@ -279,7 +291,7 @@ static void parse_params(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case IDX_V6_THRESHOLD:
|
||||||
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,25 +467,38 @@ 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;
|
||||||
@ -495,11 +508,11 @@ int main(int argc, char **argv)
|
|||||||
if (v) exithelp();
|
if (v) exithelp();
|
||||||
switch (option_index)
|
switch (option_index)
|
||||||
{
|
{
|
||||||
case 0: /* help */
|
case IDX_HELP:
|
||||||
PRINT_VER;
|
PRINT_VER;
|
||||||
exithelp();
|
exithelp();
|
||||||
break;
|
break;
|
||||||
case 1: /* threads */
|
case IDX_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)
|
||||||
{
|
{
|
||||||
@ -507,7 +520,7 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: /* family */
|
case IDX_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"))
|
||||||
@ -520,25 +533,25 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3: /* verbose */
|
case IDX_VERBOSE:
|
||||||
glob.verbose = '\1';
|
glob.verbose = '\1';
|
||||||
break;
|
break;
|
||||||
case 4: /* stats */
|
case IDX_STATS:
|
||||||
glob.stats_every = optarg ? atoi(optarg) : 0;
|
glob.stats_every = optarg ? atoi(optarg) : 0;
|
||||||
break;
|
break;
|
||||||
case 5: /* log-resolved */
|
case IDX_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 6: /* log-failed */
|
case IDX_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 7: /* dns-make-query */
|
case IDX_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 8: /* dns-parse-query */
|
case IDX_DNS_PARSE_QUERY:
|
||||||
return dns_parse_query();
|
return dns_parse_query();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,8 +143,11 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
}
|
}
|
||||||
else if (tcp_synack_segment(tcphdr))
|
else if (tcp_synack_segment(tcphdr))
|
||||||
{
|
{
|
||||||
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
// ignore SA dups
|
||||||
if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
|
uint32_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))
|
||||||
@ -338,8 +341,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 d_cutoff=%u hostname=%s l7proto=%s\n",
|
printf(" req_retrans=%u cutoff=%u wss_cutoff=%u desync_cutoff=%u dup_cutoff=%u orig_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.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.b_dup_cutoff, t->track.b_orig_mod_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,14 +77,16 @@ 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, autottl;
|
uint8_t incoming_ttl, desync_autottl, orig_autottl, dup_autottl;
|
||||||
|
bool b_autottl_discovered;
|
||||||
|
|
||||||
bool b_cutoff; // mark for deletion
|
bool b_cutoff; // mark for deletion
|
||||||
bool b_wssize_cutoff, b_desync_cutoff;
|
bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_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,6 +38,11 @@ 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);
|
||||||
@ -83,10 +88,22 @@ 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,
|
||||||
@ -116,15 +133,27 @@ 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[0] = 19; // kind
|
tcpopt[t] = 19; // kind
|
||||||
tcpopt[1] = 18; // len
|
tcpopt[t+1] = 18; // len
|
||||||
*(uint32_t*)(tcpopt+2)=random();
|
*(uint32_t*)(tcpopt+t+2)=random();
|
||||||
*(uint32_t*)(tcpopt+6)=random();
|
*(uint32_t*)(tcpopt+t+6)=random();
|
||||||
*(uint32_t*)(tcpopt+10)=random();
|
*(uint32_t*)(tcpopt+t+10)=random();
|
||||||
*(uint32_t*)(tcpopt+14)=random();
|
*(uint32_t*)(tcpopt+t+14)=random();
|
||||||
t=18;
|
t+=18;
|
||||||
}
|
}
|
||||||
if (timestamps || (fooling & FOOL_TS))
|
if (timestamps || (fooling & FOOL_TS))
|
||||||
{
|
{
|
||||||
@ -145,10 +174,12 @@ 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(uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
|
static uint16_t tcpopt_len(bool sack, bool mss, uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
|
||||||
{
|
{
|
||||||
uint16_t t=0;
|
uint16_t t=0;
|
||||||
if (fooling & FOOL_MD5SIG) t=18;
|
if (sack) t+=2;
|
||||||
|
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;
|
||||||
@ -163,11 +194,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, 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, bool DF, 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 = 0;
|
ip->ip_off = DF ? htons(IP_DF) : 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);
|
||||||
@ -190,10 +221,13 @@ 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,
|
||||||
@ -203,7 +237,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(fooling,timestamps,scale_factor);
|
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,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;
|
||||||
@ -212,12 +246,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, ttl, tos, ip_id);
|
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, DF, ttl, tos, ip_id);
|
||||||
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);
|
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);
|
||||||
|
|
||||||
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^=htons(0xBEAF);
|
if (fooling & FOOL_BADSUM) tcp->th_sum^=(uint16_t)(1+random()%0xFFFF);
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
@ -226,6 +260,8 @@ 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,
|
||||||
@ -238,7 +274,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(fooling,timestamps,scale_factor);
|
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,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) +
|
||||||
@ -297,11 +333,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,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
|
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,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^=htons(0xBEAF);
|
if (fooling & FOOL_BADSUM) tcp->th_sum^=(1+random()%0xFFFF);
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
@ -310,10 +346,13 @@ 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,
|
||||||
@ -325,9 +364,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,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,DF,ttl,tos,ip_id,fooling,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,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
|
||||||
false;
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,6 +374,7 @@ 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,
|
||||||
@ -361,7 +401,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, ttl, tos, ip_id);
|
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, DF, 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);
|
||||||
@ -370,7 +410,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^=htons(0xBEAF);
|
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF);
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
@ -459,13 +499,14 @@ 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^=htons(0xBEAF);
|
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF);
|
||||||
|
|
||||||
*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,
|
||||||
@ -477,7 +518,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,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
|
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) :
|
||||||
(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;
|
||||||
@ -601,10 +642,29 @@ bool ip_frag(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
|
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
|
||||||
{
|
{
|
||||||
if (ip) ip->ip_ttl = ttl;
|
if (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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1772,16 +1832,15 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
|
uint8_t hop_count_guess(uint8_t ttl)
|
||||||
// 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)
|
||||||
@ -1791,13 +1850,21 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
path = orig - ttl;
|
return 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;
|
||||||
|
|
||||||
fake = path > attl->delta ? path - attl->delta : attl->min;
|
d = (int)hop_count + attl->delta;
|
||||||
if (fake<attl->min) fake=attl->min;
|
if (d<attl->min) fake=attl->min;
|
||||||
else if (fake>attl->max) fake=attl->max;
|
else if (d>attl->max) fake=attl->max;
|
||||||
|
else fake=(uint8_t)d;
|
||||||
|
|
||||||
if (fake>=path) return 0;
|
if (attl->delta<0 && fake>=hop_count || attl->delta>=0 && fake<hop_count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return fake;
|
return fake;
|
||||||
}
|
}
|
||||||
@ -1849,15 +1916,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
|
||||||
#ifndef __CYGWIN__
|
if ((verdict & VERDICT_MASK)!=VERDICT_DROP)
|
||||||
#ifdef __FreeBSD__
|
#elif defined(__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);
|
||||||
}
|
}
|
||||||
@ -1866,15 +1933,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
|
||||||
#ifndef __CYGWIN__
|
if ((verdict & VERDICT_MASK)!=VERDICT_DROP)
|
||||||
#ifdef __FreeBSD__
|
#elif defined(__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,6 +59,7 @@ 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)
|
||||||
@ -68,10 +69,13 @@ 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,
|
||||||
@ -83,6 +87,8 @@ 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,
|
||||||
@ -97,10 +103,13 @@ 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,
|
||||||
@ -114,6 +123,7 @@ 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,
|
||||||
@ -133,6 +143,7 @@ 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,
|
||||||
@ -162,15 +173,20 @@ 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);
|
||||||
|
|
||||||
void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl);
|
bool 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;
|
||||||
|
|
||||||
@ -242,15 +258,13 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t delta, min, max;
|
int8_t delta;
|
||||||
|
uint8_t min, max;
|
||||||
} autottl;
|
} autottl;
|
||||||
#define AUTOTTL_DEFAULT_DELTA 1
|
|
||||||
#define AUTOTTL_DEFAULT_MIN 3
|
|
||||||
#define AUTOTTL_DEFAULT_MAX 20
|
|
||||||
#define AUTOTTL_ENABLED(a) (!!(a).delta)
|
#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 autottl_guess(uint8_t ttl, const autottl *attl);
|
uint8_t hop_count_guess(uint8_t ttl);
|
||||||
|
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);
|
||||||
|
897
nfq/desync.c
897
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 *ifout, uint8_t *data_pkt, size_t *len_pkt);
|
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, uint8_t *data_pkt, size_t *len_pkt);
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#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,11 +287,13 @@ 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,
|
||||||
|
981
nfq/nfqws.c
981
nfq/nfqws.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "packet_queue.h"
|
#include "packet_queue.h"
|
||||||
|
|
||||||
@ -25,7 +26,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 *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 *ifin,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;
|
||||||
@ -39,13 +40,14 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
|
|||||||
|
|
||||||
rp->dst = *dst;
|
rp->dst = *dst;
|
||||||
rp->fwmark = fwmark;
|
rp->fwmark = fwmark;
|
||||||
if (ifout)
|
if (ifin)
|
||||||
{
|
snprintf(rp->ifin,sizeof(rp->ifin),"%s",ifin);
|
||||||
strncpy(rp->ifout,ifout,sizeof(rp->ifout));
|
|
||||||
rp->ifout[sizeof(rp->ifout)-1]=0;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
rp->ifout[0]=0;
|
*rp->ifin = 0;
|
||||||
|
if (ifout)
|
||||||
|
snprintf(rp->ifout,sizeof(rp->ifout),"%s",ifout);
|
||||||
|
else
|
||||||
|
*rp->ifout = 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 ifout[IFNAMSIZ+1];
|
char ifin[IFNAMSIZ], ifout[IFNAMSIZ];
|
||||||
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 *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 *ifin,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 = 0xFF; // unused
|
dp->desync_ttl6 = dp->dup_ttl6 = dp->orig_mod_ttl6 = 0xFF; // unused
|
||||||
dp->desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
|
dp->desync_badseq_increment = dp->dup_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
|
||||||
dp->desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
|
dp->desync_badseq_ack_increment = dp->dup_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
|
||||||
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = 'n'; // packet number by 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->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,3 +294,12 @@ 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;
|
||||||
|
}
|
||||||
|
39
nfq/params.h
39
nfq/params.h
@ -36,6 +36,19 @@
|
|||||||
#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
|
||||||
@ -82,6 +95,20 @@ 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;
|
||||||
@ -114,9 +141,10 @@ 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;
|
||||||
@ -127,6 +155,7 @@ 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);
|
||||||
@ -168,6 +197,10 @@ 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;
|
||||||
|
|
||||||
|
unsigned int ipcache_lifetime;
|
||||||
|
bool autottl_present,cache_hostname;
|
||||||
|
ip_cache ipcache;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct params_s params;
|
extern struct params_s params;
|
||||||
|
217
nfq/pools.c
217
nfq/pools.c
@ -3,6 +3,7 @@
|
|||||||
#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; \
|
||||||
@ -579,3 +580,219 @@ 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,6 +3,7 @@
|
|||||||
#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"
|
||||||
@ -161,3 +162,43 @@ 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,6 +345,19 @@ 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)
|
||||||
{
|
{
|
||||||
@ -1015,7 +1028,8 @@ 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 &&
|
||||||
data[8]==0 && memcmp(&data[8],&data[9],63)==0; // address is not set in requests
|
!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);
|
||||||
|
// 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,6 +57,7 @@ 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);
|
||||||
|
@ -287,11 +287,13 @@ 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,
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#define FIX_SEG_DEFAULT_MAX_WAIT 50
|
#define FIX_SEG_DEFAULT_MAX_WAIT 50
|
||||||
|
|
||||||
|
#define IPCACHE_LIFETIME 7200
|
||||||
|
|
||||||
enum bindll { unwanted=0, no, prefer, force };
|
enum bindll { unwanted=0, no, prefer, force };
|
||||||
|
|
||||||
#define MAX_BINDS 32
|
#define MAX_BINDS 32
|
||||||
@ -140,6 +142,10 @@ 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,6 +3,7 @@
|
|||||||
#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; \
|
||||||
@ -517,3 +518,277 @@ 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,6 +3,7 @@
|
|||||||
#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"
|
||||||
@ -146,3 +147,55 @@ 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,6 +339,20 @@ 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,6 +53,7 @@ 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);
|
||||||
|
136
tpws/tamper.c
136
tpws/tamper.c
@ -7,6 +7,7 @@
|
|||||||
#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
|
||||||
|
|
||||||
@ -15,6 +16,123 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
@ -70,8 +188,17 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +257,7 @@ 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
|
||||||
@ -139,7 +267,11 @@ 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)
|
||||||
@ -148,15 +280,17 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
ctrack->l7proto=l7proto;
|
ctrack->l7proto=l7proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bDiscoveredHostname = bHaveHost && !ctrack->hostname;
|
bool bDiscoveredHostname = bHaveHost && !ctrack->hostname_discovered;
|
||||||
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,6 +15,7 @@ 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;
|
||||||
|
475
tpws/tpws.c
475
tpws/tpws.c
@ -88,6 +88,12 @@ static void onusr2(int sig)
|
|||||||
HostFailPoolDump(dpl->dp.hostlist_auto_fail_counters);
|
HostFailPoolDump(dpl->dp.hostlist_auto_fail_counters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.cache_hostname)
|
||||||
|
{
|
||||||
|
printf("\nIPCACHE\n");
|
||||||
|
ipcachePrint(¶ms.ipcache);
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +221,8 @@ static void exithelp(void)
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
" --fix-seg=<int>\t\t\t; fix segmentation failures at the cost of possible slowdown. wait up to N msec (default %u)\n"
|
" --fix-seg=<int>\t\t\t; fix segmentation failures at the cost of possible slowdown. wait up to N msec (default %u)\n"
|
||||||
#endif
|
#endif
|
||||||
|
" --ipcache-lifetime=<int>\t\t; time in seconds to keep cached domain name (default %u). 0 = no expiration\n"
|
||||||
|
" --ipcache-hostname=[0|1]\t\t; 1 or no argument enables ip->hostname caching\n"
|
||||||
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
|
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
|
||||||
" --debug-level=0|1|2\t\t\t; specify debug level\n"
|
" --debug-level=0|1|2\t\t\t; specify debug level\n"
|
||||||
" --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
" --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
||||||
@ -272,6 +280,7 @@ static void exithelp(void)
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
FIX_SEG_DEFAULT_MAX_WAIT,
|
FIX_SEG_DEFAULT_MAX_WAIT,
|
||||||
#endif
|
#endif
|
||||||
|
IPCACHE_LIFETIME,
|
||||||
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT
|
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT
|
||||||
);
|
);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -292,6 +301,7 @@ static void cleanup_params(void)
|
|||||||
|
|
||||||
hostlist_files_destroy(¶ms.hostlists);
|
hostlist_files_destroy(¶ms.hostlists);
|
||||||
ipset_files_destroy(¶ms.ipsets);
|
ipset_files_destroy(¶ms.ipsets);
|
||||||
|
ipcacheDestroy(¶ms.ipcache);
|
||||||
}
|
}
|
||||||
static void exithelp_clean(void)
|
static void exithelp_clean(void)
|
||||||
{
|
{
|
||||||
@ -610,6 +620,192 @@ static bool check_oob_disorder(const struct desync_profile *dp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum opt_indices {
|
||||||
|
IDX_HELP,
|
||||||
|
IDX_H,
|
||||||
|
IDX_BIND_ADDR,
|
||||||
|
IDX_BIND_IFACE4,
|
||||||
|
IDX_BIND_IFACE6,
|
||||||
|
IDX_BIND_LINKLOCAL,
|
||||||
|
IDX_BIND_WAIT_IFUP,
|
||||||
|
IDX_BIND_WAIT_IP,
|
||||||
|
IDX_BIND_WAIT_IP_LINKLOCAL,
|
||||||
|
IDX_BIND_WAIT_ONLY,
|
||||||
|
IDX_PORT,
|
||||||
|
IDX_DAEMON,
|
||||||
|
IDX_USER,
|
||||||
|
IDX_UID,
|
||||||
|
IDX_MAXCONN,
|
||||||
|
IDX_MAXFILES,
|
||||||
|
IDX_MAX_ORPHAN_TIME,
|
||||||
|
IDX_IPCACHE_LIFETIME,
|
||||||
|
IDX_IPCACHE_HOSTNAME,
|
||||||
|
IDX_HOSTCASE,
|
||||||
|
IDX_HOSTSPELL,
|
||||||
|
IDX_HOSTDOT,
|
||||||
|
IDX_HOSTNOSPACE,
|
||||||
|
IDX_HOSTPAD,
|
||||||
|
IDX_DOMCASE,
|
||||||
|
IDX_SPLIT_HTTP_REQ,
|
||||||
|
IDX_SPLIT_TLS,
|
||||||
|
IDX_SPLIT_POS,
|
||||||
|
IDX_SPLIT_ANY_PROTOCOL,
|
||||||
|
IDX_DISORDER,
|
||||||
|
IDX_OOB,
|
||||||
|
IDX_OOB_DATA,
|
||||||
|
IDX_METHODSPACE,
|
||||||
|
IDX_METHODEOL,
|
||||||
|
IDX_HOSTTAB,
|
||||||
|
IDX_UNIXEOL,
|
||||||
|
IDX_TLSREC,
|
||||||
|
IDX_TLSREC_POS,
|
||||||
|
IDX_HOSTLIST,
|
||||||
|
IDX_HOSTLIST_DOMAINS,
|
||||||
|
IDX_HOSTLIST_EXCLUDE,
|
||||||
|
IDX_HOSTLIST_EXCLUDE_DOMAINS,
|
||||||
|
IDX_HOSTLIST_AUTO,
|
||||||
|
IDX_HOSTLIST_AUTO_FAIL_THRESHOLD,
|
||||||
|
IDX_HOSTLIST_AUTO_FAIL_TIME,
|
||||||
|
IDX_HOSTLIST_AUTO_DEBUG,
|
||||||
|
IDX_PIDFILE,
|
||||||
|
IDX_DEBUG,
|
||||||
|
IDX_DEBUG_LEVEL,
|
||||||
|
IDX_DRY_RUN,
|
||||||
|
IDX_VERSION,
|
||||||
|
IDX_COMMENT,
|
||||||
|
IDX_LOCAL_RCVBUF,
|
||||||
|
IDX_LOCAL_SNDBUF,
|
||||||
|
IDX_REMOTE_RCVBUF,
|
||||||
|
IDX_REMOTE_SNDBUF,
|
||||||
|
IDX_SOCKS,
|
||||||
|
IDX_NO_RESOLVE,
|
||||||
|
IDX_RESOLVER_THREADS,
|
||||||
|
IDX_SKIP_NODELAY,
|
||||||
|
IDX_TAMPER_START,
|
||||||
|
IDX_TAMPER_CUTOFF,
|
||||||
|
IDX_CONNECT_BIND_ADDR,
|
||||||
|
|
||||||
|
IDX_NEW,
|
||||||
|
IDX_SKIP,
|
||||||
|
IDX_FILTER_L3,
|
||||||
|
IDX_FILTER_TCP,
|
||||||
|
IDX_FILTER_L7,
|
||||||
|
IDX_IPSET,
|
||||||
|
IDX_IPSET_IP,
|
||||||
|
IDX_IPSET_EXCLUDE,
|
||||||
|
IDX_IPSET_EXCLUDE_IP,
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
IDX_ENABLE_PF,
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
IDX_LOCAL_TCP_USER_TIMEOUT,
|
||||||
|
IDX_REMOTE_TCP_USER_TIMEOUT,
|
||||||
|
#elif defined(__linux__)
|
||||||
|
IDX_LOCAL_TCP_USER_TIMEOUT,
|
||||||
|
IDX_REMOTE_TCP_USER_TIMEOUT,
|
||||||
|
IDX_MSS,
|
||||||
|
IDX_FIX_SEG,
|
||||||
|
#ifdef SPLICE_PRESENT
|
||||||
|
IDX_NOSPLICE,
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD, // ignored. for nfqws command line compatibility
|
||||||
|
IDX_LAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
[IDX_HELP] = {"help", no_argument, 0, 0},
|
||||||
|
[IDX_H] = {"h", no_argument, 0, 0},
|
||||||
|
[IDX_BIND_ADDR] = {"bind-addr", required_argument, 0, 0},
|
||||||
|
[IDX_BIND_IFACE4] = {"bind-iface4", required_argument, 0, 0},
|
||||||
|
[IDX_BIND_IFACE6] = {"bind-iface6", required_argument, 0, 0},
|
||||||
|
[IDX_BIND_LINKLOCAL] = {"bind-linklocal", required_argument, 0, 0},
|
||||||
|
[IDX_BIND_WAIT_IFUP] = {"bind-wait-ifup", required_argument, 0, 0},
|
||||||
|
[IDX_BIND_WAIT_IP] = {"bind-wait-ip", required_argument, 0, 0},
|
||||||
|
[IDX_BIND_WAIT_IP_LINKLOCAL] = {"bind-wait-ip-linklocal", required_argument, 0, 0},
|
||||||
|
[IDX_BIND_WAIT_ONLY] = {"bind-wait-only", no_argument, 0, 0},
|
||||||
|
[IDX_PORT] = {"port", required_argument, 0, 0},
|
||||||
|
[IDX_DAEMON] = {"daemon", no_argument, 0, 0},
|
||||||
|
[IDX_USER] = {"user", required_argument, 0, 0},
|
||||||
|
[IDX_UID] = {"uid", required_argument, 0, 0},
|
||||||
|
[IDX_MAXCONN] = {"maxconn", required_argument, 0, 0},
|
||||||
|
[IDX_MAXFILES] = {"maxfiles", required_argument, 0, 0},
|
||||||
|
[IDX_IPCACHE_LIFETIME] = {"ipcache-lifetime", required_argument, 0, 0},
|
||||||
|
[IDX_IPCACHE_HOSTNAME] = {"ipcache-hostname", optional_argument, 0, 0},
|
||||||
|
[IDX_MAX_ORPHAN_TIME] = {"max-orphan-time", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTCASE] = {"hostcase", no_argument, 0, 0},
|
||||||
|
[IDX_HOSTSPELL] = {"hostspell", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTDOT] = {"hostdot", no_argument, 0, 0},
|
||||||
|
[IDX_HOSTNOSPACE] = {"hostnospace", no_argument, 0, 0},
|
||||||
|
[IDX_HOSTPAD] = {"hostpad", required_argument, 0, 0},
|
||||||
|
[IDX_DOMCASE] = {"domcase", no_argument, 0, 0},
|
||||||
|
[IDX_SPLIT_HTTP_REQ] = {"split-http-req", required_argument, 0, 0},
|
||||||
|
[IDX_SPLIT_TLS] = {"split-tls", required_argument, 0, 0},
|
||||||
|
[IDX_SPLIT_POS] = {"split-pos", required_argument, 0, 0},
|
||||||
|
[IDX_SPLIT_ANY_PROTOCOL] = {"split-any-protocol", optional_argument, 0, 0},
|
||||||
|
[IDX_DISORDER] = {"disorder", optional_argument, 0, 0},
|
||||||
|
[IDX_OOB] = {"oob", optional_argument, 0, 0},
|
||||||
|
[IDX_OOB_DATA] = {"oob-data", required_argument, 0, 0},
|
||||||
|
[IDX_METHODSPACE] = {"methodspace", no_argument, 0, 0},
|
||||||
|
[IDX_METHODEOL] = {"methodeol", no_argument, 0, 0},
|
||||||
|
[IDX_HOSTTAB] = {"hosttab", no_argument, 0, 0},
|
||||||
|
[IDX_UNIXEOL] = {"unixeol", no_argument, 0, 0},
|
||||||
|
[IDX_TLSREC] = {"tlsrec", required_argument, 0, 0},
|
||||||
|
[IDX_TLSREC_POS] = {"tlsrec-pos", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTLIST] = {"hostlist", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTLIST_DOMAINS] = {"hostlist-domains", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTLIST_EXCLUDE] = {"hostlist-exclude", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTLIST_EXCLUDE_DOMAINS] = {"hostlist-exclude-domains", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTLIST_AUTO] = {"hostlist-auto", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTLIST_AUTO_FAIL_THRESHOLD] = {"hostlist-auto-fail-threshold", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTLIST_AUTO_FAIL_TIME] = {"hostlist-auto-fail-time", required_argument, 0, 0},
|
||||||
|
[IDX_HOSTLIST_AUTO_DEBUG] = {"hostlist-auto-debug", required_argument, 0, 0},
|
||||||
|
[IDX_PIDFILE] = {"pidfile", required_argument, 0, 0},
|
||||||
|
[IDX_DEBUG] = {"debug", optional_argument, 0, 0},
|
||||||
|
[IDX_DEBUG_LEVEL] = {"debug-level", required_argument, 0, 0},
|
||||||
|
[IDX_DRY_RUN] = {"dry-run", no_argument, 0, 0},
|
||||||
|
[IDX_VERSION] = {"version", no_argument, 0, 0},
|
||||||
|
[IDX_COMMENT] = {"comment", optional_argument, 0, 0},
|
||||||
|
[IDX_LOCAL_RCVBUF] = {"local-rcvbuf", required_argument, 0, 0},
|
||||||
|
[IDX_LOCAL_SNDBUF] = {"local-sndbuf", required_argument, 0, 0},
|
||||||
|
[IDX_REMOTE_RCVBUF] = {"remote-rcvbuf", required_argument, 0, 0},
|
||||||
|
[IDX_REMOTE_SNDBUF] = {"remote-sndbuf", required_argument, 0, 0},
|
||||||
|
[IDX_SOCKS] = {"socks", no_argument, 0, 0},
|
||||||
|
[IDX_NO_RESOLVE] = {"no-resolve", no_argument, 0, 0},
|
||||||
|
[IDX_RESOLVER_THREADS] = {"resolver-threads", required_argument, 0, 0},
|
||||||
|
[IDX_SKIP_NODELAY] = {"skip-nodelay", no_argument, 0, 0},
|
||||||
|
[IDX_TAMPER_START] = {"tamper-start", required_argument, 0, 0},
|
||||||
|
[IDX_TAMPER_CUTOFF] = {"tamper-cutoff", required_argument, 0, 0},
|
||||||
|
[IDX_CONNECT_BIND_ADDR] = {"connect-bind-addr", required_argument, 0, 0},
|
||||||
|
|
||||||
|
[IDX_NEW] = {"new", no_argument, 0, 0},
|
||||||
|
[IDX_SKIP] = {"skip", no_argument, 0, 0},
|
||||||
|
[IDX_FILTER_L3] = {"filter-l3", required_argument, 0, 0},
|
||||||
|
[IDX_FILTER_TCP] = {"filter-tcp", required_argument, 0, 0},
|
||||||
|
[IDX_FILTER_L7] = {"filter-l7", required_argument, 0, 0},
|
||||||
|
[IDX_IPSET] = {"ipset", required_argument, 0, 0},
|
||||||
|
[IDX_IPSET_IP] = {"ipset-ip", required_argument, 0, 0},
|
||||||
|
[IDX_IPSET_EXCLUDE] = {"ipset-exclude", required_argument, 0, 0},
|
||||||
|
[IDX_IPSET_EXCLUDE_IP] = {"ipset-exclude-ip", required_argument, 0, 0},
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
[IDX_ENABLE_PF] = {"enable-pf", no_argument, 0, 0},
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
[IDX_LOCAL_TCP_USER_TIMEOUT] = {"local-tcp-user-timeout", required_argument, 0, 0},
|
||||||
|
[IDX_REMOTE_TCP_USER_TIMEOUT] = {"remote-tcp-user-timeout", required_argument, 0, 0},
|
||||||
|
#elif defined(__linux__)
|
||||||
|
[IDX_LOCAL_TCP_USER_TIMEOUT] = {"local-tcp-user-timeout", required_argument, 0, 0},
|
||||||
|
[IDX_REMOTE_TCP_USER_TIMEOUT] = {"remote-tcp-user-timeout", required_argument, 0, 0},
|
||||||
|
[IDX_MSS] = {"mss", required_argument, 0, 0},
|
||||||
|
[IDX_FIX_SEG] = {"fix-seg", optional_argument, 0, 0},
|
||||||
|
#ifdef SPLICE_PRESENT
|
||||||
|
[IDX_NOSPLICE] = {"nosplice", no_argument, 0, 0},
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
[IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD] = {"hostlist-auto-retrans-threshold", optional_argument, 0, 0},
|
||||||
|
[IDX_LAST] = {NULL, 0, NULL, 0},
|
||||||
|
};
|
||||||
|
|
||||||
void parse_params(int argc, char *argv[])
|
void parse_params(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
@ -622,6 +818,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.maxconn = DEFAULT_MAX_CONN;
|
params.maxconn = DEFAULT_MAX_CONN;
|
||||||
params.max_orphan_time = DEFAULT_MAX_ORPHAN_TIME;
|
params.max_orphan_time = DEFAULT_MAX_ORPHAN_TIME;
|
||||||
params.binds_last = -1;
|
params.binds_last = -1;
|
||||||
|
params.ipcache_lifetime = IPCACHE_LIFETIME;
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
params.tcp_user_timeout_local = DEFAULT_TCP_USER_TIMEOUT_LOCAL;
|
params.tcp_user_timeout_local = DEFAULT_TCP_USER_TIMEOUT_LOCAL;
|
||||||
params.tcp_user_timeout_remote = DEFAULT_TCP_USER_TIMEOUT_REMOTE;
|
params.tcp_user_timeout_remote = DEFAULT_TCP_USER_TIMEOUT_REMOTE;
|
||||||
@ -664,96 +861,6 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const struct option long_options[] = {
|
|
||||||
{ "help",no_argument,0,0 },// optidx=0
|
|
||||||
{ "h",no_argument,0,0 },// optidx=1
|
|
||||||
{ "bind-addr",required_argument,0,0 },// optidx=2
|
|
||||||
{ "bind-iface4",required_argument,0,0 },// optidx=3
|
|
||||||
{ "bind-iface6",required_argument,0,0 },// optidx=4
|
|
||||||
{ "bind-linklocal",required_argument,0,0 },// optidx=5
|
|
||||||
{ "bind-wait-ifup",required_argument,0,0 },// optidx=6
|
|
||||||
{ "bind-wait-ip",required_argument,0,0 },// optidx=7
|
|
||||||
{ "bind-wait-ip-linklocal",required_argument,0,0 },// optidx=8
|
|
||||||
{ "bind-wait-only",no_argument,0,0 },// optidx=9
|
|
||||||
{ "port",required_argument,0,0 },// optidx=10
|
|
||||||
{ "daemon",no_argument,0,0 },// optidx=11
|
|
||||||
{ "user",required_argument,0,0 },// optidx=12
|
|
||||||
{ "uid",required_argument,0,0 },// optidx=13
|
|
||||||
{ "maxconn",required_argument,0,0 },// optidx=14
|
|
||||||
{ "maxfiles",required_argument,0,0 },// optidx=15
|
|
||||||
{ "max-orphan-time",required_argument,0,0 },// optidx=16
|
|
||||||
{ "hostcase",no_argument,0,0 },// optidx=17
|
|
||||||
{ "hostspell",required_argument,0,0 },// optidx=18
|
|
||||||
{ "hostdot",no_argument,0,0 },// optidx=19
|
|
||||||
{ "hostnospace",no_argument,0,0 },// optidx=20
|
|
||||||
{ "hostpad",required_argument,0,0 },// optidx=21
|
|
||||||
{ "domcase",no_argument,0,0 },// optidx=22
|
|
||||||
{ "split-http-req",required_argument,0,0 },// optidx=23
|
|
||||||
{ "split-tls",required_argument,0,0 },// optidx=24
|
|
||||||
{ "split-pos",required_argument,0,0 },// optidx=25
|
|
||||||
{ "split-any-protocol",optional_argument,0,0},// optidx=26
|
|
||||||
{ "disorder",optional_argument,0,0 },// optidx=27
|
|
||||||
{ "oob",optional_argument,0,0 },// optidx=28
|
|
||||||
{ "oob-data",required_argument,0,0 },// optidx=29
|
|
||||||
{ "methodspace",no_argument,0,0 },// optidx=30
|
|
||||||
{ "methodeol",no_argument,0,0 },// optidx=31
|
|
||||||
{ "hosttab",no_argument,0,0 },// optidx=32
|
|
||||||
{ "unixeol",no_argument,0,0 },// optidx=33
|
|
||||||
{ "tlsrec",required_argument,0,0 },// optidx=34
|
|
||||||
{ "tlsrec-pos",required_argument,0,0 },// optidx=35
|
|
||||||
{ "hostlist",required_argument,0,0 },// optidx=36
|
|
||||||
{ "hostlist-domains",required_argument,0,0 },// optidx=37
|
|
||||||
{ "hostlist-exclude",required_argument,0,0 },// optidx=38
|
|
||||||
{ "hostlist-exclude-domains",required_argument,0,0 },// optidx=39
|
|
||||||
{ "hostlist-auto",required_argument,0,0}, // optidx=40
|
|
||||||
{ "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=41
|
|
||||||
{ "hostlist-auto-fail-time",required_argument,0,0}, // optidx=42
|
|
||||||
{ "hostlist-auto-debug",required_argument,0,0}, // optidx=43
|
|
||||||
{ "pidfile",required_argument,0,0 },// optidx=44
|
|
||||||
{ "debug",optional_argument,0,0 },// optidx=45
|
|
||||||
{ "debug-level",required_argument,0,0 },// optidx=46
|
|
||||||
{ "dry-run",no_argument,0,0 },// optidx=47
|
|
||||||
{ "version",no_argument,0,0 },// optidx=48
|
|
||||||
{ "comment",optional_argument,0,0 },// optidx=49
|
|
||||||
{ "local-rcvbuf",required_argument,0,0 },// optidx=50
|
|
||||||
{ "local-sndbuf",required_argument,0,0 },// optidx=51
|
|
||||||
{ "remote-rcvbuf",required_argument,0,0 },// optidx=52
|
|
||||||
{ "remote-sndbuf",required_argument,0,0 },// optidx=53
|
|
||||||
{ "socks",no_argument,0,0 },// optidx=54
|
|
||||||
{ "no-resolve",no_argument,0,0 },// optidx=55
|
|
||||||
{ "resolver-threads",required_argument,0,0 },// optidx=56
|
|
||||||
{ "skip-nodelay",no_argument,0,0 },// optidx=57
|
|
||||||
{ "tamper-start",required_argument,0,0 },// optidx=58
|
|
||||||
{ "tamper-cutoff",required_argument,0,0 },// optidx=59
|
|
||||||
{ "connect-bind-addr",required_argument,0,0 },// optidx=60
|
|
||||||
|
|
||||||
{ "new",no_argument,0,0 }, // optidx=61
|
|
||||||
{ "skip",no_argument,0,0 }, // optidx=62
|
|
||||||
{ "filter-l3",required_argument,0,0 }, // optidx=63
|
|
||||||
{ "filter-tcp",required_argument,0,0 }, // optidx=64
|
|
||||||
{ "filter-l7",required_argument,0,0 }, // optidx=65
|
|
||||||
{ "ipset",required_argument,0,0 }, // optidx=66
|
|
||||||
{ "ipset-ip",required_argument,0,0 }, // optidx=67
|
|
||||||
{ "ipset-exclude",required_argument,0,0 }, // optidx=68
|
|
||||||
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=69
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
|
||||||
{ "enable-pf",no_argument,0,0 },// optidx=69
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=79
|
|
||||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=71
|
|
||||||
#elif defined(__linux__)
|
|
||||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=70
|
|
||||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=71
|
|
||||||
{ "mss",required_argument,0,0 }, // optidx=72
|
|
||||||
{ "fix-seg",optional_argument,0,0 }, // optidx=73
|
|
||||||
#ifdef SPLICE_PRESENT
|
|
||||||
{ "nosplice",no_argument,0,0 }, // optidx=74
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
|
|
||||||
{ 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)
|
if (v)
|
||||||
@ -765,11 +872,11 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
switch (option_index)
|
switch (option_index)
|
||||||
{
|
{
|
||||||
case 0:
|
case IDX_HELP:
|
||||||
case 1:
|
case IDX_H:
|
||||||
exithelp_clean();
|
exithelp_clean();
|
||||||
break;
|
break;
|
||||||
case 2: /* bind-addr */
|
case IDX_BIND_ADDR:
|
||||||
nextbind_clean();
|
nextbind_clean();
|
||||||
{
|
{
|
||||||
char *p = strchr(optarg,'%');
|
char *p = strchr(optarg,'%');
|
||||||
@ -782,19 +889,19 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.binds[params.binds_last].bindaddr[sizeof(params.binds[params.binds_last].bindaddr) - 1] = 0;
|
params.binds[params.binds_last].bindaddr[sizeof(params.binds[params.binds_last].bindaddr) - 1] = 0;
|
||||||
break;
|
break;
|
||||||
case 3: /* bind-iface4 */
|
case IDX_BIND_IFACE4:
|
||||||
nextbind_clean();
|
nextbind_clean();
|
||||||
params.binds[params.binds_last].bind_if6=false;
|
params.binds[params.binds_last].bind_if6=false;
|
||||||
strncpy(params.binds[params.binds_last].bindiface, optarg, sizeof(params.binds[params.binds_last].bindiface));
|
strncpy(params.binds[params.binds_last].bindiface, optarg, sizeof(params.binds[params.binds_last].bindiface));
|
||||||
params.binds[params.binds_last].bindiface[sizeof(params.binds[params.binds_last].bindiface) - 1] = 0;
|
params.binds[params.binds_last].bindiface[sizeof(params.binds[params.binds_last].bindiface) - 1] = 0;
|
||||||
break;
|
break;
|
||||||
case 4: /* bind-iface6 */
|
case IDX_BIND_IFACE6:
|
||||||
nextbind_clean();
|
nextbind_clean();
|
||||||
params.binds[params.binds_last].bind_if6=true;
|
params.binds[params.binds_last].bind_if6=true;
|
||||||
strncpy(params.binds[params.binds_last].bindiface, optarg, sizeof(params.binds[params.binds_last].bindiface));
|
strncpy(params.binds[params.binds_last].bindiface, optarg, sizeof(params.binds[params.binds_last].bindiface));
|
||||||
params.binds[params.binds_last].bindiface[sizeof(params.binds[params.binds_last].bindiface) - 1] = 0;
|
params.binds[params.binds_last].bindiface[sizeof(params.binds[params.binds_last].bindiface) - 1] = 0;
|
||||||
break;
|
break;
|
||||||
case 5: /* bind-linklocal */
|
case IDX_BIND_LINKLOCAL:
|
||||||
checkbind_clean();
|
checkbind_clean();
|
||||||
params.binds[params.binds_last].bindll = true;
|
params.binds[params.binds_last].bindll = true;
|
||||||
if (!strcmp(optarg, "no"))
|
if (!strcmp(optarg, "no"))
|
||||||
@ -811,22 +918,22 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6: /* bind-wait-ifup */
|
case IDX_BIND_WAIT_IFUP:
|
||||||
checkbind_clean();
|
checkbind_clean();
|
||||||
params.binds[params.binds_last].bind_wait_ifup = atoi(optarg);
|
params.binds[params.binds_last].bind_wait_ifup = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 7: /* bind-wait-ip */
|
case IDX_BIND_WAIT_IP:
|
||||||
checkbind_clean();
|
checkbind_clean();
|
||||||
params.binds[params.binds_last].bind_wait_ip = atoi(optarg);
|
params.binds[params.binds_last].bind_wait_ip = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 8: /* bind-wait-ip-linklocal */
|
case IDX_BIND_WAIT_IP_LINKLOCAL:
|
||||||
checkbind_clean();
|
checkbind_clean();
|
||||||
params.binds[params.binds_last].bind_wait_ip_ll = atoi(optarg);
|
params.binds[params.binds_last].bind_wait_ip_ll = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 9: /* bind-wait-only */
|
case IDX_BIND_WAIT_ONLY:
|
||||||
params.bind_wait_only = true;
|
params.bind_wait_only = true;
|
||||||
break;
|
break;
|
||||||
case 10: /* port */
|
case IDX_PORT:
|
||||||
i = atoi(optarg);
|
i = atoi(optarg);
|
||||||
if (i <= 0 || i > 65535)
|
if (i <= 0 || i > 65535)
|
||||||
{
|
{
|
||||||
@ -835,10 +942,10 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.port = (uint16_t)i;
|
params.port = (uint16_t)i;
|
||||||
break;
|
break;
|
||||||
case 11: /* daemon */
|
case IDX_DAEMON:
|
||||||
params.daemon = true;
|
params.daemon = true;
|
||||||
break;
|
break;
|
||||||
case 12: /* user */
|
case IDX_USER:
|
||||||
{
|
{
|
||||||
struct passwd *pwd = getpwnam(optarg);
|
struct passwd *pwd = getpwnam(optarg);
|
||||||
if (!pwd)
|
if (!pwd)
|
||||||
@ -851,7 +958,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.droproot = true;
|
params.droproot = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 13: /* uid */
|
case IDX_UID:
|
||||||
params.gid=0x7FFFFFFF; // default git. drop gid=0
|
params.gid=0x7FFFFFFF; // default git. drop gid=0
|
||||||
params.droproot = true;
|
params.droproot = true;
|
||||||
if (sscanf(optarg,"%u:%u",¶ms.uid,¶ms.gid)<1)
|
if (sscanf(optarg,"%u:%u",¶ms.uid,¶ms.gid)<1)
|
||||||
@ -860,7 +967,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 14: /* maxconn */
|
case IDX_MAXCONN:
|
||||||
params.maxconn = atoi(optarg);
|
params.maxconn = atoi(optarg);
|
||||||
if (params.maxconn <= 0 || params.maxconn > 10000)
|
if (params.maxconn <= 0 || params.maxconn > 10000)
|
||||||
{
|
{
|
||||||
@ -868,7 +975,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 15: /* maxfiles */
|
case IDX_MAXFILES:
|
||||||
params.maxfiles = atoi(optarg);
|
params.maxfiles = atoi(optarg);
|
||||||
if (params.maxfiles < 0)
|
if (params.maxfiles < 0)
|
||||||
{
|
{
|
||||||
@ -876,7 +983,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 16: /* max-orphan-time */
|
case IDX_MAX_ORPHAN_TIME:
|
||||||
params.max_orphan_time = atoi(optarg);
|
params.max_orphan_time = atoi(optarg);
|
||||||
if (params.max_orphan_time < 0)
|
if (params.max_orphan_time < 0)
|
||||||
{
|
{
|
||||||
@ -884,11 +991,21 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 17: /* hostcase */
|
case IDX_IPCACHE_LIFETIME:
|
||||||
|
if (sscanf(optarg, "%u", ¶ms.ipcache_lifetime)!=1)
|
||||||
|
{
|
||||||
|
DLOG_ERR("invalid ipcache-lifetime value\n");
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDX_IPCACHE_HOSTNAME:
|
||||||
|
params.cache_hostname = !optarg || !!atoi(optarg);
|
||||||
|
break;
|
||||||
|
case IDX_HOSTCASE:
|
||||||
dp->hostcase = true;
|
dp->hostcase = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 18: /* hostspell */
|
case IDX_HOSTSPELL:
|
||||||
if (strlen(optarg) != 4)
|
if (strlen(optarg) != 4)
|
||||||
{
|
{
|
||||||
DLOG_ERR("hostspell must be exactly 4 chars long\n");
|
DLOG_ERR("hostspell must be exactly 4 chars long\n");
|
||||||
@ -898,23 +1015,23 @@ void parse_params(int argc, char *argv[])
|
|||||||
memcpy(dp->hostspell, optarg, 4);
|
memcpy(dp->hostspell, optarg, 4);
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 19: /* hostdot */
|
case IDX_HOSTDOT:
|
||||||
dp->hostdot = true;
|
dp->hostdot = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 20: /* hostnospace */
|
case IDX_HOSTNOSPACE:
|
||||||
dp->hostnospace = true;
|
dp->hostnospace = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 21: /* hostpad */
|
case IDX_HOSTPAD:
|
||||||
dp->hostpad = atoi(optarg);
|
dp->hostpad = atoi(optarg);
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 22: /* domcase */
|
case IDX_DOMCASE:
|
||||||
dp->domcase = true;
|
dp->domcase = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 23: /* split-http-req */
|
case IDX_SPLIT_HTTP_REQ:
|
||||||
DLOG_CONDUP("WARNING ! --split-http-req is deprecated. use --split-pos with markers.\n",MAX_SPLITS);
|
DLOG_CONDUP("WARNING ! --split-http-req is deprecated. use --split-pos with markers.\n",MAX_SPLITS);
|
||||||
if (dp->split_count>=MAX_SPLITS)
|
if (dp->split_count>=MAX_SPLITS)
|
||||||
{
|
{
|
||||||
@ -929,7 +1046,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
dp->split_count++;
|
dp->split_count++;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 24: /* split-tls */
|
case IDX_SPLIT_TLS:
|
||||||
// obsolete arg
|
// obsolete arg
|
||||||
DLOG_CONDUP("WARNING ! --split-tls is deprecated. use --split-pos with markers.\n",MAX_SPLITS);
|
DLOG_CONDUP("WARNING ! --split-tls is deprecated. use --split-pos with markers.\n",MAX_SPLITS);
|
||||||
if (dp->split_count>=MAX_SPLITS)
|
if (dp->split_count>=MAX_SPLITS)
|
||||||
@ -945,7 +1062,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
dp->split_count++;
|
dp->split_count++;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 25: /* split-pos */
|
case IDX_SPLIT_POS:
|
||||||
{
|
{
|
||||||
int ct;
|
int ct;
|
||||||
if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct))
|
if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct))
|
||||||
@ -957,10 +1074,10 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 26: /* split-any-protocol */
|
case IDX_SPLIT_ANY_PROTOCOL:
|
||||||
dp->split_any_protocol = true;
|
dp->split_any_protocol = true;
|
||||||
break;
|
break;
|
||||||
case 27: /* disorder */
|
case IDX_DISORDER:
|
||||||
if (optarg)
|
if (optarg)
|
||||||
{
|
{
|
||||||
if (!strcmp(optarg,"http")) dp->disorder_http=true;
|
if (!strcmp(optarg,"http")) dp->disorder_http=true;
|
||||||
@ -981,7 +1098,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 28: /* oob */
|
case IDX_OOB:
|
||||||
if (optarg)
|
if (optarg)
|
||||||
{
|
{
|
||||||
if (!strcmp(optarg,"http")) dp->oob_http=true;
|
if (!strcmp(optarg,"http")) dp->oob_http=true;
|
||||||
@ -1002,7 +1119,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 29: /* oob-data */
|
case IDX_OOB_DATA:
|
||||||
{
|
{
|
||||||
size_t l = strlen(optarg);
|
size_t l = strlen(optarg);
|
||||||
unsigned int bt;
|
unsigned int bt;
|
||||||
@ -1015,23 +1132,23 @@ void parse_params(int argc, char *argv[])
|
|||||||
else dp->oob_byte = (uint8_t)bt;
|
else dp->oob_byte = (uint8_t)bt;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 30: /* methodspace */
|
case IDX_METHODSPACE:
|
||||||
dp->methodspace = true;
|
dp->methodspace = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 31: /* methodeol */
|
case IDX_METHODEOL:
|
||||||
dp->methodeol = true;
|
dp->methodeol = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 32: /* hosttab */
|
case IDX_HOSTTAB:
|
||||||
dp->hosttab = true;
|
dp->hosttab = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 33: /* unixeol */
|
case IDX_UNIXEOL:
|
||||||
dp->unixeol = true;
|
dp->unixeol = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 34: /* tlsrec */
|
case IDX_TLSREC:
|
||||||
if (!parse_split_pos(optarg, &dp->tlsrec) && !parse_tlspos(optarg, &dp->tlsrec))
|
if (!parse_split_pos(optarg, &dp->tlsrec) && !parse_tlspos(optarg, &dp->tlsrec))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid argument for tlsrec\n");
|
DLOG_ERR("Invalid argument for tlsrec\n");
|
||||||
@ -1039,7 +1156,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 35: /* tlsrec-pos */
|
case IDX_TLSREC_POS:
|
||||||
// obsolete arg
|
// obsolete arg
|
||||||
i = atoi(optarg);
|
i = atoi(optarg);
|
||||||
dp->tlsrec.marker = PM_ABS;
|
dp->tlsrec.marker = PM_ABS;
|
||||||
@ -1051,7 +1168,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 36: /* hostlist */
|
case IDX_HOSTLIST:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterHostlist(dp, false, optarg))
|
if (!RegisterHostlist(dp, false, optarg))
|
||||||
{
|
{
|
||||||
@ -1060,7 +1177,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 37: /* hostlist-domains */
|
case IDX_HOSTLIST_DOMAINS:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
|
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
|
||||||
{
|
{
|
||||||
@ -1074,7 +1191,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 38: /* hostlist-exclude */
|
case IDX_HOSTLIST_EXCLUDE:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterHostlist(dp, true, optarg))
|
if (!RegisterHostlist(dp, true, optarg))
|
||||||
{
|
{
|
||||||
@ -1083,7 +1200,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 39: /* hostlist-exclude-domains */
|
case IDX_HOSTLIST_EXCLUDE_DOMAINS:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
|
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
|
||||||
{
|
{
|
||||||
@ -1097,7 +1214,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 40: /* hostlist-auto */
|
case IDX_HOSTLIST_AUTO:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (dp->hostlist_auto)
|
if (dp->hostlist_auto)
|
||||||
{
|
{
|
||||||
@ -1126,7 +1243,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
|
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
|
||||||
break;
|
break;
|
||||||
case 41: /* hostlist-auto-fail-threshold */
|
case IDX_HOSTLIST_AUTO_FAIL_THRESHOLD:
|
||||||
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||||
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
||||||
{
|
{
|
||||||
@ -1134,7 +1251,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 42: /* hostlist-auto-fail-time */
|
case IDX_HOSTLIST_AUTO_FAIL_TIME:
|
||||||
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||||
if (dp->hostlist_auto_fail_time<1)
|
if (dp->hostlist_auto_fail_time<1)
|
||||||
{
|
{
|
||||||
@ -1142,7 +1259,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 43: /* hostlist-auto-debug */
|
case IDX_HOSTLIST_AUTO_DEBUG:
|
||||||
{
|
{
|
||||||
FILE *F = fopen(optarg,"a+t");
|
FILE *F = fopen(optarg,"a+t");
|
||||||
if (!F)
|
if (!F)
|
||||||
@ -1155,11 +1272,11 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
|
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 44: /* pidfile */
|
case IDX_PIDFILE:
|
||||||
strncpy(params.pidfile,optarg,sizeof(params.pidfile));
|
strncpy(params.pidfile,optarg,sizeof(params.pidfile));
|
||||||
params.pidfile[sizeof(params.pidfile)-1]='\0';
|
params.pidfile[sizeof(params.pidfile)-1]='\0';
|
||||||
break;
|
break;
|
||||||
case 45: /* debug */
|
case IDX_DEBUG:
|
||||||
if (optarg)
|
if (optarg)
|
||||||
{
|
{
|
||||||
if (*optarg=='@')
|
if (*optarg=='@')
|
||||||
@ -1193,52 +1310,52 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.debug_target = LOG_TARGET_CONSOLE;
|
params.debug_target = LOG_TARGET_CONSOLE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 46: /* debug-level */
|
case IDX_DEBUG_LEVEL:
|
||||||
params.debug = atoi(optarg);
|
params.debug = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 47: /* dry-run */
|
case IDX_DRY_RUN:
|
||||||
bDry = true;
|
bDry = true;
|
||||||
break;
|
break;
|
||||||
case 48: /* version */
|
case IDX_VERSION:
|
||||||
exit_clean(0);
|
exit_clean(0);
|
||||||
break;
|
break;
|
||||||
case 49: /* comment */
|
case IDX_COMMENT:
|
||||||
break;
|
break;
|
||||||
case 50: /* local-rcvbuf */
|
case IDX_LOCAL_RCVBUF:
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.local_rcvbuf = atoi(optarg)/2;
|
params.local_rcvbuf = atoi(optarg)/2;
|
||||||
#else
|
#else
|
||||||
params.local_rcvbuf = atoi(optarg);
|
params.local_rcvbuf = atoi(optarg);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 51: /* local-sndbuf */
|
case IDX_LOCAL_SNDBUF:
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.local_sndbuf = atoi(optarg)/2;
|
params.local_sndbuf = atoi(optarg)/2;
|
||||||
#else
|
#else
|
||||||
params.local_sndbuf = atoi(optarg);
|
params.local_sndbuf = atoi(optarg);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 52: /* remote-rcvbuf */
|
case IDX_REMOTE_RCVBUF:
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.remote_rcvbuf = atoi(optarg)/2;
|
params.remote_rcvbuf = atoi(optarg)/2;
|
||||||
#else
|
#else
|
||||||
params.remote_rcvbuf = atoi(optarg);
|
params.remote_rcvbuf = atoi(optarg);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 53: /* remote-sndbuf */
|
case IDX_REMOTE_SNDBUF:
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.remote_sndbuf = atoi(optarg)/2;
|
params.remote_sndbuf = atoi(optarg)/2;
|
||||||
#else
|
#else
|
||||||
params.remote_sndbuf = atoi(optarg);
|
params.remote_sndbuf = atoi(optarg);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 54: /* socks */
|
case IDX_SOCKS:
|
||||||
params.proxy_type = CONN_TYPE_SOCKS;
|
params.proxy_type = CONN_TYPE_SOCKS;
|
||||||
break;
|
break;
|
||||||
case 55: /* no-resolve */
|
case IDX_NO_RESOLVE:
|
||||||
params.no_resolve = true;
|
params.no_resolve = true;
|
||||||
break;
|
break;
|
||||||
case 56: /* resolver-threads */
|
case IDX_RESOLVER_THREADS:
|
||||||
params.resolver_threads = atoi(optarg);
|
params.resolver_threads = atoi(optarg);
|
||||||
if (params.resolver_threads<1 || params.resolver_threads>300)
|
if (params.resolver_threads<1 || params.resolver_threads>300)
|
||||||
{
|
{
|
||||||
@ -1246,10 +1363,10 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 57: /* skip-nodelay */
|
case IDX_SKIP_NODELAY:
|
||||||
params.skip_nodelay = true;
|
params.skip_nodelay = true;
|
||||||
break;
|
break;
|
||||||
case 58: /* tamper-start */
|
case IDX_TAMPER_START:
|
||||||
{
|
{
|
||||||
const char *p=optarg;
|
const char *p=optarg;
|
||||||
if (*p=='n')
|
if (*p=='n')
|
||||||
@ -1263,7 +1380,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper_lim = true;
|
params.tamper_lim = true;
|
||||||
break;
|
break;
|
||||||
case 59: /* tamper-cutoff */
|
case IDX_TAMPER_CUTOFF:
|
||||||
{
|
{
|
||||||
const char *p=optarg;
|
const char *p=optarg;
|
||||||
if (*p=='n')
|
if (*p=='n')
|
||||||
@ -1277,7 +1394,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper_lim = true;
|
params.tamper_lim = true;
|
||||||
break;
|
break;
|
||||||
case 60: /* connect-bind-addr */
|
case IDX_CONNECT_BIND_ADDR:
|
||||||
{
|
{
|
||||||
char *p = strchr(optarg,'%');
|
char *p = strchr(optarg,'%');
|
||||||
if (p) *p++=0;
|
if (p) *p++=0;
|
||||||
@ -1305,7 +1422,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case 61: /* new */
|
case IDX_NEW:
|
||||||
if (bSkip)
|
if (bSkip)
|
||||||
{
|
{
|
||||||
dp_clear(dp);
|
dp_clear(dp);
|
||||||
@ -1326,31 +1443,31 @@ void parse_params(int argc, char *argv[])
|
|||||||
anon_hl = anon_hl_exclude = NULL;
|
anon_hl = anon_hl_exclude = NULL;
|
||||||
anon_ips = anon_ips_exclude = NULL;
|
anon_ips = anon_ips_exclude = NULL;
|
||||||
break;
|
break;
|
||||||
case 62: /* skip */
|
case IDX_SKIP:
|
||||||
bSkip = true;
|
bSkip = true;
|
||||||
break;
|
break;
|
||||||
case 63: /* filter-l3 */
|
case IDX_FILTER_L3:
|
||||||
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
||||||
{
|
{
|
||||||
DLOG_ERR("bad value for --filter-l3\n");
|
DLOG_ERR("bad value for --filter-l3\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 64: /* filter-tcp */
|
case IDX_FILTER_TCP:
|
||||||
if (!parse_pf_list(optarg,&dp->pf_tcp))
|
if (!parse_pf_list(optarg,&dp->pf_tcp))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 65: /* filter-l7 */
|
case IDX_FILTER_L7:
|
||||||
if (!parse_l7_list(optarg,&dp->filter_l7))
|
if (!parse_l7_list(optarg,&dp->filter_l7))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 66: /* ipset */
|
case IDX_IPSET:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterIpset(dp, false, optarg))
|
if (!RegisterIpset(dp, false, optarg))
|
||||||
{
|
{
|
||||||
@ -1359,7 +1476,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 67: /* ipset-ip */
|
case IDX_IPSET_IP:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
||||||
{
|
{
|
||||||
@ -1373,7 +1490,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 68: /* ipset-exclude */
|
case IDX_IPSET_EXCLUDE:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!RegisterIpset(dp, true, optarg))
|
if (!RegisterIpset(dp, true, optarg))
|
||||||
{
|
{
|
||||||
@ -1382,7 +1499,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 69: /* ipset-exclude-ip */
|
case IDX_IPSET_EXCLUDE_IP:
|
||||||
if (bSkip) break;
|
if (bSkip) break;
|
||||||
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
||||||
{
|
{
|
||||||
@ -1398,11 +1515,11 @@ void parse_params(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
case 70: /* enable-pf */
|
case IDX_ENABLE_PF:
|
||||||
params.pf_enable = true;
|
params.pf_enable = true;
|
||||||
break;
|
break;
|
||||||
#elif defined(__linux__) || defined(__APPLE__)
|
#elif defined(__linux__) || defined(__APPLE__)
|
||||||
case 70: /* local-tcp-user-timeout */
|
case IDX_LOCAL_TCP_USER_TIMEOUT:
|
||||||
params.tcp_user_timeout_local = atoi(optarg);
|
params.tcp_user_timeout_local = atoi(optarg);
|
||||||
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
|
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
|
||||||
{
|
{
|
||||||
@ -1410,7 +1527,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 71: /* remote-tcp-user-timeout */
|
case IDX_REMOTE_TCP_USER_TIMEOUT:
|
||||||
params.tcp_user_timeout_remote = atoi(optarg);
|
params.tcp_user_timeout_remote = atoi(optarg);
|
||||||
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
|
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
|
||||||
{
|
{
|
||||||
@ -1421,7 +1538,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
case 72: /* mss */
|
case IDX_MSS:
|
||||||
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
|
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
|
||||||
dp->mss = atoi(optarg);
|
dp->mss = atoi(optarg);
|
||||||
if (dp->mss<88 || dp->mss>32767)
|
if (dp->mss<88 || dp->mss>32767)
|
||||||
@ -1430,7 +1547,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 73: /* fix-seg */
|
case IDX_FIX_SEG:
|
||||||
if (!params.fix_seg_avail)
|
if (!params.fix_seg_avail)
|
||||||
{
|
{
|
||||||
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
|
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
|
||||||
@ -1450,7 +1567,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
|
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
|
||||||
break;
|
break;
|
||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
case 74: /* nosplice */
|
case IDX_NOSPLICE:
|
||||||
params.nosplice = true;
|
params.nosplice = true;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -1521,6 +1638,9 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!test_list_files())
|
||||||
|
exit_clean(1);
|
||||||
|
|
||||||
if (!LoadAllHostLists())
|
if (!LoadAllHostLists())
|
||||||
{
|
{
|
||||||
DLOG_ERR("hostlists load failed\n");
|
DLOG_ERR("hostlists load failed\n");
|
||||||
@ -1723,14 +1843,6 @@ int main(int argc, char *argv[])
|
|||||||
parse_params(argc, argv);
|
parse_params(argc, argv);
|
||||||
argv=NULL; argc=0;
|
argv=NULL; argc=0;
|
||||||
|
|
||||||
if (params.daemon) daemonize();
|
|
||||||
|
|
||||||
if (*params.pidfile && !writepid(params.pidfile))
|
|
||||||
{
|
|
||||||
DLOG_ERR("could not write pidfile\n");
|
|
||||||
goto exiterr;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&list, 0, sizeof(list));
|
memset(&list, 0, sizeof(list));
|
||||||
for(i=0;i<=params.binds_last;i++) listen_fd[i]=-1;
|
for(i=0;i<=params.binds_last;i++) listen_fd[i]=-1;
|
||||||
|
|
||||||
@ -1962,6 +2074,18 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.cache_hostname) VPRINT("ipcache lifetime %us\n", params.ipcache_lifetime);
|
||||||
|
DLOG_CONDUP(params.proxy_type==CONN_TYPE_SOCKS ? "socks mode\n" : "transparent proxy mode\n");
|
||||||
|
if (!params.tamper) DLOG_CONDUP("TCP proxy mode (no tampering)\n");
|
||||||
|
|
||||||
|
if (params.daemon) daemonize();
|
||||||
|
|
||||||
|
if (*params.pidfile && !writepid(params.pidfile))
|
||||||
|
{
|
||||||
|
DLOG_ERR("could not write pidfile\n");
|
||||||
|
goto exiterr;
|
||||||
|
}
|
||||||
|
|
||||||
set_ulimit();
|
set_ulimit();
|
||||||
sec_harden();
|
sec_harden();
|
||||||
if (params.droproot && !droproot(params.uid,params.gid))
|
if (params.droproot && !droproot(params.uid,params.gid))
|
||||||
@ -1982,9 +2106,6 @@ int main(int argc, char *argv[])
|
|||||||
goto exiterr;
|
goto exiterr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DLOG_CONDUP(params.proxy_type==CONN_TYPE_SOCKS ? "socks mode\n" : "transparent proxy mode\n");
|
|
||||||
if (!params.tamper) DLOG_CONDUP("TCP proxy mode (no tampering)\n");
|
|
||||||
|
|
||||||
signal(SIGHUP, onhup);
|
signal(SIGHUP, onhup);
|
||||||
signal(SIGUSR2, onusr2);
|
signal(SIGUSR2, onusr2);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user