Compare commits

..

No commits in common. "master" and "v70.6" have entirely different histories.

26 changed files with 785 additions and 1824 deletions

View File

@ -341,12 +341,6 @@ netcat_test()
} }
} }
tpws_can_fix_seg()
{
# fix-seg requires kernel 4.6+
"$TPWS" --port 1 --dry-run --fix-seg >/dev/null 2>/dev/null
}
check_system() check_system()
{ {
echo \* checking system echo \* checking system
@ -361,14 +355,7 @@ check_system()
Linux) Linux)
PKTWS="$NFQWS" PKTWS="$NFQWS"
PKTWSD=nfqws PKTWSD=nfqws
if [ -x "$TPWS" ] ; then
if tpws_can_fix_seg ; then
echo tpws supports --fix-seg on this system
FIX_SEG='--fix-seg' FIX_SEG='--fix-seg'
else
echo tpws does not support --fix-seg on this system
fi
fi
linux_fwtype linux_fwtype
[ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || { [ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || {
echo firewall type $FWTYPE not supported in $UNAME echo firewall type $FWTYPE not supported in $UNAME

View File

@ -111,14 +111,6 @@ unprepare_route_localnet()
set_route_localnet 0 "$@" set_route_localnet 0 "$@"
} }
get_uevent_devtype()
{
local DEVTYPE INTERFACE IFINDEX OF_NAME OF_FULLNAME OF_COMPATIBLE_N
[ -f "/sys/class/net/$1/uevent" ] && {
. "/sys/class/net/$1/uevent"
echo -n $DEVTYPE
}
}
resolve_lower_devices() resolve_lower_devices()
{ {
# $1 - bridge interface name # $1 - bridge interface name

View File

@ -320,7 +320,7 @@ nft_fill_ifsets()
# $5 - space separated wan physical interface names (optional) # $5 - space separated wan physical interface names (optional)
# $6 - space separated wan6 physical interface names (optional) # $6 - space separated wan6 physical interface names (optional)
local script i j ALLDEVS devs b local script i j ALLDEVS devs
# if large sets exist nft works very ineffectively # if large sets exist nft works very ineffectively
# looks like it analyzes the whole table blob to find required data pieces # looks like it analyzes the whole table blob to find required data pieces
@ -348,18 +348,15 @@ flush set inet $ZAPRET_NFT_TABLE lanif"
nft_create_or_update_flowtable 'offload' 2>/dev/null nft_create_or_update_flowtable 'offload' 2>/dev/null
# then add elements. some of them can cause error because unsupported # then add elements. some of them can cause error because unsupported
for i in $ALLDEVS; do for i in $ALLDEVS; do
# first try to add interface itself
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
# bridge members must be added instead of the bridge itself # bridge members must be added instead of the bridge itself
# some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not # some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not
b=
devs=$(resolve_lower_devices $i) devs=$(resolve_lower_devices $i)
for j in $devs; do for j in $devs; do
# do not display error if addition failed # do not display error if addition failed
nft_create_or_update_flowtable 'offload' $j && b=1 2>/dev/null nft_create_or_update_flowtable 'offload' $j 2>/dev/null
done done
[ -n "$b" ] || {
# no lower devices added ? try to add interface itself
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
}
done done
;; ;;
esac esac

View File

@ -481,8 +481,3 @@ nfqws: update default TLS ClientHello fake. firefox 136.0.4 finger, no kyber, SN
nfqws: multiple mods for multiple TLS fakes nfqws: multiple mods for multiple TLS fakes
init.d: remove 50-discord init.d: remove 50-discord
blockcheck: use tpws --fix-seg on linux for multiple splits blockcheck: use tpws --fix-seg on linux for multiple splits
v70.7
nfqws,tpws: debug tls version, alpn, ech
nfqws: --dpi-desync-fake-tls=! means default tls fake

View File

@ -1,4 +1,4 @@
# zapret v70.7 # zapret v70.6
# 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). '!' = standard fake --dpi-desync-fake-tls=<filename>|0xHEX ; file containing fake TLS ClientHello (for https)
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap --dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload --dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload --dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload

View File

@ -1,4 +1,4 @@
# zapret v70.7 # zapret v70.6
# ВНИМАНИЕ, остерегайтесь мошенников # ВНИМАНИЕ, остерегайтесь мошенников
@ -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

View File

@ -1,29 +1,19 @@
# this custom script demonstrates how to launch extra nfqws instance limited by ipset # this custom script demonstrates how to launch extra nfqws instance limited by ipset. ipv4 only.
# can override in config : # can override in config :
NFQWS_MY1_OPT="${NFQWS_MY1_OPT:---filter-udp=* --dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-any-protocol --new --filter-tcp=* --dpi-desync=multisplit}" NFQWS_OPT_DESYNC_NFQWS_MY1="${NFQWS_OPT_DESYNC_NFQWS_MY1:---dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-any-protocol}"
NFQWS_MY1_SUBNETS4="${NFQWS_MY1_SUBNETS4:-173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 64.233.160.0/19 172.217.0.0/16}" NFQWS_MY1_PORTS=${NFQWS_MY1_PORTS:-6000-6009}
NFQWS_MY1_SUBNETS6="${NFQWS_MY1_SUBNETS6:-2a00:1450::/29}" NFQWS_MY1_SUBNETS="${NFQWS_MY1_SUBNETS:-34.0.48.0/21 34.0.56.0/23 34.0.59.0/24 34.0.60.0/24 34.0.62.0/23}"
NFQWS_MY1_PORTS_TCP=${NFQWS_MY1_PORTS_TCP:-$NFQWS_PORTS_TCP}
NFQWS_MY1_PORTS_UDP=${NFQWS_MY1_PORTS_UDP:-$NFQWS_PORTS_UDP}
NFQWS_MY1_TCP_PKT_OUT=${NFQWS_MY1_TCP_PKT_OUT:-$NFQWS_TCP_PKT_OUT}
NFQWS_MY1_UDP_PKT_OUT=${NFQWS_MY1_UDP_PKT_OUT:-$NFQWS_UDP_PKT_OUT}
NFQWS_MY1_TCP_PKT_IN=${NFQWS_MY1_TCP_PKT_IN:-$NFQWS_TCP_PKT_IN}
NFQWS_MY1_UDP_PKT_IN=${NFQWS_MY1_UDP_PKT_IN:-$NFQWS_UDP_PKT_IN}
NFQWS_MY1_IPSET_SIZE=${NFQWS_MY1_IPSET_SIZE:-4096}
NFQWS_MY1_IPSET_OPT="${NFQWS_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS_MY1_IPSET_SIZE}"
alloc_dnum DNUM_NFQWS_MY1 alloc_dnum DNUM_NFQWS_MY1
alloc_qnum QNUM_NFQWS_MY1 alloc_qnum QNUM_NFQWS_MY1
NFQWS_MY1_NAME4=my1nfqws4 NFQWS_MY1_SET_NAME=my1nfqws4
NFQWS_MY1_NAME6=my1nfqws6
zapret_custom_daemons() zapret_custom_daemons()
{ {
# $1 - 1 - run, 0 - stop # $1 - 1 - run, 0 - stop
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_MY1_OPT" local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_OPT_DESYNC_NFQWS_MY1"
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt" do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
} }
@ -31,114 +21,54 @@ zapret_custom_firewall()
{ {
# $1 - 1 - run, 0 - stop # $1 - 1 - run, 0 - stop
local f4 f6 subnet local f
local NFQWS_MY1_PORTS_TCP=$(replace_char - : $NFQWS_MY1_PORTS_TCP) local first_packets_only="$ipt_connbytes 1:3"
local NFQWS_MY1_PORTS_UDP=$(replace_char - : $NFQWS_MY1_PORTS_UDP) local NFQWS_MY1_PORTS_IPT=$(replace_char - : $NFQWS_MY1_PORTS)
local dest_set="-m set --match-set $NFQWS_MY1_SET_NAME dst"
local subnet
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && { local DISABLE_IPV6=1
ipset create $NFQWS_MY1_NAME4 $NFQWS_MY1_IPSET_OPT family inet 2>/dev/null
ipset flush $NFQWS_MY1_NAME4 [ "$1" = 1 ] && {
for subnet in $NFQWS_MY1_SUBNETS4; do ipset create $NFQWS_MY1_SET_NAME hash:net hashsize 8192 maxelem 4096 2>/dev/null
echo add $NFQWS_MY1_NAME4 $subnet ipset flush $NFQWS_MY1_SET_NAME
done | ipset -! restore for subnet in $NFQWS_MY1_SUBNETS; do
} echo add $NFQWS_MY1_SET_NAME $subnet
[ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && {
ipset create $NFQWS_MY1_NAME6 $NFQWS_MY1_IPSET_OPT family inet6 2>/dev/null
ipset flush $NFQWS_MY1_NAME6
for subnet in $NFQWS_MY1_SUBNETS6; do
echo add $NFQWS_MY1_NAME6 $subnet
done | ipset -! restore done | ipset -! restore
} }
[ -n "$NFQWS_MY1_PORTS_TCP" ] && { f="-p udp -m multiport --dports $NFQWS_MY1_PORTS_IPT"
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && { fw_nfqws_post $1 "$f $first_packets_only $dest_set" "" $QNUM_NFQWS_MY1
f4="-p tcp -m multiport --dports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_OUT -m set --match-set"
f6="$f4 $NFQWS_MY1_NAME6 dst"
f4="$f4 $NFQWS_MY1_NAME4 dst"
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
f4="-p tcp -m multiport --sports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_IN -m set --match-set"
f6="$f4 $NFQWS_MY1_NAME6 src"
f4="$f4 $NFQWS_MY1_NAME4 src"
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
}
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
f4="-p udp -m multiport --dports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_OUT -m set --match-set"
f6="$f4 $NFQWS_MY1_NAME6 dst"
f4="$f4 $NFQWS_MY1_NAME4 dst"
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
f4="-p udp -m multiport --sports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_IN -m set --match-set"
f6="$f4 $NFQWS_MY1_NAME6 src"
f4="$f4 $NFQWS_MY1_NAME4 src"
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
}
[ "$1" = 1 ] || { [ "$1" = 1 ] || {
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null ipset destroy $NFQWS_MY1_SET_NAME 2>/dev/null
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
} }
} }
zapret_custom_firewall_nft() zapret_custom_firewall_nft()
{ {
local f4 f6 subnets # stop logic is not required
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
[ "$DISABLE_IPV4" != 1 ] && { local f
make_comma_list subnets $NFQWS_MY1_SUBNETS4 local first_packets_only="$nft_connbytes 1-3"
nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;" local dest_set="ip daddr @$NFQWS_MY1_SET_NAME"
nft_flush_set $NFQWS_MY1_NAME4 local subnets
nft_add_set_element $NFQWS_MY1_NAME4 "$subnets"
}
[ "$DISABLE_IPV6" != 1 ] && {
make_comma_list subnets $NFQWS_MY1_SUBNETS6
nft_create_set $NFQWS_MY1_NAME6 "type ipv6_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $NFQWS_MY1_NAME6
nft_add_set_element $NFQWS_MY1_NAME6 "$subnets"
}
[ -n "$NFQWS_MY1_PORTS_TCP" ] && { local DISABLE_IPV6=1
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)"
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
f4="tcp sport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_IN)"
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
}
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
f4="udp dport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_OUT)"
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
f4="udp sport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_IN)"
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
}
}
make_comma_list subnets $NFQWS_MY1_SUBNETS
nft_create_set $NFQWS_MY1_SET_NAME "type ipv4_addr; size 4096; auto-merge; flags interval;"
nft_flush_set $NFQWS_MY1_SET_NAME
nft_add_set_element $NFQWS_MY1_SET_NAME "$subnets"
f="udp dport {$NFQWS_MY1_PORTS}"
nft_fw_nfqws_post "$f $first_packets_only $dest_set" "" $QNUM_NFQWS_MY1
}
zapret_custom_firewall_nft_flush() zapret_custom_firewall_nft_flush()
{ {
# this function is called after all nft fw rules are deleted # this function is called after all nft fw rules are deleted
# however sets are not deleted. it's desired to clear sets here. # however sets are not deleted. it's desired to clear sets here.
nft_del_set $NFQWS_MY1_NAME4 2>/dev/null nft_del_set $NFQWS_MY1_SET_NAME 2>/dev/null
nft_del_set $NFQWS_MY1_NAME6 2>/dev/null
} }

View File

@ -28,6 +28,7 @@ zapret_custom_firewall()
local f4 f6 subnet local f4 f6 subnet
local PORTS_IPT=$(replace_char - : $TPWS_MY1_PORTS) local PORTS_IPT=$(replace_char - : $TPWS_MY1_PORTS)
local dest_set="-m set --match-set $TPWS_MY1_NAME4 dst"
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && { [ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
ipset create $TPWS_MY1_NAME4 $TPWS_MY1_IPSET_OPT family inet 2>/dev/null ipset create $TPWS_MY1_NAME4 $TPWS_MY1_IPSET_OPT family inet 2>/dev/null
@ -57,7 +58,7 @@ zapret_custom_firewall()
zapret_custom_firewall_nft() zapret_custom_firewall_nft()
{ {
local f4 f6 subnets local f4 f6 subnet
[ "$DISABLE_IPV4" != 1 ] && { [ "$DISABLE_IPV4" != 1 ] && {
make_comma_list subnets $TPWS_MY1_SUBNETS4 make_comma_list subnets $TPWS_MY1_SUBNETS4

View File

@ -1,7 +1,7 @@
# Example systemd service unit for nfqws. Adjust for your installation. # Example systemd service unit for nfqws. Adjust for your installation.
# WARNING ! This unit requires to compile nfqws using `make systemd` # WARNING ! This unit requires to compile nfqws using `make systemd`
# WARNING ! This makefile target enables special systemd notify support. # WARNING ! This makefile target enabled special systemd notify support.
# PREPARE # PREPARE
# install build depends # install build depends

View File

@ -1,7 +1,7 @@
# Example systemd service unit for tpws. Adjust for your installation. # Example systemd service unit for tpws. Adjust for your installation.
# WARNING ! This unit requires to compile tpws using `make systemd` # WARNING ! This unit requires to compile tpws using `make systemd`
# WARNING ! This makefile target enables special systemd notify support. # WARNING ! This makefile target enabled special systemd notify support.
# PREPARE # PREPARE
# install build depends # install build depends

View File

@ -225,28 +225,6 @@ static void exithelp(void)
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__) #define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif #endif
enum opt_indices {
IDX_HELP,
IDX_H,
IDX_4,
IDX_6,
IDX_PREFIX_LENGTH,
IDX_V4_THRESHOLD,
IDX_V6_THRESHOLD,
IDX_LAST,
};
static const struct option long_options[] = {
[IDX_HELP] = {"help", no_argument, 0, 0},
[IDX_H] = {"h", no_argument, 0, 0},
[IDX_4] = {"4", no_argument, 0, 0},
[IDX_6] = {"6", no_argument, 0, 0},
[IDX_PREFIX_LENGTH] = {"prefix-length", required_argument, 0, 0},
[IDX_V4_THRESHOLD] = {"v4-threshold", required_argument, 0, 0},
[IDX_V6_THRESHOLD] = {"v6-threshold", required_argument, 0, 0},
[IDX_LAST] = {NULL, 0, NULL, 0},
};
static void parse_params(int argc, char *argv[]) static void parse_params(int argc, char *argv[])
{ {
int option_index = 0; int option_index = 0;
@ -258,23 +236,33 @@ static void parse_params(int argc, char *argv[])
params.pctdiv = DEFAULT_PCTDIV; params.pctdiv = DEFAULT_PCTDIV;
params.v6_threshold = DEFAULT_V6_THRESHOLD; params.v6_threshold = DEFAULT_V6_THRESHOLD;
const struct option long_options[] = {
{ "help",no_argument,0,0 },// optidx=0
{ "h",no_argument,0,0 },// optidx=1
{ "4",no_argument,0,0 },// optidx=2
{ "6",no_argument,0,0 },// optidx=3
{ "prefix-length",required_argument,0,0 },// optidx=4
{ "v4-threshold",required_argument,0,0 },// optidx=5
{ "v6-threshold",required_argument,0,0 },// optidx=6
{ NULL,0,NULL,0 }
};
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{ {
if (v) exithelp(); if (v) exithelp();
switch (option_index) switch (option_index)
{ {
case IDX_HELP: case 0:
case IDX_H: case 1:
PRINT_VER; PRINT_VER;
exithelp(); exithelp();
break; break;
case IDX_4: case 2:
params.ipv6 = false; params.ipv6 = false;
break; break;
case IDX_6: case 3:
params.ipv6 = true; params.ipv6 = true;
break; break;
case IDX_PREFIX_LENGTH: case 4:
i = sscanf(optarg,"%u-%u",&plen1,&plen2); i = sscanf(optarg,"%u-%u",&plen1,&plen2);
if (i == 1) plen2 = plen1; if (i == 1) plen2 = plen1;
if (i<=0 || plen2<plen1 || !plen1 || !plen2) if (i<=0 || plen2<plen1 || !plen1 || !plen2)
@ -283,7 +271,7 @@ static void parse_params(int argc, char *argv[])
exit(1); exit(1);
} }
break; break;
case IDX_V4_THRESHOLD: case 5:
i = sscanf(optarg, "%u/%u", &params.pctmult, &params.pctdiv); i = sscanf(optarg, "%u/%u", &params.pctmult, &params.pctdiv);
if (i!=2 || params.pctdiv<2 || params.pctmult<1 || params.pctmult>=params.pctdiv) if (i!=2 || params.pctdiv<2 || params.pctmult<1 || params.pctmult>=params.pctdiv)
{ {
@ -291,7 +279,7 @@ static void parse_params(int argc, char *argv[])
exit(1); exit(1);
} }
break; break;
case IDX_V6_THRESHOLD: case 6:
i = sscanf(optarg, "%u", &params.v6_threshold); i = sscanf(optarg, "%u", &params.v6_threshold);
if (i != 1 || params.v6_threshold<1) if (i != 1 || params.v6_threshold<1)
{ {

View File

@ -467,38 +467,25 @@ static void exithelp(void)
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__) #define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif #endif
enum opt_indices {
IDX_HELP,
IDX_THREADS,
IDX_FAMILY,
IDX_VERBOSE,
IDX_STATS,
IDX_LOG_RESOLVED,
IDX_LOG_FAILED,
IDX_DNS_MAKE_QUERY,
IDX_DNS_PARSE_QUERY,
IDX_LAST,
};
static const struct option long_options[] = {
[IDX_HELP] = {"help", no_argument, 0, 0},
[IDX_THREADS] = {"threads", required_argument, 0, 0},
[IDX_FAMILY] = {"family", required_argument, 0, 0},
[IDX_VERBOSE] = {"verbose", no_argument, 0, 0},
[IDX_STATS] = {"stats", required_argument, 0, 0},
[IDX_LOG_RESOLVED] = {"log-resolved", required_argument, 0, 0},
[IDX_LOG_FAILED] = {"log-failed", required_argument, 0, 0},
[IDX_DNS_MAKE_QUERY] = {"dns-make-query", required_argument, 0, 0},
[IDX_DNS_PARSE_QUERY] = {"dns-parse-query", no_argument, 0, 0},
[IDX_LAST] = {NULL, 0, NULL, 0},
};
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int r, v, option_index = 0; int r, v, option_index = 0;
char fn1[256],fn2[256]; char fn1[256],fn2[256];
char dom[256]; char dom[256];
static const struct option long_options[] = {
{"help",no_argument,0,0}, // optidx=0
{"threads",required_argument,0,0}, // optidx=1
{"family",required_argument,0,0}, // optidx=2
{"verbose",no_argument,0,0}, // optidx=3
{"stats",required_argument,0,0}, // optidx=4
{"log-resolved",required_argument,0,0}, // optidx=5
{"log-failed",required_argument,0,0}, // optidx=6
{"dns-make-query",required_argument,0,0}, // optidx=7
{"dns-parse-query",no_argument,0,0}, // optidx=8
{NULL,0,NULL,0}
};
memset(&glob, 0, sizeof(glob)); memset(&glob, 0, sizeof(glob));
*fn1 = *fn2 = *dom = 0; *fn1 = *fn2 = *dom = 0;
glob.family = FAMILY4; glob.family = FAMILY4;
@ -508,11 +495,11 @@ int main(int argc, char **argv)
if (v) exithelp(); if (v) exithelp();
switch (option_index) switch (option_index)
{ {
case IDX_HELP: case 0: /* help */
PRINT_VER; PRINT_VER;
exithelp(); exithelp();
break; break;
case IDX_THREADS: case 1: /* threads */
glob.threads = optarg ? atoi(optarg) : 0; glob.threads = optarg ? atoi(optarg) : 0;
if (glob.threads <= 0 || glob.threads > 100) if (glob.threads <= 0 || glob.threads > 100)
{ {
@ -520,7 +507,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
break; break;
case IDX_FAMILY: case 2: /* family */
if (!strcmp(optarg, "4")) if (!strcmp(optarg, "4"))
glob.family = FAMILY4; glob.family = FAMILY4;
else if (!strcmp(optarg, "6")) else if (!strcmp(optarg, "6"))
@ -533,25 +520,25 @@ int main(int argc, char **argv)
return 1; return 1;
} }
break; break;
case IDX_VERBOSE: case 3: /* verbose */
glob.verbose = '\1'; glob.verbose = '\1';
break; break;
case IDX_STATS: case 4: /* stats */
glob.stats_every = optarg ? atoi(optarg) : 0; glob.stats_every = optarg ? atoi(optarg) : 0;
break; break;
case IDX_LOG_RESOLVED: case 5: /* log-resolved */
strncpy(fn1,optarg,sizeof(fn1)); strncpy(fn1,optarg,sizeof(fn1));
fn1[sizeof(fn1)-1] = 0; fn1[sizeof(fn1)-1] = 0;
break; break;
case IDX_LOG_FAILED: case 6: /* log-failed */
strncpy(fn2,optarg,sizeof(fn2)); strncpy(fn2,optarg,sizeof(fn2));
fn2[sizeof(fn2)-1] = 0; fn2[sizeof(fn2)-1] = 0;
break; break;
case IDX_DNS_MAKE_QUERY: case 7: /* dns-make-query */
strncpy(dom,optarg,sizeof(dom)); strncpy(dom,optarg,sizeof(dom));
dom[sizeof(dom)-1] = 0; dom[sizeof(dom)-1] = 0;
break; break;
case IDX_DNS_PARSE_QUERY: case 8: /* dns-parse-query */
return dns_parse_query(); return dns_parse_query();
} }
} }

View File

@ -143,11 +143,8 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
} }
else if (tcp_synack_segment(tcphdr)) else if (tcp_synack_segment(tcphdr))
{ {
// ignore SA dups if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
uint32_t seq0 = ntohl(tcphdr->th_ack)-1; if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
if (t->state!=SYN && t->seq0!=seq0)
ConntrackReInitTrack(t); // erase current entry
if (!t->seq0) t->seq0 = seq0;
t->ack0 = ntohl(tcphdr->th_seq); t->ack0 = ntohl(tcphdr->th_seq);
} }
else if (tcphdr->th_flags & (TH_FIN|TH_RST)) else if (tcphdr->th_flags & (TH_FIN|TH_RST))
@ -341,8 +338,8 @@ void ConntrackPoolDump(const t_conntrack *p)
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u", printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
t->track.seq_last, t->track.pos_orig, t->track.seq_last, t->track.pos_orig,
t->track.ack_last, t->track.pos_reply); t->track.ack_last, t->track.pos_reply);
printf(" req_retrans=%u cutoff=%u wss_cutoff=%u desync_cutoff=%u dup_cutoff=%u orig_cutoff=%u hostname=%s l7proto=%s\n", printf(" req_retrans=%u cutoff=%u wss_cutoff=%u d_cutoff=%u hostname=%s l7proto=%s\n",
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff, t->track.b_dup_cutoff, t->track.b_orig_mod_cutoff, t->track.hostname, l7proto_str(t->track.l7proto)); t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
}; };
} }

View File

@ -80,7 +80,7 @@ typedef struct
uint8_t incoming_ttl, autottl; uint8_t incoming_ttl, autottl;
bool b_cutoff; // mark for deletion bool b_cutoff; // mark for deletion
bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff; bool b_wssize_cutoff, b_desync_cutoff;
t_l7proto l7proto; t_l7proto l7proto;
bool l7proto_discovered; bool l7proto_discovered;

View File

@ -38,11 +38,6 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
return htons(ntohs(netorder_value)+cpuorder_increment); return htons(ntohs(netorder_value)+cpuorder_increment);
} }
bool ip_has_df(const struct ip *ip)
{
return ip && !!(ntohs(ip->ip_off) & IP_DF);
}
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind) uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
{ {
uint8_t *t = (uint8_t*)(tcp+1); uint8_t *t = (uint8_t*)(tcp+1);
@ -88,22 +83,10 @@ bool tcp_has_fastopen(const struct tcphdr *tcp)
opt = tcp_find_option((struct tcphdr*)tcp, 254); opt = tcp_find_option((struct tcphdr*)tcp, 254);
return opt && opt[1]>=4 && opt[2]==0xF9 && opt[3]==0x89; return opt && opt[1]>=4 && opt[2]==0xF9 && opt[3]==0x89;
} }
uint16_t tcp_find_mss(struct tcphdr *tcp)
{
uint8_t *t = tcp_find_option(tcp,2);
return (t && t[1]==4) ? *(uint16_t*)(t+2) : 0;
}
bool tcp_has_sack(struct tcphdr *tcp)
{
uint8_t *t = tcp_find_option(tcp,4);
return !!t;
}
// n prefix (nsport, nwsize) means network byte order // n prefix (nsport, nwsize) means network byte order
static void fill_tcphdr( static void fill_tcphdr(
struct tcphdr *tcp, uint32_t fooling, uint8_t tcp_flags, struct tcphdr *tcp, uint32_t fooling, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nsport, uint16_t ndport, uint16_t nsport, uint16_t ndport,
uint16_t nwsize, uint8_t scale_factor, uint16_t nwsize, uint8_t scale_factor,
@ -133,27 +116,15 @@ static void fill_tcphdr(
tcp_flags &= ~TH_ACK; tcp_flags &= ~TH_ACK;
*((uint8_t*)tcp+13)= tcp_flags; *((uint8_t*)tcp+13)= tcp_flags;
tcp->th_win = nwsize; tcp->th_win = nwsize;
if (nmss)
{
tcpopt[t++] = 2; // kind
tcpopt[t++] = 4; // len
*(uint16_t*)(tcpopt+t) = nmss;
t+=2;
}
if (sack)
{
tcpopt[t++] = 4; // kind
tcpopt[t++] = 2; // len
}
if (fooling & FOOL_MD5SIG) if (fooling & FOOL_MD5SIG)
{ {
tcpopt[t] = 19; // kind tcpopt[0] = 19; // kind
tcpopt[t+1] = 18; // len tcpopt[1] = 18; // len
*(uint32_t*)(tcpopt+t+2)=random(); *(uint32_t*)(tcpopt+2)=random();
*(uint32_t*)(tcpopt+t+6)=random(); *(uint32_t*)(tcpopt+6)=random();
*(uint32_t*)(tcpopt+t+10)=random(); *(uint32_t*)(tcpopt+10)=random();
*(uint32_t*)(tcpopt+t+14)=random(); *(uint32_t*)(tcpopt+14)=random();
t+=18; t=18;
} }
if (timestamps || (fooling & FOOL_TS)) if (timestamps || (fooling & FOOL_TS))
{ {
@ -174,12 +145,10 @@ static void fill_tcphdr(
tcp->th_off += t>>2; tcp->th_off += t>>2;
tcp->th_sum = 0; tcp->th_sum = 0;
} }
static uint16_t tcpopt_len(bool sack, bool mss, uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor) static uint16_t tcpopt_len(uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
{ {
uint16_t t=0; uint16_t t=0;
if (sack) t+=2; if (fooling & FOOL_MD5SIG) t=18;
if (mss) t+=4;
if (fooling & FOOL_MD5SIG) t+=18;
if ((fooling & FOOL_TS) || timestamps) t+=10; if ((fooling & FOOL_TS) || timestamps) t+=10;
if (scale_factor!=SCALE_NONE) t+=3; if (scale_factor!=SCALE_NONE) t+=3;
return (t+3)&~3; return (t+3)&~3;
@ -194,11 +163,11 @@ static void fill_udphdr(struct udphdr *udp, uint16_t nsport, uint16_t ndport, ui
udp->uh_sum = 0; udp->uh_sum = 0;
} }
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, bool DF, uint8_t ttl, uint8_t tos, uint16_t ip_id) static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl, uint8_t tos, uint16_t ip_id)
{ {
ip->ip_tos = tos; ip->ip_tos = tos;
ip->ip_sum = 0; ip->ip_sum = 0;
ip->ip_off = DF ? htons(IP_DF) : 0; ip->ip_off = 0;
ip->ip_v = 4; ip->ip_v = 4;
ip->ip_hl = 5; ip->ip_hl = 5;
ip->ip_len = htons(pktlen); ip->ip_len = htons(pktlen);
@ -221,13 +190,10 @@ static void fill_ip6hdr(struct ip6_hdr *ip6, const struct in6_addr *src, const s
bool prepare_tcp_segment4( bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -237,7 +203,7 @@ bool prepare_tcp_segment4(
const void *data, uint16_t len, const void *data, uint16_t len,
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,fooling,timestamps,scale_factor); uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
uint16_t ip_payload_len = sizeof(struct tcphdr) + tcpoptlen + len; uint16_t ip_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
uint16_t pktlen = sizeof(struct ip) + ip_payload_len; uint16_t pktlen = sizeof(struct ip) + ip_payload_len;
if (pktlen>*buflen) return false; if (pktlen>*buflen) return false;
@ -246,12 +212,12 @@ bool prepare_tcp_segment4(
struct tcphdr *tcp = (struct tcphdr*)(ip+1); struct tcphdr *tcp = (struct tcphdr*)(ip+1);
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen; uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, DF, ttl, tos, ip_id); fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl, tos, ip_id);
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len); fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len); memcpy(payload,data,len);
tcp4_fix_checksum(tcp,ip_payload_len,&ip->ip_src,&ip->ip_dst); tcp4_fix_checksum(tcp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=(uint16_t)(1+random()%0xFFFF); if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
*buflen = pktlen; *buflen = pktlen;
return true; return true;
@ -260,8 +226,6 @@ bool prepare_tcp_segment4(
bool prepare_tcp_segment6( bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst, const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
@ -274,7 +238,7 @@ bool prepare_tcp_segment6(
const void *data, uint16_t len, const void *data, uint16_t len,
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,fooling,timestamps,scale_factor); uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len; uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
uint16_t ip_payload_len = transport_payload_len + uint16_t ip_payload_len = transport_payload_len +
8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) + 8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) +
@ -333,11 +297,11 @@ bool prepare_tcp_segment6(
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen; uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl, flow_label); fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl, flow_label);
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len); fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len); memcpy(payload,data,len);
tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=(1+random()%0xFFFF); if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
*buflen = pktlen; *buflen = pktlen;
return true; return true;
@ -346,13 +310,10 @@ bool prepare_tcp_segment6(
bool prepare_tcp_segment( bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -364,9 +325,9 @@ bool prepare_tcp_segment(
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ? return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,DF,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) : prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ? (src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) : prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
false; false;
} }
@ -374,7 +335,6 @@ bool prepare_tcp_segment(
// padlen<0 means payload shrinking // padlen<0 means payload shrinking
bool prepare_udp_segment4( bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -401,7 +361,7 @@ bool prepare_udp_segment4(
uint8_t *payload = (uint8_t*)(udp+1); uint8_t *payload = (uint8_t*)(udp+1);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, DF, ttl, tos, ip_id); fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl, tos, ip_id);
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen); fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
memcpy(payload,data,len); memcpy(payload,data,len);
@ -410,7 +370,7 @@ bool prepare_udp_segment4(
else else
memset(payload+len,0,padlen); memset(payload+len,0,padlen);
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst); udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF); if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
*buflen = pktlen; *buflen = pktlen;
return true; return true;
@ -499,14 +459,13 @@ bool prepare_udp_segment6(
else else
memset(payload+len,0,padlen); memset(payload+len,0,padlen);
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF); if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
*buflen = pktlen; *buflen = pktlen;
return true; return true;
} }
bool prepare_udp_segment( bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -518,7 +477,7 @@ bool prepare_udp_segment(
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ? return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,DF,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) : prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ? (src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) : prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
false; false;
@ -642,29 +601,10 @@ bool ip_frag(
return false; return false;
} }
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl) void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
{ {
if (ttl) if (ip) ip->ip_ttl = ttl;
{ if (ip6) ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
if (ip)
{
if (ip->ip_ttl!=ttl)
{
ip->ip_ttl = ttl;
ip4_fix_checksum(ip);
return true;
}
}
else if (ip6)
{
if (ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim!=ttl)
{
ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
return true;
}
}
}
return false;
} }
@ -1837,7 +1777,6 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
uint8_t autottl_guess(uint8_t ttl, const autottl *attl) uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
{ {
uint8_t orig, path, fake; uint8_t orig, path, fake;
int d;
// 18.65.168.125 ( cloudfront ) 255 // 18.65.168.125 ( cloudfront ) 255
// 157.254.246.178 128 // 157.254.246.178 128
@ -1854,13 +1793,11 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
path = orig - ttl; path = orig - ttl;
d = (int)path + attl->delta; fake = path > attl->delta ? path - attl->delta : attl->min;
if (d<attl->min) fake=attl->min; if (fake<attl->min) fake=attl->min;
else if (d>attl->max) fake=attl->max; else if (fake>attl->max) fake=attl->max;
else fake=(uint8_t)d;
if (attl->delta<0 && fake>=path || attl->delta>=0 && fake<path) if (fake>=path) return 0;
return 0;
return fake; return fake;
} }
@ -1912,15 +1849,15 @@ void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transpo
{ {
if (!(verdict & VERDICT_NOCSUM)) if (!(verdict & VERDICT_NOCSUM))
{ {
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad // always fix csum for windivert. original can be partial or bad
if ((verdict & VERDICT_MASK)!=VERDICT_DROP) #ifndef __CYGWIN__
#elif defined(__FreeBSD__) #ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum // FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else #else
// if original packet was tampered earlier it needs checksum fixed // if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif #endif
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr); tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
} }
@ -1929,15 +1866,15 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
{ {
if (!(verdict & VERDICT_NOCSUM)) if (!(verdict & VERDICT_NOCSUM))
{ {
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad // always fix csum for windivert. original can be partial or bad
if ((verdict & VERDICT_MASK)!=VERDICT_DROP) #ifndef __CYGWIN__
#elif defined(__FreeBSD__) #ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum // FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else #else
// if original packet was tampered earlier it needs checksum fixed // if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif #endif
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr); udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
} }

View File

@ -59,7 +59,6 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
#define VERDICT_DROP 2 #define VERDICT_DROP 2
#define VERDICT_MASK 3 #define VERDICT_MASK 3
#define VERDICT_NOCSUM 4 #define VERDICT_NOCSUM 4
#define VERDICT_GARBAGE 8
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0) #define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
#define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0) #define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
@ -69,13 +68,10 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
bool prepare_tcp_segment4( bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -87,8 +83,6 @@ bool prepare_tcp_segment4(
bool prepare_tcp_segment6( bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst, const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
@ -103,13 +97,10 @@ bool prepare_tcp_segment6(
bool prepare_tcp_segment( bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -123,7 +114,6 @@ bool prepare_tcp_segment(
bool prepare_udp_segment4( bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -143,7 +133,6 @@ bool prepare_udp_segment6(
uint8_t *buf, size_t *buflen); uint8_t *buf, size_t *buflen);
bool prepare_udp_segment( bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -173,20 +162,15 @@ bool ip_frag(
uint8_t *pkt1, size_t *pkt1_size, uint8_t *pkt1, size_t *pkt1_size,
uint8_t *pkt2, size_t *pkt2_size); uint8_t *pkt2, size_t *pkt2_size);
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl); void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl);
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport); void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport);
void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst); void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind); uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
uint32_t *tcp_find_timestamps(struct tcphdr *tcp); uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp); uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
uint16_t tcp_find_mss(struct tcphdr *tcp);
bool tcp_has_sack(struct tcphdr *tcp);
bool tcp_has_fastopen(const struct tcphdr *tcp); bool tcp_has_fastopen(const struct tcphdr *tcp);
bool ip_has_df(const struct ip *ip);
#ifdef __CYGWIN__ #ifdef __CYGWIN__
extern uint32_t w_win32_error; extern uint32_t w_win32_error;
@ -258,10 +242,9 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
typedef struct typedef struct
{ {
int8_t delta; uint8_t delta, min, max;
uint8_t min, max;
} autottl; } autottl;
#define AUTOTTL_DEFAULT_DELTA -1 #define AUTOTTL_DEFAULT_DELTA 1
#define AUTOTTL_DEFAULT_MIN 3 #define AUTOTTL_DEFAULT_MIN 3
#define AUTOTTL_DEFAULT_MAX 20 #define AUTOTTL_DEFAULT_MAX 20
#define AUTOTTL_ENABLED(a) (!!(a).delta) #define AUTOTTL_ENABLED(a) (!!(a).delta)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -187,10 +187,10 @@ void dp_init(struct desync_profile *dp)
dp->desync_repeats = 1; dp->desync_repeats = 1;
dp->fake_syndata_size = 16; dp->fake_syndata_size = 16;
dp->wscale=-1; // default - dont change scale factor (client) dp->wscale=-1; // default - dont change scale factor (client)
dp->desync_ttl6 = dp->dup_ttl6 = dp->orig_mod_ttl6 = 0xFF; // unused dp->desync_ttl6 = 0xFF; // unused
dp->desync_badseq_increment = dp->dup_badseq_increment = BADSEQ_INCREMENT_DEFAULT; dp->desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
dp->desync_badseq_ack_increment = dp->dup_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT; dp->desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = dp->dup_start_mode = dp->dup_cutoff_mode = dp->orig_mod_start_mode = dp->orig_mod_cutoff_mode = 'n'; // packet number by default dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = 'n'; // packet number by default
dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT; dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT;
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT; dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT; dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
@ -294,12 +294,3 @@ bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
return true; return true;
return false; return false;
} }
// check if we need empty outgoing ACK
bool dp_list_need_all_out(struct desync_profile_list_head *head)
{
struct desync_profile_list *dpl;
LIST_FOREACH(dpl, head, next)
if (dpl->dp.dup_repeats || PROFILE_HAS_ORIG_MOD(&dpl->dp))
return true;
return false;
}

View File

@ -82,18 +82,6 @@ struct desync_profile
int split_count; int split_count;
struct proto_pos seqovl; struct proto_pos seqovl;
char dup_start_mode, dup_cutoff_mode; // n - packets, d - data packets, s - relative sequence
bool dup_replace;
unsigned int dup_start, dup_cutoff;
unsigned int dup_repeats;
uint8_t dup_ttl, dup_ttl6;
uint32_t dup_fooling_mode;
uint32_t dup_badseq_increment, dup_badseq_ack_increment;
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;
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;
@ -126,10 +114,9 @@ struct desync_profile
hostfail_pool *hostlist_auto_fail_counters; hostfail_pool *hostlist_auto_fail_counters;
}; };
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude)) #define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&dp->ips_collection) && !LIST_FIRST(&dp->ips_collection_exclude))
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude)) #define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&dp->ips_collection) && ipset_collection_is_empty(&dp->ips_collection_exclude))
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&(dp)->hl_collection) && hostlist_collection_is_empty(&(dp)->hl_collection_exclude)) #define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&dp->hl_collection) && hostlist_collection_is_empty(&dp->hl_collection_exclude))
#define PROFILE_HAS_ORIG_MOD(dp) ((dp)->orig_mod_ttl || (dp)->orig_mod_ttl6)
struct desync_profile_list { struct desync_profile_list {
struct desync_profile dp; struct desync_profile dp;
@ -140,7 +127,6 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
void dp_entry_destroy(struct desync_profile_list *entry); void dp_entry_destroy(struct desync_profile_list *entry);
void dp_list_destroy(struct desync_profile_list_head *head); void dp_list_destroy(struct desync_profile_list_head *head);
bool dp_list_have_autohostlist(struct desync_profile_list_head *head); bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
bool dp_list_need_all_out(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp); void dp_init(struct desync_profile *dp);
bool dp_fake_defaults(struct desync_profile *dp); bool dp_fake_defaults(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp); void dp_clear(struct desync_profile *dp);

View File

@ -345,19 +345,6 @@ size_t HttpPos(uint8_t posmarker, int16_t pos, const uint8_t *data, size_t sz)
} }
const char *TLSVersionStr(uint16_t tlsver)
{
switch(tlsver)
{
case 0x0301: return "TLS 1.0";
case 0x0302: return "TLS 1.1";
case 0x0303: return "TLS 1.2";
case 0x0304: return "TLS 1.3";
default:
// 0x0a0a, 0x1a1a, ..., 0xfafa
return (((tlsver & 0x0F0F) == 0x0A0A) && ((tlsver>>12)==((tlsver>>4)&0xF))) ? "GREASE" : "UNKNOWN";
}
}
uint16_t TLSRecordDataLen(const uint8_t *data) uint16_t TLSRecordDataLen(const uint8_t *data)
{ {
@ -1028,8 +1015,7 @@ bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len)
return len==74 && return len==74 &&
data[0]==0 && data[1]==1 && data[0]==0 && data[1]==1 &&
data[2]==0 && data[3]==70 && data[2]==0 && data[3]==70 &&
!memcmp(data+8,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",64); data[8]==0 && memcmp(&data[8],&data[9],63)==0; // address is not set in requests
// address is not set in request
} }
bool IsStunMessage(const uint8_t *data, size_t len) bool IsStunMessage(const uint8_t *data, size_t len)
{ {

View File

@ -57,7 +57,6 @@ int HttpReplyCode(const uint8_t *data, size_t len);
// must be pre-checked by IsHttpReply // must be pre-checked by IsHttpReply
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host); bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
const char *TLSVersionStr(uint16_t tlsver);
uint16_t TLSRecordDataLen(const uint8_t *data); uint16_t TLSRecordDataLen(const uint8_t *data);
size_t TLSRecordLen(const uint8_t *data); size_t TLSRecordLen(const uint8_t *data);
bool IsTLSRecordFull(const uint8_t *data, size_t len); bool IsTLSRecordFull(const uint8_t *data, size_t len);

View File

@ -339,20 +339,6 @@ size_t HttpPos(uint8_t posmarker, int16_t pos, const uint8_t *data, size_t sz)
const char *TLSVersionStr(uint16_t tlsver)
{
switch(tlsver)
{
case 0x0301: return "TLS 1.0";
case 0x0302: return "TLS 1.1";
case 0x0303: return "TLS 1.2";
case 0x0304: return "TLS 1.3";
default:
// 0x0a0a, 0x1a1a, ..., 0xfafa
return (((tlsver & 0x0F0F) == 0x0A0A) && ((tlsver>>12)==((tlsver>>4)&0xF))) ? "GREASE" : "UNKNOWN";
}
}
uint16_t TLSRecordDataLen(const uint8_t *data) uint16_t TLSRecordDataLen(const uint8_t *data)
{ {
return pntoh16(data + 3); return pntoh16(data + 3);

View File

@ -53,7 +53,6 @@ int HttpReplyCode(const uint8_t *data, size_t len);
// must be pre-checked by IsHttpReply // must be pre-checked by IsHttpReply
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host); bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
const char *TLSVersionStr(uint16_t tlsver);
uint16_t TLSRecordDataLen(const uint8_t *data); uint16_t TLSRecordDataLen(const uint8_t *data);
size_t TLSRecordLen(const uint8_t *data); size_t TLSRecordLen(const uint8_t *data);
bool IsTLSRecordFull(const uint8_t *data, size_t len); bool IsTLSRecordFull(const uint8_t *data, size_t len);

View File

@ -15,81 +15,6 @@ void packet_debug(const uint8_t *data, size_t sz)
hexdump_limited_dlog(data, sz, PKTDATA_MAXDUMP); VPRINT("\n"); hexdump_limited_dlog(data, sz, PKTDATA_MAXDUMP); VPRINT("\n");
} }
static void TLSDebugHandshake(const uint8_t *tls,size_t sz)
{
if (!params.debug) return;
if (sz<6) return;
const uint8_t *ext;
size_t len,len2;
uint16_t v_handshake=pntoh16(tls+4), v, v2;
VPRINT("TLS handshake version : %s\n",TLSVersionStr(v_handshake));
if (TLSFindExtInHandshake(tls,sz,43,&ext,&len,false))
{
if (len)
{
len2 = ext[0];
if (len2<len)
{
for(ext++,len2&=~1 ; len2 ; len2-=2,ext+=2)
{
v = pntoh16(ext);
VPRINT("TLS supported versions ext : %s\n",TLSVersionStr(v));
}
}
}
}
else
VPRINT("TLS supported versions ext : not present\n");
if (TLSFindExtInHandshake(tls,sz,16,&ext,&len,false))
{
if (len>=2)
{
len2 = pntoh16(ext);
if (len2<=(len-2))
{
char s[32];
for(ext+=2; len2 ;)
{
v = *ext; ext++; len2--;
if (v<=len2)
{
v2 = v<sizeof(s) ? v : sizeof(s)-1;
memcpy(s,ext,v2);
s[v2]=0;
VPRINT("TLS ALPN ext : %s\n",s);
len2-=v;
ext+=v;
}
else
break;
}
}
}
}
else
VPRINT("TLS ALPN ext : not present\n");
VPRINT("TLS ECH ext : %s\n",TLSFindExtInHandshake(tls,sz,65037,NULL,NULL,false) ? "present" : "not present");
}
static void TLSDebug(const uint8_t *tls,size_t sz)
{
if (!params.debug) return;
if (sz<11) return;
VPRINT("TLS record layer version : %s\n",TLSVersionStr(pntoh16(tls+1)));
size_t reclen=TLSRecordLen(tls);
if (reclen<sz) sz=reclen; // correct len if it has more data than the first tls record has
TLSDebugHandshake(tls+5,sz-5);
}
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;
@ -205,7 +130,6 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
{ {
VPRINT("Data block contains TLS ClientHello\n"); VPRINT("Data block contains TLS ClientHello\n");
l7proto=TLS; l7proto=TLS;
TLSDebug(segment,*size);
bHaveHost=TLSHelloExtractHost((uint8_t*)segment,*size,Host,sizeof(Host),false); bHaveHost=TLSHelloExtractHost((uint8_t*)segment,*size,Host,sizeof(Host),false);
} }
else else

View File

@ -610,188 +610,6 @@ 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_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_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;
@ -846,6 +664,96 @@ 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)
@ -857,11 +765,11 @@ void parse_params(int argc, char *argv[])
} }
switch (option_index) switch (option_index)
{ {
case IDX_HELP: case 0:
case IDX_H: case 1:
exithelp_clean(); exithelp_clean();
break; break;
case IDX_BIND_ADDR: case 2: /* bind-addr */
nextbind_clean(); nextbind_clean();
{ {
char *p = strchr(optarg,'%'); char *p = strchr(optarg,'%');
@ -874,19 +782,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 IDX_BIND_IFACE4: case 3: /* 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 IDX_BIND_IFACE6: case 4: /* 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 IDX_BIND_LINKLOCAL: case 5: /* 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"))
@ -903,22 +811,22 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_BIND_WAIT_IFUP: case 6: /* 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 IDX_BIND_WAIT_IP: case 7: /* 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 IDX_BIND_WAIT_IP_LINKLOCAL: case 8: /* 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 IDX_BIND_WAIT_ONLY: case 9: /* bind-wait-only */
params.bind_wait_only = true; params.bind_wait_only = true;
break; break;
case IDX_PORT: case 10: /* port */
i = atoi(optarg); i = atoi(optarg);
if (i <= 0 || i > 65535) if (i <= 0 || i > 65535)
{ {
@ -927,10 +835,10 @@ void parse_params(int argc, char *argv[])
} }
params.port = (uint16_t)i; params.port = (uint16_t)i;
break; break;
case IDX_DAEMON: case 11: /* daemon */
params.daemon = true; params.daemon = true;
break; break;
case IDX_USER: case 12: /* user */
{ {
struct passwd *pwd = getpwnam(optarg); struct passwd *pwd = getpwnam(optarg);
if (!pwd) if (!pwd)
@ -943,7 +851,7 @@ void parse_params(int argc, char *argv[])
params.droproot = true; params.droproot = true;
break; break;
} }
case IDX_UID: case 13: /* 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",&params.uid,&params.gid)<1) if (sscanf(optarg,"%u:%u",&params.uid,&params.gid)<1)
@ -952,7 +860,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_MAXCONN: case 14: /* maxconn */
params.maxconn = atoi(optarg); params.maxconn = atoi(optarg);
if (params.maxconn <= 0 || params.maxconn > 10000) if (params.maxconn <= 0 || params.maxconn > 10000)
{ {
@ -960,7 +868,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_MAXFILES: case 15: /* maxfiles */
params.maxfiles = atoi(optarg); params.maxfiles = atoi(optarg);
if (params.maxfiles < 0) if (params.maxfiles < 0)
{ {
@ -968,7 +876,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_MAX_ORPHAN_TIME: case 16: /* 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)
{ {
@ -976,11 +884,11 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_HOSTCASE: case 17: /* hostcase */
dp->hostcase = true; dp->hostcase = true;
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTSPELL: case 18: /* 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");
@ -990,23 +898,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 IDX_HOSTDOT: case 19: /* hostdot */
dp->hostdot = true; dp->hostdot = true;
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTNOSPACE: case 20: /* hostnospace */
dp->hostnospace = true; dp->hostnospace = true;
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTPAD: case 21: /* hostpad */
dp->hostpad = atoi(optarg); dp->hostpad = atoi(optarg);
params.tamper = true; params.tamper = true;
break; break;
case IDX_DOMCASE: case 22: /* domcase */
dp->domcase = true; dp->domcase = true;
params.tamper = true; params.tamper = true;
break; break;
case IDX_SPLIT_HTTP_REQ: case 23: /* 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)
{ {
@ -1021,7 +929,7 @@ void parse_params(int argc, char *argv[])
dp->split_count++; dp->split_count++;
params.tamper = true; params.tamper = true;
break; break;
case IDX_SPLIT_TLS: case 24: /* 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)
@ -1037,7 +945,7 @@ void parse_params(int argc, char *argv[])
dp->split_count++; dp->split_count++;
params.tamper = true; params.tamper = true;
break; break;
case IDX_SPLIT_POS: case 25: /* 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))
@ -1049,10 +957,10 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_SPLIT_ANY_PROTOCOL: case 26: /* split-any-protocol */
dp->split_any_protocol = true; dp->split_any_protocol = true;
break; break;
case IDX_DISORDER: case 27: /* disorder */
if (optarg) if (optarg)
{ {
if (!strcmp(optarg,"http")) dp->disorder_http=true; if (!strcmp(optarg,"http")) dp->disorder_http=true;
@ -1073,7 +981,7 @@ void parse_params(int argc, char *argv[])
} }
#endif #endif
break; break;
case IDX_OOB: case 28: /* oob */
if (optarg) if (optarg)
{ {
if (!strcmp(optarg,"http")) dp->oob_http=true; if (!strcmp(optarg,"http")) dp->oob_http=true;
@ -1094,7 +1002,7 @@ void parse_params(int argc, char *argv[])
} }
#endif #endif
break; break;
case IDX_OOB_DATA: case 29: /* oob-data */
{ {
size_t l = strlen(optarg); size_t l = strlen(optarg);
unsigned int bt; unsigned int bt;
@ -1107,23 +1015,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 IDX_METHODSPACE: case 30: /* methodspace */
dp->methodspace = true; dp->methodspace = true;
params.tamper = true; params.tamper = true;
break; break;
case IDX_METHODEOL: case 31: /* methodeol */
dp->methodeol = true; dp->methodeol = true;
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTTAB: case 32: /* hosttab */
dp->hosttab = true; dp->hosttab = true;
params.tamper = true; params.tamper = true;
break; break;
case IDX_UNIXEOL: case 33: /* unixeol */
dp->unixeol = true; dp->unixeol = true;
params.tamper = true; params.tamper = true;
break; break;
case IDX_TLSREC: case 34: /* 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");
@ -1131,7 +1039,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_TLSREC_POS: case 35: /* tlsrec-pos */
// obsolete arg // obsolete arg
i = atoi(optarg); i = atoi(optarg);
dp->tlsrec.marker = PM_ABS; dp->tlsrec.marker = PM_ABS;
@ -1143,7 +1051,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTLIST: case 36: /* hostlist */
if (bSkip) break; if (bSkip) break;
if (!RegisterHostlist(dp, false, optarg)) if (!RegisterHostlist(dp, false, optarg))
{ {
@ -1152,7 +1060,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTLIST_DOMAINS: case 37: /* 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)))
{ {
@ -1166,7 +1074,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTLIST_EXCLUDE: case 38: /* hostlist-exclude */
if (bSkip) break; if (bSkip) break;
if (!RegisterHostlist(dp, true, optarg)) if (!RegisterHostlist(dp, true, optarg))
{ {
@ -1175,7 +1083,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTLIST_EXCLUDE_DOMAINS: case 39: /* 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)))
{ {
@ -1189,7 +1097,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_HOSTLIST_AUTO: case 40: /* hostlist-auto */
if (bSkip) break; if (bSkip) break;
if (dp->hostlist_auto) if (dp->hostlist_auto)
{ {
@ -1218,7 +1126,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 IDX_HOSTLIST_AUTO_FAIL_THRESHOLD: case 41: /* 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)
{ {
@ -1226,7 +1134,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_HOSTLIST_AUTO_FAIL_TIME: case 42: /* 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)
{ {
@ -1234,7 +1142,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_HOSTLIST_AUTO_DEBUG: case 43: /* hostlist-auto-debug */
{ {
FILE *F = fopen(optarg,"a+t"); FILE *F = fopen(optarg,"a+t");
if (!F) if (!F)
@ -1247,11 +1155,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 IDX_PIDFILE: case 44: /* 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 IDX_DEBUG: case 45: /* debug */
if (optarg) if (optarg)
{ {
if (*optarg=='@') if (*optarg=='@')
@ -1285,52 +1193,52 @@ void parse_params(int argc, char *argv[])
params.debug_target = LOG_TARGET_CONSOLE; params.debug_target = LOG_TARGET_CONSOLE;
} }
break; break;
case IDX_DEBUG_LEVEL: case 46: /* debug-level */
params.debug = atoi(optarg); params.debug = atoi(optarg);
break; break;
case IDX_DRY_RUN: case 47: /* dry-run */
bDry = true; bDry = true;
break; break;
case IDX_VERSION: case 48: /* version */
exit_clean(0); exit_clean(0);
break; break;
case IDX_COMMENT: case 49: /* comment */
break; break;
case IDX_LOCAL_RCVBUF: case 50: /* local-rcvbuf */
#ifdef __linux__ #ifdef __linux__
params.local_rcvbuf = atoi(optarg)/2; params.local_rcvbuf = atoi(optarg)/2;
#else #else
params.local_rcvbuf = atoi(optarg); params.local_rcvbuf = atoi(optarg);
#endif #endif
break; break;
case IDX_LOCAL_SNDBUF: case 51: /* local-sndbuf */
#ifdef __linux__ #ifdef __linux__
params.local_sndbuf = atoi(optarg)/2; params.local_sndbuf = atoi(optarg)/2;
#else #else
params.local_sndbuf = atoi(optarg); params.local_sndbuf = atoi(optarg);
#endif #endif
break; break;
case IDX_REMOTE_RCVBUF: case 52: /* remote-rcvbuf */
#ifdef __linux__ #ifdef __linux__
params.remote_rcvbuf = atoi(optarg)/2; params.remote_rcvbuf = atoi(optarg)/2;
#else #else
params.remote_rcvbuf = atoi(optarg); params.remote_rcvbuf = atoi(optarg);
#endif #endif
break; break;
case IDX_REMOTE_SNDBUF: case 53: /* remote-sndbuf */
#ifdef __linux__ #ifdef __linux__
params.remote_sndbuf = atoi(optarg)/2; params.remote_sndbuf = atoi(optarg)/2;
#else #else
params.remote_sndbuf = atoi(optarg); params.remote_sndbuf = atoi(optarg);
#endif #endif
break; break;
case IDX_SOCKS: case 54: /* socks */
params.proxy_type = CONN_TYPE_SOCKS; params.proxy_type = CONN_TYPE_SOCKS;
break; break;
case IDX_NO_RESOLVE: case 55: /* no-resolve */
params.no_resolve = true; params.no_resolve = true;
break; break;
case IDX_RESOLVER_THREADS: case 56: /* resolver-threads */
params.resolver_threads = atoi(optarg); params.resolver_threads = atoi(optarg);
if (params.resolver_threads<1 || params.resolver_threads>300) if (params.resolver_threads<1 || params.resolver_threads>300)
{ {
@ -1338,10 +1246,10 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_SKIP_NODELAY: case 57: /* skip-nodelay */
params.skip_nodelay = true; params.skip_nodelay = true;
break; break;
case IDX_TAMPER_START: case 58: /* tamper-start */
{ {
const char *p=optarg; const char *p=optarg;
if (*p=='n') if (*p=='n')
@ -1355,7 +1263,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper_lim = true; params.tamper_lim = true;
break; break;
case IDX_TAMPER_CUTOFF: case 59: /* tamper-cutoff */
{ {
const char *p=optarg; const char *p=optarg;
if (*p=='n') if (*p=='n')
@ -1369,7 +1277,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper_lim = true; params.tamper_lim = true;
break; break;
case IDX_CONNECT_BIND_ADDR: case 60: /* connect-bind-addr */
{ {
char *p = strchr(optarg,'%'); char *p = strchr(optarg,'%');
if (p) *p++=0; if (p) *p++=0;
@ -1397,7 +1305,7 @@ void parse_params(int argc, char *argv[])
break; break;
case IDX_NEW: case 61: /* new */
if (bSkip) if (bSkip)
{ {
dp_clear(dp); dp_clear(dp);
@ -1418,31 +1326,31 @@ void parse_params(int argc, char *argv[])
anon_hl = anon_hl_exclude = NULL; anon_hl = anon_hl_exclude = NULL;
anon_ips = anon_ips_exclude = NULL; anon_ips = anon_ips_exclude = NULL;
break; break;
case IDX_SKIP: case 62: /* skip */
bSkip = true; bSkip = true;
break; break;
case IDX_FILTER_L3: case 63: /* filter-l3 */
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6)) if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{ {
DLOG_ERR("bad value for --filter-l3\n"); DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_FILTER_TCP: case 64: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp)) if (!parse_pf_list(optarg,&dp->pf_tcp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); DLOG_ERR("Invalid port filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_FILTER_L7: case 65: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7)) if (!parse_l7_list(optarg,&dp->filter_l7))
{ {
DLOG_ERR("Invalid l7 filter : %s\n",optarg); DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_IPSET: case 66: /* ipset */
if (bSkip) break; if (bSkip) break;
if (!RegisterIpset(dp, false, optarg)) if (!RegisterIpset(dp, false, optarg))
{ {
@ -1451,7 +1359,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_IPSET_IP: case 67: /* ipset-ip */
if (bSkip) break; if (bSkip) break;
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL))) if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
{ {
@ -1465,7 +1373,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_IPSET_EXCLUDE: case 68: /* ipset-exclude */
if (bSkip) break; if (bSkip) break;
if (!RegisterIpset(dp, true, optarg)) if (!RegisterIpset(dp, true, optarg))
{ {
@ -1474,7 +1382,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case IDX_IPSET_EXCLUDE_IP: case 69: /* ipset-exclude-ip */
if (bSkip) break; if (bSkip) break;
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL))) if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
{ {
@ -1490,11 +1398,11 @@ void parse_params(int argc, char *argv[])
break; break;
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
case IDX_ENABLE_PF: case 70: /* enable-pf */
params.pf_enable = true; params.pf_enable = true;
break; break;
#elif defined(__linux__) || defined(__APPLE__) #elif defined(__linux__) || defined(__APPLE__)
case IDX_LOCAL_TCP_USER_TIMEOUT: case 70: /* local-tcp-user-timeout */
params.tcp_user_timeout_local = atoi(optarg); params.tcp_user_timeout_local = atoi(optarg);
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400) if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
{ {
@ -1502,7 +1410,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_REMOTE_TCP_USER_TIMEOUT: case 71: /* remote-tcp-user-timeout */
params.tcp_user_timeout_remote = atoi(optarg); params.tcp_user_timeout_remote = atoi(optarg);
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400) if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
{ {
@ -1513,7 +1421,7 @@ void parse_params(int argc, char *argv[])
#endif #endif
#if defined(__linux__) #if defined(__linux__)
case IDX_MSS: case 72: /* mss */
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing // this option does not work in any BSD and MacOS. OS may accept but it changes nothing
dp->mss = atoi(optarg); dp->mss = atoi(optarg);
if (dp->mss<88 || dp->mss>32767) if (dp->mss<88 || dp->mss>32767)
@ -1522,7 +1430,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_FIX_SEG: case 73: /* fix-seg */
if (!params.fix_seg_avail) if (!params.fix_seg_avail)
{ {
DLOG_ERR("--fix-seg is supported since kernel 4.6\n"); DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
@ -1542,7 +1450,7 @@ void parse_params(int argc, char *argv[])
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT; params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
break; break;
#ifdef SPLICE_PRESENT #ifdef SPLICE_PRESENT
case IDX_NOSPLICE: case 74: /* nosplice */
params.nosplice = true; params.nosplice = true;
break; break;
#endif #endif