mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-20 16:25:49 +00:00
Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de8845b89d | ||
|
|
f1eae764ab | ||
|
|
03c650b33c | ||
|
|
64b12c51e5 | ||
|
|
2d8e031904 | ||
|
|
28f0cd6e73 | ||
|
|
9a9179a23b | ||
|
|
48123bf1f7 | ||
|
|
ece4e52676 | ||
|
|
1d24d1e040 | ||
|
|
d0fd6b4868 | ||
|
|
328408fa30 | ||
|
|
0343bb248d | ||
|
|
e4dd1574b8 | ||
|
|
1e3486ee14 | ||
|
|
efe7470732 | ||
|
|
8acd5690f4 | ||
|
|
c2e3176a46 | ||
|
|
658252d46a | ||
|
|
5aaf7b3d6c | ||
|
|
031ac7616d | ||
|
|
098417d19f | ||
|
|
2f0a74a11e | ||
|
|
40c37c3448 | ||
|
|
77fb530120 | ||
|
|
faa0274521 | ||
|
|
8a253d3d95 | ||
|
|
0aac2965c1 | ||
|
|
d1128a8bc6 | ||
|
|
e016fc0e42 | ||
|
|
f48ea2f6a7 | ||
|
|
2ab71ab895 | ||
|
|
736e0ba3d4 | ||
|
|
f2ae880c11 | ||
|
|
019f3089c6 | ||
|
|
30d28488c9 | ||
|
|
5bcec4aada | ||
|
|
886fbabcfc | ||
|
|
cd8dbf2a2b | ||
|
|
002742bd03 | ||
|
|
dc2c707c3c | ||
|
|
9630d0a9df | ||
|
|
f4c4d5e558 | ||
|
|
7b37880954 | ||
|
|
6b7738ac16 | ||
|
|
8dec014b50 | ||
|
|
b0ee32f3dc | ||
|
|
0e770ff46d | ||
|
|
14b3aef030 | ||
|
|
004c583595 | ||
|
|
c4818a6a32 | ||
|
|
58d57fed01 | ||
|
|
d6b73fe7e0 | ||
|
|
4867838fce | ||
|
|
4b2551509f | ||
|
|
ed6acb36a1 | ||
|
|
26b80e80b6 | ||
|
|
79b776b5a9 | ||
|
|
3b251b9ee6 | ||
|
|
8c65a966d9 | ||
|
|
9da0b13aa3 | ||
|
|
d7fd491121 | ||
|
|
c60ef399ec | ||
|
|
2abab21e4b | ||
|
|
6190babb99 | ||
|
|
7ce0b4a996 | ||
|
|
053556fe2d | ||
|
|
52571045fe | ||
|
|
db875ed1d4 | ||
|
|
e828864811 | ||
|
|
4404127fa3 | ||
|
|
13e81e4b6f | ||
|
|
a631add2d9 | ||
|
|
26b9b63a20 | ||
|
|
90489fad2f | ||
|
|
d93c243d21 | ||
|
|
65235d71d7 | ||
|
|
fc01e6715f | ||
|
|
1a33d68998 | ||
|
|
dfaa475d2a | ||
|
|
743018423a | ||
|
|
762023f201 | ||
|
|
a296b93b7a | ||
|
|
1c9b3aa1bc | ||
|
|
565fa8e337 | ||
|
|
9fcecd07d1 | ||
|
|
652e271877 | ||
|
|
fc7ed4f4a8 | ||
|
|
e9e5bdc860 | ||
|
|
a2b8300219 | ||
|
|
dfdcfbdf51 | ||
|
|
170ec372fb | ||
|
|
3f073908a6 |
@@ -97,17 +97,19 @@ nft_activate_chain4()
|
|||||||
{
|
{
|
||||||
# $1 - chain name
|
# $1 - chain name
|
||||||
# $2 - saddr/daddr
|
# $2 - saddr/daddr
|
||||||
local b rule markf= act
|
local b rule markf= act flt_ifname
|
||||||
[ "$DISABLE_IPV4" = "1" ] || {
|
[ "$DISABLE_IPV4" = "1" ] || {
|
||||||
eval act="\$${1}_act4"
|
eval act="\$${1}_act4"
|
||||||
[ -n "$act" ] && return
|
[ -n "$act" ] && return
|
||||||
|
|
||||||
b=0
|
b=0
|
||||||
nft_wanif_filter_present && b=1
|
nft_wanif_filter_present && b=1
|
||||||
|
flt_ifname="oifname"
|
||||||
|
starts_with "$1" pre && flt_ifname="iifname"
|
||||||
|
|
||||||
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
||||||
rule="meta mark and $DESYNC_MARK == 0 $markf"
|
rule="meta mark and $DESYNC_MARK == 0 $markf"
|
||||||
[ $b = 1 ] && rule="$rule oifname @wanif"
|
[ $b = 1 ] && rule="$rule $flt_ifname @wanif"
|
||||||
rule="$rule ip $2 != @nozapret jump $1"
|
rule="$rule ip $2 != @nozapret jump $1"
|
||||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||||
|
|
||||||
@@ -118,17 +120,19 @@ nft_activate_chain6()
|
|||||||
{
|
{
|
||||||
# $1 - chain name
|
# $1 - chain name
|
||||||
# $2 - saddr/daddr
|
# $2 - saddr/daddr
|
||||||
local b rule markf=
|
local b rule markf= act flt_ifname
|
||||||
[ "$DISABLE_IPV6" = "1" ] || {
|
[ "$DISABLE_IPV6" = "1" ] || {
|
||||||
eval act="\$${1}_act6"
|
eval act="\$${1}_act6"
|
||||||
[ -n "$act" ] && return
|
[ -n "$act" ] && return
|
||||||
|
|
||||||
b=0
|
b=0
|
||||||
nft_wanif6_filter_present && b=1
|
nft_wanif6_filter_present && b=1
|
||||||
|
flt_ifname="oifname"
|
||||||
|
starts_with "$1" pre && flt_ifname="iifname"
|
||||||
|
|
||||||
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
||||||
rule="meta mark and $DESYNC_MARK == 0 $markf"
|
rule="meta mark and $DESYNC_MARK == 0 $markf"
|
||||||
[ $b = 1 ] && rule="$rule oifname @wanif6"
|
[ $b = 1 ] && rule="$rule $flt_ifname @wanif6"
|
||||||
rule="$rule ip6 $2 != @nozapret6 jump $1"
|
rule="$rule ip6 $2 != @nozapret6 jump $1"
|
||||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
|||||||
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
|
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
|
||||||
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
|
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
|
||||||
# options for auto hostlist
|
# options for auto hostlist
|
||||||
|
# NOTE : in order for these adjustment to work it's required to redirect enough starting packets
|
||||||
|
# NOTE : set PKT_IN, PKT_OUT variables appropriately
|
||||||
AUTOHOSTLIST_INCOMING_MAXSEQ=4096
|
AUTOHOSTLIST_INCOMING_MAXSEQ=4096
|
||||||
AUTOHOSTLIST_RETRANS_MAXSEQ=65536
|
AUTOHOSTLIST_RETRANS_MAXSEQ=32768
|
||||||
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
||||||
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
||||||
AUTOHOSTLIST_FAIL_TIME=60
|
AUTOHOSTLIST_FAIL_TIME=60
|
||||||
@@ -64,11 +66,10 @@ NFQWS2_PORTS_TCP=80,443
|
|||||||
NFQWS2_PORTS_UDP=443
|
NFQWS2_PORTS_UDP=443
|
||||||
# PKT_OUT means connbytes dir original
|
# PKT_OUT means connbytes dir original
|
||||||
# PKT_IN means connbytes dir reply
|
# PKT_IN means connbytes dir reply
|
||||||
# this is --dpi-desync-cutoff=nX kernel mode implementation for linux. it saves a lot of CPU.
|
NFQWS2_TCP_PKT_OUT=20
|
||||||
NFQWS2_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
NFQWS2_TCP_PKT_IN=10
|
||||||
NFQWS2_TCP_PKT_IN=3
|
NFQWS2_UDP_PKT_OUT=5
|
||||||
NFQWS2_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
NFQWS2_UDP_PKT_IN=3
|
||||||
NFQWS2_UDP_PKT_IN=0
|
|
||||||
# redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter
|
# redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter
|
||||||
# normally it's needed only for stateless DPI that matches every packet in a single TCP session
|
# normally it's needed only for stateless DPI that matches every packet in a single TCP session
|
||||||
# typical example are plain HTTP keep alives
|
# typical example are plain HTTP keep alives
|
||||||
|
|||||||
@@ -90,3 +90,18 @@ v0.7
|
|||||||
* nfqws2: push desync.track.pos.dt as float with nsec accuracy
|
* nfqws2: push desync.track.pos.dt as float with nsec accuracy
|
||||||
* zapret-auto: override host autostate key in automate_host_record
|
* zapret-auto: override host autostate key in automate_host_record
|
||||||
* nfqws2: rewrite udp autohostlist failure detector logic
|
* nfqws2: rewrite udp autohostlist failure detector logic
|
||||||
|
|
||||||
|
v0.7.1
|
||||||
|
|
||||||
|
* init.d: nft fix non-working incoming redirect
|
||||||
|
* nfqws2: cancel reasm if server window size is smaller than expected reasm size
|
||||||
|
* nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer
|
||||||
|
* nfqws2: autohostlist reset fail counter if udp_in > threshold
|
||||||
|
* nfqws2: reduced default retrans maxseq to 32768
|
||||||
|
* nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+
|
||||||
|
|
||||||
|
v0.7.2
|
||||||
|
|
||||||
|
* zapret-lib: fix broken is_retransmission()
|
||||||
|
* zapret-auto: add success detector logic
|
||||||
|
* nfqws2: clean lua cutoff on profile change
|
||||||
|
|||||||
1070
docs/manual.md
1070
docs/manual.md
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,49 @@
|
|||||||
-- standard automation/orchestration code
|
-- standard automation/orchestration code
|
||||||
-- this is related to making dynamic strategy decisions without rewriting or altering strategy function code
|
-- this is related to making dynamic strategy decisions without rewriting or altering strategy function code
|
||||||
-- orchestrators can decide which instances to call or not to call or pass them dynamic arguments
|
-- orchestrators can decide which instances to call or not to call or pass them dynamic arguments
|
||||||
-- failure detectors test potential block conditions for orchestrators
|
-- failure and success detectors test potential block conditions for orchestrators
|
||||||
|
|
||||||
|
-- standard host key generator for per-host storage
|
||||||
-- arg: reqhost - require hostname, do not work with ip
|
-- arg: reqhost - require hostname, do not work with ip
|
||||||
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
|
-- arg: nld=N - cut hostname to N level domain. NLD=2 static.intranet.microsoft.com => microsoft.com
|
||||||
function automate_host_record(desync)
|
function standard_hostkey(desync)
|
||||||
local hostkey, askey
|
local hostkey = desync.track and desync.track.hostname
|
||||||
if desync.arg.reqhost then
|
if hostkey then
|
||||||
hostkey = desync.track and desync.track.hostname
|
if desync.arg.nld and tonumber(desync.arg.nld)>0 then
|
||||||
else
|
-- dissect_nld returns nil if domain is invalid or does not have this NLD
|
||||||
hostkey = host_or_ip(desync)
|
-- fall back to original hostkey if it fails
|
||||||
|
local hktemp = dissect_nld(hostkey, tonumber(desync.arg.nld))
|
||||||
|
if hktemp then
|
||||||
|
hostkey = hktemp
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif not desync.arg.reqhost then
|
||||||
|
hostkey = host_ip(desync)
|
||||||
end
|
end
|
||||||
|
-- prevent nld for ip addresses
|
||||||
|
return hostkey
|
||||||
|
end
|
||||||
|
|
||||||
|
-- per-host storage
|
||||||
|
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
|
||||||
|
-- arg: hostkey - hostkey generator function name
|
||||||
|
function automate_host_record(desync)
|
||||||
|
local hostkey, hkf, askey
|
||||||
|
|
||||||
|
if desync.arg.hostkey then
|
||||||
|
if type(_G[desync.arg.hostkey])~="function" then
|
||||||
|
error("automate: invalid hostkey function '"..desync.arg.hostkey.."'")
|
||||||
|
end
|
||||||
|
hkf = _G[desync.arg.hostkey]
|
||||||
|
else
|
||||||
|
hkf = standard_hostkey
|
||||||
|
end
|
||||||
|
hostkey = hkf(desync)
|
||||||
if not hostkey then
|
if not hostkey then
|
||||||
DLOG("automate: host record key unavailable")
|
DLOG("automate: host record key unavailable")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
askey = (desync.arg.key and #desync.arg.key>0) and desync.arg.key or desync.func_instance
|
askey = (desync.arg.key and #desync.arg.key>0) and desync.arg.key or desync.func_instance
|
||||||
DLOG("automate: host record key 'autostate."..askey.."."..hostkey.."'")
|
DLOG("automate: host record key 'autostate."..askey.."."..hostkey.."'")
|
||||||
if not autostate then
|
if not autostate then
|
||||||
@@ -28,6 +57,7 @@ function automate_host_record(desync)
|
|||||||
end
|
end
|
||||||
return autostate[askey][hostkey]
|
return autostate[askey][hostkey]
|
||||||
end
|
end
|
||||||
|
-- per-connection storage
|
||||||
function automate_conn_record(desync)
|
function automate_conn_record(desync)
|
||||||
if not desync.track.lua_state.automate then
|
if not desync.track.lua_state.automate then
|
||||||
desync.track.lua_state.automate = {}
|
desync.track.lua_state.automate = {}
|
||||||
@@ -65,6 +95,13 @@ function automate_failure_counter(hrec, crec, fails, maxtime)
|
|||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
-- resets failure counter if it has started counting
|
||||||
|
function automate_failure_counter_reset(hrec)
|
||||||
|
if hrec.failure_counter then
|
||||||
|
DLOG("automate: failure counter reset")
|
||||||
|
hrec.failure_counter = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- location is url compatible with Location: header
|
-- location is url compatible with Location: header
|
||||||
-- hostname is original hostname
|
-- hostname is original hostname
|
||||||
@@ -78,6 +115,18 @@ function is_dpi_redirect(hostname, location)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function standard_detector_defaults(arg)
|
||||||
|
return {
|
||||||
|
inseq = tonumber(arg.inseq) or 4096,
|
||||||
|
retrans = tonumber(arg.retrans) or 3,
|
||||||
|
maxseq = tonumber(arg.maxseq) or 32768,
|
||||||
|
udp_in = tonumber(arg.udp_in) or 1,
|
||||||
|
udp_out = tonumber(arg.udp_out) or 4,
|
||||||
|
no_http_redirect = arg.no_http_redirect,
|
||||||
|
no_rst = arg.no_rst
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
-- standard failure detector
|
-- standard failure detector
|
||||||
-- works with tcp and udp
|
-- works with tcp and udp
|
||||||
-- detected failures:
|
-- detected failures:
|
||||||
@@ -85,46 +134,34 @@ end
|
|||||||
-- incoming http redirection
|
-- incoming http redirection
|
||||||
-- outgoing retransmissions
|
-- outgoing retransmissions
|
||||||
-- udp too much out with too few in
|
-- udp too much out with too few in
|
||||||
-- arg: seq=<rseq> - tcp: if packet is beyond this relative sequence number treat this connection as successful. default is 64K
|
-- arg: maxseq=<rseq> - tcp: test retransmissions only within this relative sequence. default is 32K
|
||||||
-- arg: retrans=N - tcp: retrans count threshold. default is 3
|
-- arg: retrans=N - tcp: retrans count threshold. default is 3
|
||||||
-- arg: rst=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 1
|
-- arg: inseq=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 4K
|
||||||
-- arg: no_http_redirect - tcp: disable http_reply dpi redirect trigger
|
-- arg: no_http_redirect - tcp: disable http_reply dpi redirect trigger
|
||||||
|
-- arg: no_rst - tcp: disable incoming RST trigger
|
||||||
-- arg: udp_out - udp: >= outgoing udp packets. default is 4
|
-- arg: udp_out - udp: >= outgoing udp packets. default is 4
|
||||||
-- arg: udp_in - udp: with <= incoming udp packets. default is 1
|
-- arg: udp_in - udp: with <= incoming udp packets. default is 1
|
||||||
function standard_failure_detector(desync, crec, arg)
|
function standard_failure_detector(desync, crec)
|
||||||
if crec.nocheck then return false end
|
local arg = standard_detector_defaults(desync.arg)
|
||||||
|
|
||||||
local seq_rst = tonumber(arg.rst) or 1
|
|
||||||
local retrans = tonumber(arg.retrans) or 3
|
|
||||||
local maxseq = tonumber(arg.seq) or 0x10000
|
|
||||||
local udp_in = tonumber(arg.udp_in) or 1
|
|
||||||
local udp_out = tonumber(arg.udp_out) or 4
|
|
||||||
|
|
||||||
local trigger = false
|
local trigger = false
|
||||||
if desync.dis.tcp then
|
if desync.dis.tcp then
|
||||||
local seq = pos_get(desync,'s')
|
local seq = pos_get(desync,'s')
|
||||||
if maxseq and seq>maxseq then
|
|
||||||
DLOG("standard_failure_detector: s"..seq.." is beyond s"..maxseq..". treating connection as successful")
|
|
||||||
crec.nocheck = true
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
if desync.outgoing then
|
if desync.outgoing then
|
||||||
if #desync.dis.payload>0 and retrans and (crec.retrans or 0)<retrans then
|
if #desync.dis.payload>0 and arg.retrans and arg.maxseq>0 and seq<=arg.maxseq and (crec.retrans or 0)<arg.retrans then
|
||||||
if is_retransmission(desync) then
|
if is_retransmission(desync) then
|
||||||
crec.retrans = crec.retrans and (crec.retrans+1) or 1
|
crec.retrans = crec.retrans and (crec.retrans+1) or 1
|
||||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..retrans)
|
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..arg.retrans)
|
||||||
trigger = crec.retrans>=retrans
|
trigger = crec.retrans>=arg.retrans
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if seq_rst and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 then
|
if not arg.no_rst and arg.inseq>0 and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 and seq>=1 then
|
||||||
trigger = seq<=seq_rst
|
trigger = seq<=arg.inseq
|
||||||
if b_debug then
|
if b_debug then
|
||||||
if trigger then
|
if trigger then
|
||||||
DLOG("standard_failure_detector: incoming RST s"..seq.." in range s"..seq_rst)
|
DLOG("standard_failure_detector: incoming RST s"..seq.." in range s"..arg.inseq)
|
||||||
else
|
else
|
||||||
DLOG("standard_failure_detector: not counting incoming RST s"..seq.." beyond s"..seq_rst)
|
DLOG("standard_failure_detector: not counting incoming RST s"..seq.." beyond s"..arg.inseq)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
|
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
|
||||||
@@ -143,13 +180,13 @@ function standard_failure_detector(desync, crec, arg)
|
|||||||
end
|
end
|
||||||
elseif desync.dis.udp then
|
elseif desync.dis.udp then
|
||||||
if desync.outgoing then
|
if desync.outgoing then
|
||||||
if udp_out then
|
if arg.udp_out>0 then
|
||||||
local udp_in = udp_in or 0
|
local pos_out = pos_get(desync,'n',false)
|
||||||
trigger = desync.track.pos.direct.pcounter>=udp_out and desync.track.pos.reverse.pcounter<=udp_in
|
local pos_in = pos_get(desync,'n',true)
|
||||||
|
trigger = pos_out>=arg.udp_out and pos_in<=arg.udp_in
|
||||||
if trigger then
|
if trigger then
|
||||||
crec.nocheck = true
|
|
||||||
if b_debug then
|
if b_debug then
|
||||||
DLOG("standard_failure_detector: udp_out "..desync.track.pos.direct.pcounter..">="..udp_out.." udp_in "..desync.track.pos.reverse.pcounter.."<="..udp_in)
|
DLOG("standard_failure_detector: arg.udp_out "..pos_out..">="..arg.udp_out.." arg.udp_in "..pos_in.."<="..arg.udp_in)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -158,17 +195,101 @@ function standard_failure_detector(desync, crec, arg)
|
|||||||
return trigger
|
return trigger
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- standard success detector
|
||||||
|
-- success means previous failures were temporary and counter should be reset
|
||||||
|
-- detected successes:
|
||||||
|
-- tcp: outgoing seq is beyond 'maxseq' and maxseq>0
|
||||||
|
-- tcp: incoming seq is beyond 'inseq' and inseq>0
|
||||||
|
-- udp: incoming packets count > `udp_in` and `udp_out`>0
|
||||||
|
-- arg: maxseq=<rseq> - tcp: success if outgoing relative sequence is beyond this value. default is 32K
|
||||||
|
-- arg: inseq=<rseq> - tcp: success if incoming relative sequence is beyond this value. default is 4K
|
||||||
|
-- arg: udp_out - udp : must be nil or >0 to test udp_in
|
||||||
|
-- arg: udp_in - udp: if number if incoming packets > udp_in it means success
|
||||||
|
function standard_success_detector(desync, crec)
|
||||||
|
local arg = standard_detector_defaults(desync.arg)
|
||||||
|
if desync.dis.tcp then
|
||||||
|
local seq = pos_get(desync,'s')
|
||||||
|
if desync.outgoing then
|
||||||
|
if arg.maxseq>0 and seq>arg.maxseq then
|
||||||
|
DLOG("standard_success_detector: outgoing s"..seq.." is beyond s"..arg.maxseq..". treating connection as successful")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if arg.inseq>0 and seq>arg.inseq then
|
||||||
|
DLOG("standard_success_detector: incoming s"..seq.." is beyond s"..arg.inseq..". treating connection as successful")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif desync.dis.udp then
|
||||||
|
if not desync.outgoing then
|
||||||
|
local pos = pos_get(desync,'n')
|
||||||
|
if arg.udp_out>0 and pos>arg.udp_in then
|
||||||
|
if b_debug then
|
||||||
|
DLOG("standard_success_detector: arg.udp_in "..pos..">"..arg.udp_in)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- calls success and failure detectors
|
||||||
|
-- resets counter if success is detected
|
||||||
|
-- increases counter if failure is detected
|
||||||
|
-- returns true if failure counter exceeds threshold
|
||||||
|
function automate_failure_check(desync, hrec, crec)
|
||||||
|
if crec.nocheck then return false end
|
||||||
|
|
||||||
|
local failure_detector, success_detector
|
||||||
|
if desync.arg.failure_detector then
|
||||||
|
if type(_G[desync.arg.failure_detector])~="function" then
|
||||||
|
error("automate: invalid failure detector function '"..desync.arg.failure_detector.."'")
|
||||||
|
end
|
||||||
|
failure_detector = _G[desync.arg.failure_detector]
|
||||||
|
else
|
||||||
|
failure_detector = standard_failure_detector
|
||||||
|
end
|
||||||
|
if desync.arg.success_detector then
|
||||||
|
if type(_G[desync.arg.success_detector])~="function" then
|
||||||
|
error("automate: invalid success detector function '"..desync.arg.success_detector.."'")
|
||||||
|
end
|
||||||
|
success_detector = _G[desync.arg.success_detector]
|
||||||
|
else
|
||||||
|
success_detector = standard_success_detector
|
||||||
|
end
|
||||||
|
|
||||||
|
if success_detector(desync, crec) then
|
||||||
|
crec.nocheck = true
|
||||||
|
DLOG("automate: success detected")
|
||||||
|
automate_failure_counter_reset(hrec)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if failure_detector(desync, crec) then
|
||||||
|
crec.nocheck = true
|
||||||
|
DLOG("automate: failure detected")
|
||||||
|
local fails = tonumber(desync.arg.fails) or 3
|
||||||
|
local maxtime = tonumber(desync.arg.time) or 60
|
||||||
|
return automate_failure_counter(hrec, crec, fails, maxtime)
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- circularily change strategy numbers when failure count reaches threshold ('fails')
|
-- circularily change strategy numbers when failure count reaches threshold ('fails')
|
||||||
-- works with tcp only
|
|
||||||
-- this orchestrator requires redirection of incoming traffic to cache RST and http replies !
|
-- this orchestrator requires redirection of incoming traffic to cache RST and http replies !
|
||||||
-- each orchestrated instance must have strategy=N arg, where N starts from 1 and increment without gaps
|
-- each orchestrated instance must have strategy=N arg, where N starts from 1 and increment without gaps
|
||||||
-- if 'final' arg is present in an orchestrated instance it stops rotation
|
-- if 'final' arg is present in an orchestrated instance it stops rotation
|
||||||
-- arg: fails=N - failture count threshold. default is 3
|
-- arg: fails=N - failture count threshold. default is 3
|
||||||
-- arg: time=<sec> - if last failure happened earlier than `maxtime` seconds ago - reset failure counter. default is 60.
|
-- arg: time=<sec> - if last failure happened earlier than `maxtime` seconds ago - reset failure counter. default is 60.
|
||||||
-- arg: reqhost - pass with no tampering if hostname is unavailable
|
-- arg: reqhost - pass with no tampering if hostname is unavailable
|
||||||
-- arg: detector - failure detector function name.
|
-- arg: success_detector - success detector function name
|
||||||
|
-- arg: failure_detector - failure detector function name
|
||||||
-- args for failure detector - see standard_failure_detector or your own detector
|
-- args for failure detector - see standard_failure_detector or your own detector
|
||||||
-- test case: nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s1 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
-- args for success detector - see standard_success_detector or your own detector
|
||||||
|
-- test case: nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s34228 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||||
function circular(ctx, desync)
|
function circular(ctx, desync)
|
||||||
local function count_strategies(hrec)
|
local function count_strategies(hrec)
|
||||||
if not hrec.ctstrategy then
|
if not hrec.ctstrategy then
|
||||||
@@ -223,26 +344,11 @@ function circular(ctx, desync)
|
|||||||
local verdict = VERDICT_PASS
|
local verdict = VERDICT_PASS
|
||||||
if hrec.final~=hrec.nstrategy then
|
if hrec.final~=hrec.nstrategy then
|
||||||
local crec = automate_conn_record(desync)
|
local crec = automate_conn_record(desync)
|
||||||
local fails = tonumber(desync.arg.fails) or 3
|
if automate_failure_check(desync, hrec, crec) then
|
||||||
local maxtime = tonumber(desync.arg.time) or 60
|
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
|
||||||
local failure_detector
|
DLOG("circular: rotate strategy to "..hrec.nstrategy)
|
||||||
if desync.arg.detector then
|
if hrec.nstrategy == hrec.final then
|
||||||
if type(_G[desync.arg.detector])~="function" then
|
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
|
||||||
error("circular: invalid failure detector function '"..desync.arg.detector.."'")
|
|
||||||
end
|
|
||||||
failure_detector = _G[desync.arg.detector]
|
|
||||||
else
|
|
||||||
failure_detector = standard_failure_detector
|
|
||||||
end
|
|
||||||
if failure_detector(desync,crec,desync.arg) then
|
|
||||||
-- failure happened. count failures.
|
|
||||||
if automate_failure_counter(hrec, crec, fails, maxtime) then
|
|
||||||
-- counter reaches threshold. circular strategy change
|
|
||||||
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
|
|
||||||
DLOG("circular: rotate strategy to "..hrec.nstrategy)
|
|
||||||
if hrec.nstrategy == hrec.final then
|
|
||||||
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ function pos_str(desync, pos)
|
|||||||
return pos.mode..pos_get(desync, pos.mode)
|
return pos.mode..pos_get(desync, pos.mode)
|
||||||
end
|
end
|
||||||
function is_retransmission(desync)
|
function is_retransmission(desync)
|
||||||
return desync.track and desync.track.tcp and 0==bitand(u32add(desync.track.tcp.uppos_orig_prev, -desync.track.tcp.pos_orig), 0x80000000)
|
return desync.track and desync.track.pos.direct.tcp and 0==bitand(u32add(desync.track.pos.direct.tcp.uppos_prev, -desync.track.pos.direct.tcp.pos), 0x80000000)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- prepare standard rawsend options from desync
|
-- prepare standard rawsend options from desync
|
||||||
@@ -1236,12 +1236,16 @@ function genhost(len, template)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- return hostname if present or ip address in text form otherwise
|
-- return ip addr of target host in text form
|
||||||
|
function host_ip(desync)
|
||||||
|
return desync.target.ip and ntop(desync.target.ip) or desync.target.ip6 and ntop(desync.target.ip6)
|
||||||
|
end
|
||||||
|
-- return hostname of target host if present or ip address in text form otherwise
|
||||||
function host_or_ip(desync)
|
function host_or_ip(desync)
|
||||||
if desync.track and desync.track.hostname then
|
if desync.track and desync.track.hostname then
|
||||||
return desync.track.hostname
|
return desync.track.hostname
|
||||||
end
|
end
|
||||||
return desync.target.ip and ntop(desync.target.ip) or desync.target.ip6 and ntop(desync.target.ip6)
|
return host_ip(desync)
|
||||||
end
|
end
|
||||||
|
|
||||||
function is_absolute_path(path)
|
function is_absolute_path(path)
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ typedef struct
|
|||||||
// tcp only state, not used in udp
|
// tcp only state, not used in udp
|
||||||
uint32_t seq0; // starting seq and ack
|
uint32_t seq0; // starting seq and ack
|
||||||
uint16_t winsize; // last seen window size
|
uint16_t winsize; // last seen window size
|
||||||
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
|
|
||||||
uint32_t winsize_calc; // calculated window size
|
|
||||||
uint16_t mss;
|
uint16_t mss;
|
||||||
|
uint32_t winsize_calc; // calculated window size
|
||||||
|
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
|
||||||
} t_ctrack_position;
|
} t_ctrack_position;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
157
nfq2/darkmagic.c
157
nfq2/darkmagic.c
@@ -40,9 +40,6 @@
|
|||||||
#include <linux/genetlink.h>
|
#include <linux/genetlink.h>
|
||||||
#include <libmnl/libmnl.h>
|
#include <libmnl/libmnl.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#define _LINUX_IF_H // prevent conflict between linux/if.h and net/if.h in old gcc 4.x
|
|
||||||
#include <linux/wireless.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
||||||
@@ -1578,9 +1575,9 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
|
|||||||
|
|
||||||
// linux-specific wlan retrieval implementation
|
// linux-specific wlan retrieval implementation
|
||||||
|
|
||||||
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh);
|
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh, void *param);
|
||||||
|
|
||||||
static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, mnl_cb_t cb_data, void *data)
|
static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, void *prepare_data, mnl_cb_t cb_data, void *data)
|
||||||
{
|
{
|
||||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
@@ -1595,7 +1592,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
|
|||||||
genl->cmd = cmd;
|
genl->cmd = cmd;
|
||||||
genl->version = version;
|
genl->version = version;
|
||||||
|
|
||||||
if (cb_prepare_nlh) cb_prepare_nlh(nlh);
|
if (cb_prepare_nlh) cb_prepare_nlh(nlh, prepare_data);
|
||||||
|
|
||||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||||
{
|
{
|
||||||
@@ -1619,7 +1616,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wlan_id_prepare(struct nlmsghdr *nlh)
|
static void wlan_id_prepare(struct nlmsghdr *nlh, void *param)
|
||||||
{
|
{
|
||||||
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, "nl80211");
|
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, "nl80211");
|
||||||
}
|
}
|
||||||
@@ -1651,7 +1648,7 @@ static int wlan_id_cb(const struct nlmsghdr *nlh, void *data)
|
|||||||
static uint16_t wlan_get_family_id(struct mnl_socket* nl)
|
static uint16_t wlan_get_family_id(struct mnl_socket* nl)
|
||||||
{
|
{
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, wlan_id_cb, &id) ? id : 0;
|
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, NULL, wlan_id_cb, &id) ? id : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
|
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
|
||||||
@@ -1686,42 +1683,130 @@ static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
|
|||||||
}
|
}
|
||||||
return MNL_CB_OK;
|
return MNL_CB_OK;
|
||||||
}
|
}
|
||||||
|
struct wlan_info_req
|
||||||
|
{
|
||||||
|
struct wlan_interface_collection *wc;
|
||||||
|
bool bReqSSID;
|
||||||
|
};
|
||||||
static int wlan_info_cb(const struct nlmsghdr *nlh, void *data)
|
static int wlan_info_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct wlan_info_req *wr = (struct wlan_info_req*)data;
|
||||||
|
if (wr->wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
|
||||||
|
memset(wr->wc->wlan + wr->wc->count,0,sizeof(struct wlan_interface));
|
||||||
|
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wr->wc->wlan + wr->wc->count);
|
||||||
|
if (ret>=0 && (!wr->bReqSSID || *wr->wc->wlan[wr->wc->count].ssid) && *wr->wc->wlan[wr->wc->count].ifname && wr->wc->wlan[wr->wc->count].ifindex)
|
||||||
|
wr->wc->count++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w, bool bReqSSID)
|
||||||
|
{
|
||||||
|
struct wlan_info_req req = { .bReqSSID = bReqSSID, .wc = w };
|
||||||
|
return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, NULL, wlan_info_cb, &req);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void scan_prepare(struct nlmsghdr *nlh, void *param)
|
||||||
|
{
|
||||||
|
mnl_attr_put_u32(nlh, NL80211_ATTR_IFINDEX, *(int*)param);
|
||||||
|
}
|
||||||
|
static uint8_t *find_ie(uint8_t *buf, size_t len, uint8_t ie)
|
||||||
|
{
|
||||||
|
while (len>=2)
|
||||||
|
{
|
||||||
|
if (len<(2+buf[1])) break;
|
||||||
|
if (buf[0]==ie) return buf;
|
||||||
|
buf+=buf[1]+2;
|
||||||
|
len-=buf[1]+2;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static int scan_info_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
struct wlan_interface *wlan = (struct wlan_interface *)data;
|
||||||
|
const struct nlattr *nested;
|
||||||
|
uint8_t *payload, *ie;
|
||||||
|
uint16_t payload_len;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
switch(mnl_attr_get_type(attr))
|
||||||
|
{
|
||||||
|
case NL80211_ATTR_IFINDEX:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
|
||||||
|
{
|
||||||
|
DLOG_PERROR("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
wlan->ifindex = mnl_attr_get_u32(attr);
|
||||||
|
if (!if_indextoname(wlan->ifindex, wlan->ifname))
|
||||||
|
DLOG_PERROR("if_indextoname");
|
||||||
|
break;
|
||||||
|
case NL80211_ATTR_BSS:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
|
||||||
|
{
|
||||||
|
DLOG_PERROR("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
ok = false;
|
||||||
|
mnl_attr_for_each_nested(nested, attr)
|
||||||
|
{
|
||||||
|
if (mnl_attr_get_type(nested)==NL80211_BSS_STATUS)
|
||||||
|
{
|
||||||
|
uint32_t status = mnl_attr_get_u32(nested);
|
||||||
|
if (status==NL80211_BSS_STATUS_ASSOCIATED || status==NL80211_BSS_STATUS_AUTHENTICATED || status==NL80211_BSS_STATUS_IBSS_JOINED)
|
||||||
|
{
|
||||||
|
ok=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) break;
|
||||||
|
mnl_attr_for_each_nested(nested, attr)
|
||||||
|
{
|
||||||
|
switch(mnl_attr_get_type(nested))
|
||||||
|
{
|
||||||
|
case NL80211_BSS_INFORMATION_ELEMENTS:
|
||||||
|
payload_len = mnl_attr_get_payload_len(nested);
|
||||||
|
payload = mnl_attr_get_payload(nested);
|
||||||
|
ie = find_ie(payload,payload_len,0);
|
||||||
|
if (ie)
|
||||||
|
{
|
||||||
|
uint8_t l = ie[1];
|
||||||
|
if (l>=(sizeof(wlan->ssid))) l=sizeof(wlan->ssid)-1;
|
||||||
|
memcpy(wlan->ssid,ie+2,l);
|
||||||
|
wlan->ssid[l]=0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
static int scan_info_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct wlan_interface_collection *wc = (struct wlan_interface_collection*)data;
|
struct wlan_interface_collection *wc = (struct wlan_interface_collection*)data;
|
||||||
if (wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
|
if (wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
|
||||||
memset(wc->wlan+wc->count,0,sizeof(wc->wlan[0]));
|
memset(wc->wlan+wc->count,0,sizeof(wc->wlan[0]));
|
||||||
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wc->wlan+wc->count);
|
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), scan_info_attr_cb, wc->wlan+wc->count);
|
||||||
if (ret>=0 && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
|
if (ret>=0 && *wc->wlan[wc->count].ssid && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
|
||||||
{
|
wc->count++;
|
||||||
if (*wc->wlan[wc->count].ssid)
|
|
||||||
wc->count++;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// sometimes nl80211 does not return SSID but wireless ext does
|
|
||||||
int wext_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
||||||
if (wext_fd!=-1)
|
|
||||||
{
|
|
||||||
struct iwreq req;
|
|
||||||
snprintf(req.ifr_ifrn.ifrn_name,sizeof(req.ifr_ifrn.ifrn_name),"%s",wc->wlan[wc->count].ifname);
|
|
||||||
req.u.essid.pointer = wc->wlan[wc->count].ssid;
|
|
||||||
req.u.essid.length = sizeof(wc->wlan[wc->count].ssid);
|
|
||||||
req.u.essid.flags = 0;
|
|
||||||
if (ioctl(wext_fd, SIOCGIWESSID, &req)!=-1)
|
|
||||||
if (*wc->wlan[wc->count].ssid)
|
|
||||||
wc->count++;
|
|
||||||
close(wext_fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
|
static bool scan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
|
||||||
{
|
{
|
||||||
return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, wlan_info_cb, w);
|
struct wlan_interface_collection wc_all = { .count = 0 };
|
||||||
|
// wlan_info does not return ssid since kernel 5.19
|
||||||
|
// it's used to enumerate all wifi interfaces then call scan_info on each
|
||||||
|
if (!wlan_info(nl, wlan_family_id, &wc_all, false)) return false;
|
||||||
|
for(int i=0;i<wc_all.count;i++)
|
||||||
|
if (!netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0, scan_prepare, (void*)&wc_all.wlan[i].ifindex, scan_info_cb, w))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool wlan_init80211(struct mnl_socket** nl)
|
static bool wlan_init80211(struct mnl_socket** nl)
|
||||||
{
|
{
|
||||||
if (!(*nl = mnl_socket_open(NETLINK_GENERIC)))
|
if (!(*nl = mnl_socket_open(NETLINK_GENERIC)))
|
||||||
@@ -1755,7 +1840,7 @@ static bool wlan_info_rate_limited(struct mnl_socket* nl, uint16_t wlan_family_i
|
|||||||
// do not purge too often to save resources
|
// do not purge too often to save resources
|
||||||
if (wlan_info_last != now)
|
if (wlan_info_last != now)
|
||||||
{
|
{
|
||||||
bres = wlan_info(nl,wlan_family_id,w);
|
bres = scan_info(nl,wlan_family_id,w);
|
||||||
wlan_info_last = now;
|
wlan_info_last = now;
|
||||||
}
|
}
|
||||||
return bres;
|
return bres;
|
||||||
@@ -1781,10 +1866,6 @@ bool wlan_info_init(void)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool wlan_info_get(void)
|
|
||||||
{
|
|
||||||
return wlan_info(nl_wifi, id_nl80211, &wlans);
|
|
||||||
}
|
|
||||||
bool wlan_info_get_rate_limited(void)
|
bool wlan_info_get_rate_limited(void)
|
||||||
{
|
{
|
||||||
return wlan_info_rate_limited(nl_wifi, id_nl80211, &wlans);
|
return wlan_info_rate_limited(nl_wifi, id_nl80211, &wlans);
|
||||||
|
|||||||
@@ -190,7 +190,6 @@ extern struct wlan_interface_collection wlans;
|
|||||||
|
|
||||||
void wlan_info_deinit(void);
|
void wlan_info_deinit(void);
|
||||||
bool wlan_info_init(void);
|
bool wlan_info_init(void);
|
||||||
bool wlan_info_get(void);
|
|
||||||
bool wlan_info_get_rate_limited(void);
|
bool wlan_info_get_rate_limited(void);
|
||||||
const char *wlan_ssid_search_ifname(const char *ifname);
|
const char *wlan_ssid_search_ifname(const char *ifname);
|
||||||
const char *wlan_ssid_search_ifidx(int ifidx);
|
const char *wlan_ssid_search_ifidx(int ifidx);
|
||||||
|
|||||||
@@ -348,15 +348,20 @@ static void process_udp_fail(t_ctrack *ctrack, const t_ctrack_positions *tpos, c
|
|||||||
if (!params.server && ctrack && ctrack->dp && ctrack->hostname && ctrack->hostname_ah_check &&
|
if (!params.server && ctrack && ctrack->dp && ctrack->hostname && ctrack->hostname_ah_check &&
|
||||||
!ctrack->failure_detect_finalized && ctrack->dp->hostlist_auto_udp_out)
|
!ctrack->failure_detect_finalized && ctrack->dp->hostlist_auto_udp_out)
|
||||||
{
|
{
|
||||||
|
char client_ip_port[48];
|
||||||
|
|
||||||
if (!tpos) tpos = &ctrack->pos;
|
if (!tpos) tpos = &ctrack->pos;
|
||||||
//printf("UDP_POS %u %u\n",tpos->client.pcounter, tpos->server.pcounter);
|
//printf("UDP_POS %u %u\n",tpos->client.pcounter, tpos->server.pcounter);
|
||||||
if (tpos->server.pcounter > ctrack->dp->hostlist_auto_udp_in)
|
if (tpos->server.pcounter > ctrack->dp->hostlist_auto_udp_in)
|
||||||
|
{
|
||||||
// success
|
// success
|
||||||
ctrack->failure_detect_finalized = true;
|
ctrack->failure_detect_finalized = true;
|
||||||
|
fill_client_ip_port(client, client_ip_port, sizeof(client_ip_port));
|
||||||
|
auto_hostlist_reset_fail_counter(ctrack->dp, ctrack->hostname, client_ip_port, ctrack->l7proto);
|
||||||
|
}
|
||||||
else if (tpos->client.pcounter >= ctrack->dp->hostlist_auto_udp_out)
|
else if (tpos->client.pcounter >= ctrack->dp->hostlist_auto_udp_out)
|
||||||
{
|
{
|
||||||
// failure
|
// failure
|
||||||
char client_ip_port[48];
|
|
||||||
ctrack->failure_detect_finalized = true;
|
ctrack->failure_detect_finalized = true;
|
||||||
fill_client_ip_port(client, client_ip_port, sizeof(client_ip_port));
|
fill_client_ip_port(client, client_ip_port, sizeof(client_ip_port));
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : udp_in %u<=%u udp_out %u>=%u",
|
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : udp_in %u<=%u udp_out %u>=%u",
|
||||||
@@ -410,6 +415,15 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, ui
|
|||||||
static bool reasm_client_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
static bool reasm_client_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
||||||
{
|
{
|
||||||
if (!ctrack) return false;
|
if (!ctrack) return false;
|
||||||
|
if (proto==IPPROTO_TCP && ctrack->pos.server.winsize_calc < sz)
|
||||||
|
{
|
||||||
|
// this is rare but possible situation
|
||||||
|
// server gave us too small tcp window
|
||||||
|
// client will not send all pieces of reasm
|
||||||
|
// if we drop packets and wait for next pieces we will see nothing but retransmissions
|
||||||
|
DLOG("reasm cancelled because server window size %u is smaller than expected reasm size %u\n", ctrack->pos.server.winsize_calc, sz);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return reasm_start(ctrack, &ctrack->reasm_client, proto, (proto == IPPROTO_TCP) ? ctrack->pos.client.seq_last : 0, sz, szMax, data_payload, len_payload);
|
return reasm_start(ctrack, &ctrack->reasm_client, proto, (proto == IPPROTO_TCP) ? ctrack->pos.client.seq_last : 0, sz, szMax, data_payload, len_payload);
|
||||||
}
|
}
|
||||||
static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, uint32_t seq, const uint8_t *data_payload, size_t len_payload)
|
static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, uint32_t seq, const uint8_t *data_payload, size_t len_payload)
|
||||||
@@ -961,6 +975,23 @@ static void setup_direction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dp_changed(t_ctrack *ctrack)
|
||||||
|
{
|
||||||
|
if (ctrack)
|
||||||
|
{
|
||||||
|
if (ctrack->b_lua_in_cutoff)
|
||||||
|
{
|
||||||
|
DLOG("clearing lua in cutoff because of profile change\n");
|
||||||
|
ctrack->b_lua_in_cutoff = false;
|
||||||
|
}
|
||||||
|
if (ctrack->b_lua_out_cutoff)
|
||||||
|
{
|
||||||
|
DLOG("clearing lua out cutoff because of profile change\n");
|
||||||
|
ctrack->b_lua_out_cutoff = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t dpi_desync_tcp_packet_play(
|
static uint8_t dpi_desync_tcp_packet_play(
|
||||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||||
uint32_t fwmark,
|
uint32_t fwmark,
|
||||||
@@ -1328,6 +1359,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
|||||||
if (!dp) goto pass_reasm_cancel;
|
if (!dp) goto pass_reasm_cancel;
|
||||||
if (dp != dp_prev)
|
if (dp != dp_prev)
|
||||||
{
|
{
|
||||||
|
dp_changed(ctrack_replay);
|
||||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1772,6 +1804,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
|||||||
goto pass_reasm_cancel;
|
goto pass_reasm_cancel;
|
||||||
if (dp != dp_prev)
|
if (dp != dp_prev)
|
||||||
{
|
{
|
||||||
|
dp_changed(ctrack_replay);
|
||||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#define DPI_DESYNC_FWMARK_DEFAULT 0x40000000
|
#define DPI_DESYNC_FWMARK_DEFAULT 0x40000000
|
||||||
#else
|
#elif defined(SO_USER_COOKIE)
|
||||||
#define DPI_DESYNC_FWMARK_DEFAULT 512
|
#define DPI_DESYNC_FWMARK_DEFAULT 512
|
||||||
|
#else
|
||||||
|
#define DPI_DESYNC_FWMARK_DEFAULT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt);
|
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt);
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ int DLOG_FILENAME_VA(const char *filename, const char *format, va_list args)
|
|||||||
|
|
||||||
typedef void (*f_log_function)(int priority, const char *line);
|
typedef void (*f_log_function)(int priority, const char *line);
|
||||||
|
|
||||||
static char log_buf[1024];
|
static char log_buf[4096];
|
||||||
static size_t log_buf_sz=0;
|
static size_t log_buf_sz=0;
|
||||||
static void syslog_log_function(int priority, const char *line)
|
static void syslog_log_function(int priority, const char *line)
|
||||||
{
|
{
|
||||||
@@ -158,11 +158,18 @@ static void android_log_function(int priority, const char *line)
|
|||||||
#endif
|
#endif
|
||||||
static void log_buffered(f_log_function log_function, int syslog_priority, const char *format, va_list args)
|
static void log_buffered(f_log_function log_function, int syslog_priority, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
if (vsnprintf(log_buf+log_buf_sz,sizeof(log_buf)-log_buf_sz,format,args)>0)
|
if (vsnprintf(log_buf+log_buf_sz,sizeof(log_buf)-log_buf_sz-1,format,args)>0)
|
||||||
{
|
{
|
||||||
log_buf_sz=strlen(log_buf);
|
log_buf_sz=strlen(log_buf);
|
||||||
// log when buffer is full or buffer ends with \n
|
// log when buffer is full or buffer ends with \n
|
||||||
if (log_buf_sz>=(sizeof(log_buf)-1) || (log_buf_sz && log_buf[log_buf_sz-1]=='\n'))
|
if (log_buf_sz==(sizeof(log_buf)-2))
|
||||||
|
{
|
||||||
|
log_buf[log_buf_sz++] = '\n';
|
||||||
|
log_buf[log_buf_sz] = 0;
|
||||||
|
log_function(syslog_priority,log_buf);
|
||||||
|
log_buf_sz = 0;
|
||||||
|
}
|
||||||
|
else if (log_buf_sz && log_buf[log_buf_sz-1]=='\n')
|
||||||
{
|
{
|
||||||
log_function(syslog_priority,log_buf);
|
log_function(syslog_priority,log_buf);
|
||||||
log_buf_sz = 0;
|
log_buf_sz = 0;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
||||||
#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 HOSTLIST_AUTO_RETRANS_MAXSEQ 65536
|
#define HOSTLIST_AUTO_RETRANS_MAXSEQ 32768
|
||||||
#define HOSTLIST_AUTO_INCOMING_MAXSEQ 4096
|
#define HOSTLIST_AUTO_INCOMING_MAXSEQ 4096
|
||||||
#define HOSTLIST_AUTO_UDP_OUT 4
|
#define HOSTLIST_AUTO_UDP_OUT 4
|
||||||
#define HOSTLIST_AUTO_UDP_IN 1
|
#define HOSTLIST_AUTO_UDP_IN 1
|
||||||
|
|||||||
Reference in New Issue
Block a user