mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-16 14:58:17 +00:00
Compare commits
180 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ecd34cbca | ||
|
|
b5b1f71fcc | ||
|
|
f5f7de4086 | ||
|
|
a331d59d33 | ||
|
|
0a6d066e92 | ||
|
|
1216ef0364 | ||
|
|
52e38ee687 | ||
|
|
fd53a54cf3 | ||
|
|
c6b7e1fc43 | ||
|
|
a7a1520b40 | ||
|
|
04881b10b1 | ||
|
|
561e5e2718 | ||
|
|
e83e127c15 | ||
|
|
3590861ffe | ||
|
|
a12307d7f9 | ||
|
|
25a9f9e426 | ||
|
|
f4644e2a47 | ||
|
|
b9a0d42815 | ||
|
|
f76beba434 | ||
|
|
60b6ec2f49 | ||
|
|
ce95210d1c | ||
|
|
953d92b177 | ||
|
|
4d9b4c9ad8 | ||
|
|
ee7b72dc66 | ||
|
|
8eb588d6a4 | ||
|
|
08e1f8fba1 | ||
|
|
454eedeb36 | ||
|
|
7e761b3f03 | ||
|
|
3dd51ee3b1 | ||
|
|
07b1356c6c | ||
|
|
23445785c9 | ||
|
|
f4a7fe3aaf | ||
|
|
6d31036ca1 | ||
|
|
5ceb3aa301 | ||
|
|
7fd602885f | ||
|
|
af75c3d63d | ||
|
|
cb9789668f | ||
|
|
c16508e2e4 | ||
|
|
912eb1217a | ||
|
|
3a328089a3 | ||
|
|
4c76444b2d | ||
|
|
403413bb26 | ||
|
|
8ea6a17942 | ||
|
|
15731d6135 | ||
|
|
8255481787 | ||
|
|
d2a919f71d | ||
|
|
915130aed9 | ||
|
|
901ffdfe5a | ||
|
|
8caaf85b36 | ||
|
|
1dc5e23a41 | ||
|
|
ee859db268 | ||
|
|
37f7fbbdec | ||
|
|
81f6937187 | ||
|
|
cbf5be50d1 | ||
|
|
1966ea2298 | ||
|
|
d96350d2c7 | ||
|
|
5cb96559d0 | ||
|
|
dffba7cd13 | ||
|
|
5ad122da40 | ||
|
|
54871f4ef8 | ||
|
|
d06e4f4c82 | ||
|
|
322b050e45 | ||
|
|
5cb9cfc820 | ||
|
|
ede260d4fa | ||
|
|
9a7de03830 | ||
|
|
b9b14f254a | ||
|
|
653ed92cf8 | ||
|
|
0d99c68b1b | ||
|
|
6c75dcc002 | ||
|
|
b76e1f65a3 | ||
|
|
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 | ||
|
|
7708021587 | ||
|
|
912aadf6ca | ||
|
|
420cc0c3ef | ||
|
|
6ce5829d06 | ||
|
|
a6d43af931 | ||
|
|
ca9898959e | ||
|
|
8cd2904614 | ||
|
|
0de1ab1b1b | ||
|
|
d1690aadcf | ||
|
|
2dd8533fb5 | ||
|
|
33ac18ea6b | ||
|
|
5c05c10f83 | ||
|
|
7de0995d4a | ||
|
|
a1c64e4dea | ||
|
|
92b66b1535 | ||
|
|
9bf4fb11e7 | ||
|
|
7deeb04207 |
@@ -25,7 +25,7 @@ filter_apply_hostlist_target()
|
||||
{
|
||||
# $1 - var name of nfqws params
|
||||
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parmNA
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 parmNA
|
||||
eval v="\$$1"
|
||||
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
|
||||
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
|
||||
@@ -41,10 +41,13 @@ filter_apply_hostlist_target()
|
||||
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
|
||||
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
|
||||
parm8="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
|
||||
parm9="--hostlist=$HOSTLIST_AUTO"
|
||||
parm9="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
|
||||
parm10="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
|
||||
parm11="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
|
||||
parm12="--hostlist=$HOSTLIST_AUTO"
|
||||
}
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm9:+ $parm9}"
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm10:+ $parm12}"
|
||||
}
|
||||
v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")"
|
||||
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"
|
||||
|
||||
@@ -97,17 +97,19 @@ nft_activate_chain4()
|
||||
{
|
||||
# $1 - chain name
|
||||
# $2 - saddr/daddr
|
||||
local b rule markf= act
|
||||
local b rule markf= act flt_ifname
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
eval act="\$${1}_act4"
|
||||
[ -n "$act" ] && return
|
||||
|
||||
b=0
|
||||
nft_wanif_filter_present && b=1
|
||||
flt_ifname="oifname"
|
||||
starts_with "$1" pre && flt_ifname="iifname"
|
||||
|
||||
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
||||
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"
|
||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||
|
||||
@@ -118,17 +120,19 @@ nft_activate_chain6()
|
||||
{
|
||||
# $1 - chain name
|
||||
# $2 - saddr/daddr
|
||||
local b rule markf=
|
||||
local b rule markf= act flt_ifname
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
eval act="\$${1}_act6"
|
||||
[ -n "$act" ] && return
|
||||
|
||||
b=0
|
||||
nft_wanif6_filter_present && b=1
|
||||
flt_ifname="oifname"
|
||||
starts_with "$1" pre && flt_ifname="iifname"
|
||||
|
||||
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
||||
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"
|
||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||
|
||||
|
||||
@@ -26,10 +26,15 @@ IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
||||
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
|
||||
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
|
||||
# options for auto hostlist
|
||||
AUTOHOSTLIST_RETRANS_MAXSEQ=65536
|
||||
# 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_RETRANS_MAXSEQ=32768
|
||||
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_TIME=60
|
||||
AUTOHOSTLIST_UDP_IN=1
|
||||
AUTOHOSTLIST_UDP_OUT=4
|
||||
# 1 = debug autohostlist positives to ipset/zapret-hosts-auto-debug.log
|
||||
AUTOHOSTLIST_DEBUGLOG=0
|
||||
|
||||
@@ -61,11 +66,10 @@ NFQWS2_PORTS_TCP=80,443
|
||||
NFQWS2_PORTS_UDP=443
|
||||
# PKT_OUT means connbytes dir original
|
||||
# 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=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||||
NFQWS2_TCP_PKT_IN=3
|
||||
NFQWS2_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||||
NFQWS2_UDP_PKT_IN=0
|
||||
NFQWS2_TCP_PKT_OUT=20
|
||||
NFQWS2_TCP_PKT_IN=10
|
||||
NFQWS2_UDP_PKT_OUT=5
|
||||
NFQWS2_UDP_PKT_IN=3
|
||||
# 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
|
||||
# typical example are plain HTTP keep alives
|
||||
|
||||
@@ -80,3 +80,37 @@ v0.6.1
|
||||
* zapret-lib, zapret-auto: condition and stopif orchestrators
|
||||
* zapret-lib: detect_payload_str - sample lua payload detector
|
||||
* blockcheck2: unterminated string fix
|
||||
|
||||
v0.7
|
||||
|
||||
* nfqws2, zapret-lib : fix non-working % and # arg substitution under orchestrator
|
||||
* nfqws2, zapret-lib : structure conntrack in/out positions. pass in desync.track.pos.{client,server,direct,reverse} position tables
|
||||
* nfqws2: autohostlist: trigger RST and http redirect failures only within specified relative sequence
|
||||
* nfqws2: autohostlist: trigger http redirect failure if payload is http_req without connection proto check
|
||||
* nfqws2: push desync.track.pos.dt as float with nsec accuracy
|
||||
* zapret-auto: override host autostate key in automate_host_record
|
||||
* 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
|
||||
* zapret-auto: separate hostkey function
|
||||
|
||||
v0.7.4
|
||||
|
||||
* nfqws2, zapret-lib : check tcp sequence range overflow
|
||||
* zapret-lib : seq compare functions
|
||||
* nfqws2: add l3_len, l4_len to dissect
|
||||
* nfqws2: fix broken l7proto profile rediscovery
|
||||
* winws2: harden sandbox. disable child process execution , some UI interaction and desktop settings change
|
||||
|
||||
@@ -5,3 +5,7 @@ v2
|
||||
* removed "stun_binding_req" specialized payload. replaced with common "stun" - any stun packets, not only binding request.
|
||||
every LUA relying on desync.l7payload should be revised.
|
||||
nfqws2 --payload option and init.d custom scripts must be updated.
|
||||
|
||||
v3
|
||||
* restructured desync.track. pass positions in desync.track.pos.{client,server,direct,reverse}
|
||||
code relying on conntrack counters and sequence numbers must be rewritten
|
||||
|
||||
2324
docs/manual.md
Normal file
2324
docs/manual.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,3 @@
|
||||
# zapret2 v0.2
|
||||
|
||||
## Зачем это нужно
|
||||
|
||||
Автономное средство противодействия DPI, которое не требует подключения каких-либо сторонних серверов. Может помочь
|
||||
|
||||
@@ -1,29 +1,62 @@
|
||||
-- standard automation/orchestration 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
|
||||
-- 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
|
||||
function automate_host_record(desync)
|
||||
local key
|
||||
if desync.arg.reqhost then
|
||||
key = desync.track and desync.track.hostname
|
||||
else
|
||||
key = host_or_ip(desync)
|
||||
-- arg: nld=N - cut hostname to N level domain. NLD=2 static.intranet.microsoft.com => microsoft.com
|
||||
function standard_hostkey(desync)
|
||||
local hostkey = desync.track and desync.track.hostname
|
||||
if hostkey then
|
||||
if desync.arg.nld and tonumber(desync.arg.nld)>0 and not (desync.track and desync.track.hostname_is_ip) then
|
||||
-- dissect_nld returns nil if domain is invalid or does not have this NLD
|
||||
-- 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
|
||||
if not key then
|
||||
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
|
||||
DLOG("automate: host record key unavailable")
|
||||
return nil
|
||||
end
|
||||
DLOG("automate: host record key '"..key.."'")
|
||||
|
||||
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.."'")
|
||||
if not autostate then
|
||||
autostate = {}
|
||||
end
|
||||
if not autostate[key] then
|
||||
autostate[key] = {}
|
||||
if not autostate[askey] then
|
||||
autostate[askey] = {}
|
||||
end
|
||||
return autostate[key]
|
||||
if not autostate[askey][hostkey] then
|
||||
autostate[askey][hostkey] = {}
|
||||
end
|
||||
return autostate[askey][hostkey]
|
||||
end
|
||||
-- per-connection storage
|
||||
function automate_conn_record(desync)
|
||||
if not desync.track.lua_state.automate then
|
||||
desync.track.lua_state.automate = {}
|
||||
@@ -61,6 +94,13 @@ function automate_failure_counter(hrec, crec, fails, maxtime)
|
||||
end
|
||||
return false
|
||||
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
|
||||
-- hostname is original hostname
|
||||
@@ -74,6 +114,18 @@ function is_dpi_redirect(hostname, location)
|
||||
return false
|
||||
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
|
||||
-- works with tcp and udp
|
||||
-- detected failures:
|
||||
@@ -81,46 +133,34 @@ end
|
||||
-- incoming http redirection
|
||||
-- outgoing retransmissions
|
||||
-- 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: 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: udp_out - udp: >= outgoing udp packets. default is 3
|
||||
-- arg: no_rst - tcp: disable incoming RST trigger
|
||||
-- arg: udp_out - udp: >= outgoing udp packets. default is 4
|
||||
-- arg: udp_in - udp: with <= incoming udp packets. default is 1
|
||||
function standard_failure_detector(desync, crec, arg)
|
||||
if crec.nocheck then return false end
|
||||
|
||||
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 3
|
||||
|
||||
function standard_failure_detector(desync, crec)
|
||||
local arg = standard_detector_defaults(desync.arg)
|
||||
local trigger = false
|
||||
if desync.dis.tcp then
|
||||
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.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
|
||||
crec.retrans = crec.retrans and (crec.retrans+1) or 1
|
||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..retrans)
|
||||
trigger = crec.retrans>=retrans
|
||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..arg.retrans)
|
||||
trigger = crec.retrans>=arg.retrans
|
||||
end
|
||||
end
|
||||
else
|
||||
if seq_rst and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 then
|
||||
trigger = seq<=seq_rst
|
||||
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<=arg.inseq
|
||||
if b_debug 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
|
||||
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
|
||||
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
|
||||
@@ -139,13 +179,13 @@ function standard_failure_detector(desync, crec, arg)
|
||||
end
|
||||
elseif desync.dis.udp then
|
||||
if desync.outgoing then
|
||||
if udp_out then
|
||||
local udp_in = udp_in or 0
|
||||
trigger = desync.track.pcounter_orig>=udp_out and desync.track.pcounter_reply<=udp_in
|
||||
if arg.udp_out>0 then
|
||||
local pos_out = pos_get(desync,'n',false)
|
||||
local pos_in = pos_get(desync,'n',true)
|
||||
trigger = pos_out>=arg.udp_out and pos_in<=arg.udp_in
|
||||
if trigger then
|
||||
crec.nocheck = true
|
||||
if b_debug then
|
||||
DLOG("standard_failure_detector: udp_out "..desync.track.pcounter_orig..">="..udp_out.." udp_in "..desync.track.pcounter_reply.."<="..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
|
||||
@@ -154,17 +194,102 @@ function standard_failure_detector(desync, crec, arg)
|
||||
return trigger
|
||||
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')
|
||||
-- works with tcp only
|
||||
-- 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
|
||||
-- if 'final' arg is present in an orchestrated instance it stops rotation
|
||||
-- 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: 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
|
||||
-- arg: hostkey - hostkey generator function name
|
||||
-- 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
|
||||
-- args for hostkey generator - see standard_hostkey or your own generator
|
||||
-- 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)
|
||||
local function count_strategies(hrec)
|
||||
if not hrec.ctstrategy then
|
||||
@@ -219,37 +344,21 @@ function circular(ctx, desync)
|
||||
local verdict = VERDICT_PASS
|
||||
if hrec.final~=hrec.nstrategy then
|
||||
local crec = automate_conn_record(desync)
|
||||
local fails = tonumber(desync.arg.fails) or 3
|
||||
local maxtime = tonumber(desync.arg.time) or 60
|
||||
local failure_detector
|
||||
if desync.arg.detector then
|
||||
if type(_G[desync.arg.detector])~="function" then
|
||||
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
|
||||
if automate_failure_check(desync, hrec, crec) then
|
||||
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
|
||||
|
||||
DLOG("circular: current strategy "..hrec.nstrategy)
|
||||
local dcopy = desync_copy(desync)
|
||||
while true do
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
if instance.arg.strategy and tonumber(instance.arg.strategy)==hrec.nstrategy then
|
||||
verdict = plan_instance_execute(dcopy, verdict, instance)
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -37,16 +37,24 @@ function pktdebug(ctx, desync)
|
||||
end
|
||||
-- basic desync function
|
||||
-- prints function args
|
||||
function argdebug(ctx,desync)
|
||||
function argdebug(ctx, desync)
|
||||
var_debug(desync.arg)
|
||||
end
|
||||
|
||||
-- basic desync function
|
||||
-- prints conntrack positions to DLOG
|
||||
function posdebug(ctx,desync)
|
||||
local s="posdebug:"
|
||||
for i,pos in pairs({'n','d','b','s'}) do
|
||||
s=s.." "..pos..pos_get(desync,pos)
|
||||
function posdebug(ctx, desync)
|
||||
if not desync.track then
|
||||
DLOG("posdebug: no track")
|
||||
return
|
||||
end
|
||||
local s="posdebug: "..(desync.outgoing and "out" or "in").." time +"..desync.track.pos.dt.."s direct"
|
||||
for i,pos in pairs({'n','d','b','s','p'}) do
|
||||
s=s.." "..pos..pos_get(desync, pos, false)
|
||||
end
|
||||
s=s.." reverse"
|
||||
for i,pos in pairs({'n','d','b','s','p'}) do
|
||||
s=s.." "..pos..pos_get(desync, pos, true)
|
||||
end
|
||||
s=s.." payload "..#desync.dis.payload
|
||||
if desync.reasm_data then
|
||||
@@ -126,28 +134,32 @@ end
|
||||
|
||||
|
||||
-- applies # and $ prefixes. #var means var length, %var means var value
|
||||
function apply_arg_prefix(arg)
|
||||
for a,v in pairs(arg) do
|
||||
function apply_arg_prefix(desync)
|
||||
for a,v in pairs(desync.arg) do
|
||||
local c = string.sub(v,1,1)
|
||||
if v=='#' then
|
||||
arg[a] = #_G[string.sub(v,2)]
|
||||
elseif v=='%' then
|
||||
arg[a] = _G[string.sub(v,2)]
|
||||
elseif v=='\\' then
|
||||
if c=='#' then
|
||||
local blb = blob(desync,string.sub(v,2))
|
||||
desync.arg[a] = (type(blb)=='string' or type(blb)=='table') and #blb or 0
|
||||
elseif c=='%' then
|
||||
desync.arg[a] = blob(desync,string.sub(v,2))
|
||||
elseif c=='\\' then
|
||||
c = string.sub(v,2,2);
|
||||
if c=='#' or c=='%' then
|
||||
arg[a] = string.sub(v,2)
|
||||
desync.arg[a] = string.sub(v,2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- copy instance identification and args from execution plan to desync table
|
||||
-- NOTE : to not lose VERDICT_MODIFY dissect changes pass original desync table
|
||||
-- NOTE : if a copy was passed and VERDICT_MODIFY returned you must copy modified dissect back to desync table or resend it and return VERDICT_DROP
|
||||
-- NOTE : args and some fields are substituted. if you need them - make a copy before calling this.
|
||||
function apply_execution_plan(desync, instance)
|
||||
desync.func = instance.func
|
||||
desync.func_n = instance.func_n
|
||||
desync.func_instance = instance.func_instance
|
||||
desync.arg = deepcopy(instance.arg)
|
||||
apply_arg_prefix(desync.arg)
|
||||
apply_arg_prefix(desync)
|
||||
end
|
||||
-- produce resulting verdict from 2 verdicts
|
||||
function verdict_aggregate(v1, v2)
|
||||
@@ -205,12 +217,11 @@ function desync_copy(desync)
|
||||
end
|
||||
-- redo what whould be done without orchestration
|
||||
function replay_execution_plan(desync)
|
||||
local dcopy = desync_copy(desync)
|
||||
local verdict = VERDICT_PASS
|
||||
while true do
|
||||
local instance = plan_instance_pop(dcopy)
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
verdict = plan_instance_execute(dcopy, verdict, instance)
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
end
|
||||
return verdict
|
||||
end
|
||||
@@ -223,27 +234,44 @@ function desync_orchestrator_example(ctx, desync)
|
||||
return replay_execution_plan(desync)
|
||||
end
|
||||
|
||||
-- if seq is over 2G s and p position comparision can be wrong
|
||||
function pos_counter_overflow(desync, mode, reverse)
|
||||
if not desync.track or not desync.track.tcp or (mode~='s' and mode~='p') then return false end
|
||||
local track_pos = reverse and desync.track.pos.reverse or desync.track.pos.direct
|
||||
return track_pos.tcp.rseq_over_2G
|
||||
end
|
||||
-- these functions duplicate range check logic from C code
|
||||
-- mode must be n,d,b,s,x,a
|
||||
-- pos is {mode,pos}
|
||||
-- range is {from={mode,pos}, to={mode,pos}, upper_cutoff}
|
||||
-- upper_cutoff = true means non-inclusive upper boundary
|
||||
function pos_get(desync, mode)
|
||||
if desync.track then
|
||||
function pos_get_pos(track_pos, mode)
|
||||
if track_pos then
|
||||
if mode=='n' then
|
||||
return desync.outgoing and desync.track.pcounter_orig or desync.track.pcounter_reply
|
||||
return track_pos.pcounter
|
||||
elseif mode=='d' then
|
||||
return desync.outgoing and desync.track.pdcounter_orig or desync.track.pdcounter_reply
|
||||
return track_pos.pdcounter
|
||||
elseif mode=='b' then
|
||||
return desync.outgoing and desync.track.pbcounter_orig or desync.track.pbcounter_reply
|
||||
elseif mode=='s' and desync.track.tcp then
|
||||
return desync.outgoing and u32add(desync.track.tcp.seq, -desync.track.tcp.seq0) or u32add(desync.track.tcp.ack, -desync.track.tcp.ack0)
|
||||
return track_pos.pbcounter
|
||||
elseif track_pos.tcp then
|
||||
if mode=='s' then
|
||||
return track_pos.tcp.rseq
|
||||
elseif mode=='p' then
|
||||
return track_pos.tcp.pos
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
function pos_get(desync, mode, reverse)
|
||||
if desync.track then
|
||||
local track_pos = reverse and desync.track.pos.reverse or desync.track.pos.direct
|
||||
return pos_get_pos(track_pos,mode)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
function pos_check_from(desync, range)
|
||||
if range.from.mode == 'x' then return false end
|
||||
if range.from.mode == 'x' or pos_counter_overflow(desync, range.from.mode) then return false end
|
||||
if range.from.mode ~= 'a' then
|
||||
if desync.track then
|
||||
return pos_get(desync, range.from.mode) >= range.from.pos
|
||||
@@ -255,7 +283,7 @@ function pos_check_from(desync, range)
|
||||
end
|
||||
function pos_check_to(desync, range)
|
||||
local ps
|
||||
if range.to.mode == 'x' then return false end
|
||||
if range.to.mode == 'x' or pos_counter_overflow(desync, range.to.mode) then return false end
|
||||
if range.to.mode ~= 'a' then
|
||||
if desync.track then
|
||||
ps = pos_get(desync, range.to.mode)
|
||||
@@ -275,8 +303,31 @@ end
|
||||
function pos_str(desync, pos)
|
||||
return pos.mode..pos_get(desync, pos.mode)
|
||||
end
|
||||
|
||||
-- sequence comparision functions. they work only within 2G interval
|
||||
-- seq1>=seq2
|
||||
function seq_ge(seq1, seq2)
|
||||
return 0==bitand(u32add(seq1, -seq2), 0x80000000)
|
||||
end
|
||||
-- seq1>seq2
|
||||
function seq_gt(seq1, seq2)
|
||||
return seq1~=seq2 and seq_ge(seq1, seq2)
|
||||
end
|
||||
-- seq1<seq2
|
||||
function seq_lt(seq1, seq2)
|
||||
return 0~=bitand(u32add(seq1, -seq2), 0x80000000)
|
||||
end
|
||||
-- seq1<=seq2
|
||||
function seq_le(seq1, seq2)
|
||||
return seq1==seq2 or 0~=bitand(u32add(seq1, -seq2), 0x80000000)
|
||||
end
|
||||
-- seq_low<=seq<=seq_hi
|
||||
function seq_within(seq, seq_low, seq_hi)
|
||||
return seq_ge(seq, seq_low) and seq_le(seq, seq_hi)
|
||||
end
|
||||
|
||||
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 seq_ge(desync.track.pos.direct.tcp.uppos_prev, desync.track.pos.direct.tcp.pos)
|
||||
end
|
||||
|
||||
-- prepare standard rawsend options from desync
|
||||
@@ -779,6 +830,7 @@ end
|
||||
-- ip6_hopbyhop[=hex] - add hopbyhop ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_hopbyhop2[=hex] - add second hopbyhop ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_destopt[=hex] - add destopt ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_destopt2[=hex] - add second destopt ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_routing[=hex] - add routing ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_ah[=hex] - add authentication ipv6 header with optional data. data size must be 6+N*4. 0000 + 4 random bytes by default.
|
||||
|
||||
@@ -1214,12 +1266,16 @@ function genhost(len, template)
|
||||
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)
|
||||
if desync.track and desync.track.hostname then
|
||||
return desync.track.hostname
|
||||
end
|
||||
return desync.target.ip and ntop(desync.target.ip) or desync.target.ip6 and ntop(desync.target.ip6)
|
||||
return host_ip(desync)
|
||||
end
|
||||
|
||||
function is_absolute_path(path)
|
||||
|
||||
161
nfq2/conntrack.c
161
nfq2/conntrack.c
@@ -37,7 +37,7 @@ void ConntrackClearHostname(t_ctrack *track)
|
||||
static void ConntrackClearTrack(t_ctrack *track)
|
||||
{
|
||||
ConntrackClearHostname(track);
|
||||
ReasmClear(&track->reasm_orig);
|
||||
ReasmClear(&track->reasm_client);
|
||||
rawpacket_queue_destroy(&track->delayed);
|
||||
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_state);
|
||||
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_instance_cutoff);
|
||||
@@ -102,8 +102,7 @@ static void ConntrackInitTrack(t_ctrack *t)
|
||||
{
|
||||
memset(t, 0, sizeof(*t));
|
||||
t->l7proto = L7_UNKNOWN;
|
||||
t->pos.scale_orig = t->pos.scale_reply = SCALE_NONE;
|
||||
time(&t->pos.t_start);
|
||||
t->pos.client.scale = t->pos.server.scale = SCALE_NONE;
|
||||
rawpacket_queue_init(&t->delayed);
|
||||
lua_newtable(params.L);
|
||||
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
||||
@@ -128,6 +127,41 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
||||
return ctnew;
|
||||
}
|
||||
|
||||
static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bReverse, uint32_t len_payload)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
t_ctrack_position *direct, *reverse;
|
||||
|
||||
direct = bReverse ? &t->pos.server : &t->pos.client;
|
||||
reverse = bReverse ? &t->pos.client : &t->pos.server;
|
||||
|
||||
scale = tcp_find_scale_factor(tcp);
|
||||
mss = ntohs(tcp_find_mss(tcp));
|
||||
|
||||
direct->seq_last = ntohl(tcp->th_seq);
|
||||
direct->pos = direct->seq_last + len_payload;
|
||||
reverse->pos = reverse->seq_last = ntohl(tcp->th_ack);
|
||||
if (t->pos.state == SYN)
|
||||
direct->uppos_prev = direct->uppos = direct->pos;
|
||||
else if (len_payload)
|
||||
{
|
||||
direct->uppos_prev = direct->uppos;
|
||||
if (!((direct->pos - direct->uppos) & 0x80000000))
|
||||
direct->uppos = direct->pos;
|
||||
}
|
||||
direct->winsize = ntohs(tcp->th_win);
|
||||
direct->winsize_calc = direct->winsize;
|
||||
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
|
||||
if (mss && !direct->mss) direct->mss = mss;
|
||||
if (scale != SCALE_NONE) direct->scale = scale;
|
||||
|
||||
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
|
||||
direct->rseq_over_2G = true;
|
||||
if (!reverse->rseq_over_2G && ((reverse->seq_last - reverse->seq0) & 0x80000000))
|
||||
reverse->rseq_over_2G = true;
|
||||
}
|
||||
|
||||
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
|
||||
{
|
||||
@@ -136,16 +170,16 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.pcounter_reply++;
|
||||
t->pos.pdcounter_reply += !!len_payload;
|
||||
t->pos.pbcounter_reply += len_payload;
|
||||
t->pos.server.pcounter++;
|
||||
t->pos.server.pdcounter += !!len_payload;
|
||||
t->pos.server.pbcounter += len_payload;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
t->pos.pcounter_orig++;
|
||||
t->pos.pdcounter_orig += !!len_payload;
|
||||
t->pos.pbcounter_orig += len_payload;
|
||||
t->pos.client.pcounter++;
|
||||
t->pos.client.pdcounter += !!len_payload;
|
||||
t->pos.client.pbcounter += len_payload;
|
||||
}
|
||||
|
||||
if (tcphdr)
|
||||
@@ -153,16 +187,16 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
if (tcp_syn_segment(tcphdr))
|
||||
{
|
||||
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->pos.seq0 = ntohl(tcphdr->th_seq);
|
||||
t->pos.client.seq0 = ntohl(tcphdr->th_seq);
|
||||
}
|
||||
else if (tcp_synack_segment(tcphdr))
|
||||
{
|
||||
// ignore SA dups
|
||||
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
if (t->pos.state != SYN && t->pos.seq0 != seq0)
|
||||
if (t->pos.state != SYN && t->pos.client.seq0 != seq0)
|
||||
ConntrackReInitTrack(t); // erase current entry
|
||||
if (!t->pos.seq0) t->pos.seq0 = seq0;
|
||||
t->pos.ack0 = ntohl(tcphdr->th_seq);
|
||||
if (!t->pos.client.seq0) t->pos.client.seq0 = seq0;
|
||||
t->pos.server.seq0 = ntohl(tcphdr->th_seq);
|
||||
}
|
||||
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
|
||||
{
|
||||
@@ -173,65 +207,16 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
if (t->pos.state == SYN)
|
||||
{
|
||||
t->pos.state = ESTABLISHED;
|
||||
if (!bReverse && !t->pos.ack0) t->pos.ack0 = ntohl(tcphdr->th_ack) - 1;
|
||||
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
}
|
||||
}
|
||||
scale = tcp_find_scale_factor(tcphdr);
|
||||
mss = ntohs(tcp_find_mss(tcphdr));
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.ack_last = ntohl(tcphdr->th_seq);
|
||||
t->pos.pos_orig = t->pos.seq_last = ntohl(tcphdr->th_ack);
|
||||
t->pos.pos_reply = t->pos.ack_last + len_payload;
|
||||
if (t->pos.state == SYN)
|
||||
t->pos.uppos_reply_prev = t->pos.uppos_reply = t->pos.pos_reply;
|
||||
else if (len_payload)
|
||||
{
|
||||
t->pos.uppos_reply_prev = t->pos.uppos_reply;
|
||||
if (!((t->pos.pos_reply - t->pos.uppos_reply) & 0x80000000))
|
||||
t->pos.uppos_reply = t->pos.pos_reply;
|
||||
}
|
||||
t->pos.winsize_reply = ntohs(tcphdr->th_win);
|
||||
t->pos.winsize_reply_calc = t->pos.winsize_reply;
|
||||
if (t->pos.scale_reply != SCALE_NONE) t->pos.winsize_reply_calc <<= t->pos.scale_reply;
|
||||
if (mss && !t->pos.mss_reply) t->pos.mss_reply = mss;
|
||||
if (scale != SCALE_NONE) t->pos.scale_reply = scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->pos.seq_last = ntohl(tcphdr->th_seq);
|
||||
t->pos.pos_orig = t->pos.seq_last + len_payload;
|
||||
t->pos.pos_reply = t->pos.ack_last = ntohl(tcphdr->th_ack);
|
||||
if (t->pos.state == SYN)
|
||||
t->pos.uppos_orig_prev = t->pos.uppos_orig = t->pos.pos_orig;
|
||||
else if (len_payload)
|
||||
{
|
||||
t->pos.uppos_orig_prev = t->pos.uppos_orig;
|
||||
if (!((t->pos.pos_orig - t->pos.uppos_orig) & 0x80000000))
|
||||
t->pos.uppos_orig = t->pos.pos_orig;
|
||||
}
|
||||
t->pos.winsize_orig = ntohs(tcphdr->th_win);
|
||||
t->pos.winsize_orig_calc = t->pos.winsize_orig;
|
||||
if (t->pos.scale_orig != SCALE_NONE) t->pos.winsize_orig_calc <<= t->pos.scale_orig;
|
||||
if (mss && !t->pos.mss_reply) t->pos.mss_orig = mss;
|
||||
if (scale != SCALE_NONE) t->pos.scale_orig = scale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.ack_last = t->pos.pos_reply;
|
||||
t->pos.pos_reply += len_payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->pos.seq_last = t->pos.pos_orig;
|
||||
t->pos.pos_orig += len_payload;
|
||||
}
|
||||
|
||||
ConntrackApplyPos(tcphdr, t, bReverse, len_payload);
|
||||
}
|
||||
|
||||
time(&t->pos.t_last);
|
||||
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
|
||||
// make sure t_start gets exactly the same value as first t_last
|
||||
if (!t->t_start.tv_sec) t->t_start = t->pos.t_last;
|
||||
}
|
||||
|
||||
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||
@@ -327,13 +312,15 @@ bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr
|
||||
|
||||
void ConntrackPoolPurge(t_conntrack *p)
|
||||
{
|
||||
time_t tidle, tnow = time(NULL);
|
||||
time_t tidle;
|
||||
struct timespec tnow;
|
||||
t_conntrack_pool *t, *tmp;
|
||||
|
||||
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
|
||||
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
|
||||
if ((tnow.tv_sec - p->t_last_purge) >= p->t_purge_interval)
|
||||
{
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
tidle = tnow - t->track.pos.t_last;
|
||||
tidle = tnow.tv_sec - t->track.pos.t_last.tv_sec;
|
||||
if (t->track.b_cutoff ||
|
||||
(t->conn.l4proto == IPPROTO_TCP && (
|
||||
(t->track.pos.state == SYN && tidle >= p->timeout_syn) ||
|
||||
@@ -345,7 +332,7 @@ void ConntrackPoolPurge(t_conntrack *p)
|
||||
HASH_DEL(p->pool, t); ConntrackFreeElem(t);
|
||||
}
|
||||
}
|
||||
p->t_last_purge = tnow;
|
||||
p->t_last_purge = tnow.tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,29 +344,31 @@ static void taddr2str(uint8_t l3proto, const t_addr *a, char *buf, size_t bufsiz
|
||||
void ConntrackPoolDump(const t_conntrack *p)
|
||||
{
|
||||
t_conntrack_pool *t, *tmp;
|
||||
struct timespec tnow;
|
||||
char sa1[40], sa2[40];
|
||||
time_t tnow = time(NULL);
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
|
||||
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu orig=d%llu/n%llu/b%llu reply=d%llu/n%llu/b%lld ",
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%lld ",
|
||||
proto_name(t->conn.l4proto),
|
||||
sa1, t->conn.sport, sa2, t->conn.dport,
|
||||
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
|
||||
(unsigned long long)t->track.pos.t_start, (unsigned long long)(t->track.pos.t_last - t->track.pos.t_start), (unsigned long long)(tnow - t->track.pos.t_last),
|
||||
(unsigned long long)t->track.pos.pdcounter_orig, (unsigned long long)t->track.pos.pcounter_orig, (unsigned long long)t->track.pos.pbcounter_orig,
|
||||
(unsigned long long)t->track.pos.pdcounter_reply, (unsigned long long)t->track.pos.pcounter_reply, (unsigned long long)t->track.pos.pbcounter_reply);
|
||||
(unsigned long long)t->track.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow.tv_sec - t->track.pos.t_last.tv_sec),
|
||||
(unsigned long long)t->track.pos.client.pdcounter, (unsigned long long)t->track.pos.client.pcounter, (unsigned long long)t->track.pos.client.pbcounter,
|
||||
(unsigned long long)t->track.pos.server.pdcounter, (unsigned long long)t->track.pos.server.pcounter, (unsigned long long)t->track.pos.server.pbcounter);
|
||||
if (t->conn.l4proto == IPPROTO_TCP)
|
||||
printf("seq0=%u rseq=%u pos_orig=%u ack0=%u rack=%u pos_reply=%u mss_orig=%u mss_reply=%u wsize_orig=%u:%d wsize_reply=%u:%d",
|
||||
t->track.pos.seq0, t->track.pos.seq_last - t->track.pos.seq0, t->track.pos.pos_orig - t->track.pos.seq0,
|
||||
t->track.pos.ack0, t->track.pos.ack_last - t->track.pos.ack0, t->track.pos.pos_reply - t->track.pos.ack0,
|
||||
t->track.pos.mss_orig, t->track.pos.mss_reply,
|
||||
t->track.pos.winsize_orig, t->track.pos.scale_orig == SCALE_NONE ? -1 : t->track.pos.scale_orig,
|
||||
t->track.pos.winsize_reply, t->track.pos.scale_reply == SCALE_NONE ? -1 : t->track.pos.scale_reply);
|
||||
printf("seq0=%u rseq=%u client.pos=%u ack0=%u rack=%u server.pos=%u client.mss=%u server.mss=%u client.wsize=%u:%d server.wsize=%u:%d",
|
||||
t->track.pos.client.seq0, t->track.pos.client.seq_last - t->track.pos.client.seq0, t->track.pos.client.pos - t->track.pos.client.seq0,
|
||||
t->track.pos.server.seq0, t->track.pos.server.seq_last - t->track.pos.server.seq0, t->track.pos.server.pos - t->track.pos.server.seq0,
|
||||
t->track.pos.client.mss, t->track.pos.server.mss,
|
||||
t->track.pos.client.winsize, t->track.pos.client.scale == SCALE_NONE ? -1 : t->track.pos.client.scale,
|
||||
t->track.pos.server.winsize, t->track.pos.server.scale == SCALE_NONE ? -1 : t->track.pos.server.scale);
|
||||
else
|
||||
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
|
||||
t->track.pos.seq_last, t->track.pos.pos_orig,
|
||||
t->track.pos.ack_last, t->track.pos.pos_reply);
|
||||
printf("rseq=%u client.pos=%u rack=%u server.pos=%u",
|
||||
t->track.pos.client.seq_last, t->track.pos.client.pos,
|
||||
t->track.pos.server.seq_last, t->track.pos.server.pos);
|
||||
printf(" req_retrans=%u cutoff=%u lua_in_cutoff=%u lua_out_cutoff=%u hostname=%s l7proto=%s\n",
|
||||
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_lua_in_cutoff, t->track.b_lua_out_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
|
||||
};
|
||||
|
||||
@@ -54,14 +54,16 @@ typedef struct
|
||||
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
|
||||
uint8_t ipproto;
|
||||
|
||||
struct timespec t_start;
|
||||
|
||||
// this block of data can change between delayed (queued) packets. need to remeber this data for each packet for further replay
|
||||
t_ctrack_position pos;
|
||||
t_ctrack_positions pos;
|
||||
|
||||
struct desync_profile *dp; // desync profile cache
|
||||
bool dp_search_complete;
|
||||
|
||||
uint8_t req_retrans_counter; // number of request retransmissions
|
||||
bool retrans_detect_finalized;
|
||||
bool failure_detect_finalized;
|
||||
|
||||
uint8_t incoming_ttl;
|
||||
|
||||
@@ -78,7 +80,7 @@ typedef struct
|
||||
int lua_state; // registry index of associated LUA object
|
||||
int lua_instance_cutoff; // registry index of per connection function instance cutoff table
|
||||
|
||||
t_reassemble reasm_orig;
|
||||
t_reassemble reasm_client;
|
||||
struct rawpacket_tailhead delayed;
|
||||
} t_ctrack;
|
||||
|
||||
|
||||
@@ -14,21 +14,27 @@ typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
time_t t_last, t_start;
|
||||
|
||||
uint64_t pcounter_orig, pcounter_reply; // packet counter
|
||||
uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload)
|
||||
uint64_t pbcounter_orig, pbcounter_reply; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||
uint32_t pos_orig, pos_reply; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
uint32_t uppos_orig, uppos_reply; // max seen position. useful to detect retransmissions
|
||||
uint32_t uppos_orig_prev, uppos_reply_prev; // previous max seen position. useful to detect retransmissions
|
||||
uint32_t seq_last, ack_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
|
||||
uint64_t pcounter; // packet counter
|
||||
uint64_t pdcounter; // data packet counter (with payload)
|
||||
uint64_t pbcounter; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||
|
||||
// tcp only state, not used in udp
|
||||
t_connstate state;
|
||||
uint32_t seq0, ack0; // starting seq and ack
|
||||
uint16_t winsize_orig, winsize_reply; // last seen window size
|
||||
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
|
||||
uint32_t winsize_orig_calc, winsize_reply_calc; // calculated window size
|
||||
uint16_t mss_orig, mss_reply;
|
||||
uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
uint32_t uppos; // max seen position. useful to detect retransmissions
|
||||
uint32_t uppos_prev; // previous max seen position. useful to detect retransmissions
|
||||
uint32_t seq_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
|
||||
uint32_t seq0; // starting seq and ack
|
||||
uint16_t winsize; // last seen window size
|
||||
uint16_t mss;
|
||||
uint32_t winsize_calc; // calculated window size
|
||||
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
|
||||
bool rseq_over_2G;
|
||||
} t_ctrack_position;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct timespec t_last;
|
||||
t_connstate state;
|
||||
t_ctrack_position client, server;
|
||||
}
|
||||
t_ctrack_positions;
|
||||
|
||||
182
nfq2/darkmagic.c
182
nfq2/darkmagic.c
@@ -40,9 +40,6 @@
|
||||
#include <linux/genetlink.h>
|
||||
#include <libmnl/libmnl.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
|
||||
|
||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
||||
@@ -721,6 +718,29 @@ bool prepare_low_appdata()
|
||||
return b;
|
||||
}
|
||||
|
||||
BOOL JobSandbox()
|
||||
{
|
||||
BOOL bRes = FALSE;
|
||||
HANDLE hJob;
|
||||
JOBOBJECT_BASIC_LIMIT_INFORMATION basic_limit;
|
||||
JOBOBJECT_BASIC_UI_RESTRICTIONS basic_ui;
|
||||
|
||||
if (hJob = CreateJobObjectW(NULL, NULL))
|
||||
{
|
||||
basic_limit.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
|
||||
// prevent child process creation
|
||||
basic_limit.ActiveProcessLimit = 1;
|
||||
// prevent some UI interaction and settings change
|
||||
basic_ui.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_GLOBALATOMS | JOB_OBJECT_UILIMIT_HANDLES | JOB_OBJECT_UILIMIT_READCLIPBOARD | JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
|
||||
bRes = SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &basic_limit, sizeof(basic_limit)) &&
|
||||
SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &basic_ui, sizeof(basic_ui)) &&
|
||||
AssignProcessToJobObject(hJob, GetCurrentProcess());
|
||||
w_win32_error = GetLastError();
|
||||
CloseHandle(hJob);
|
||||
}
|
||||
return bRes;
|
||||
}
|
||||
|
||||
|
||||
#define WINDIVERT_DEVICE_NAME "WinDivert"
|
||||
static bool b_isandbox_set = false;
|
||||
@@ -737,6 +757,8 @@ bool win_sandbox(void)
|
||||
return FALSE;
|
||||
if (!LowMandatoryLevel())
|
||||
return false;
|
||||
if (!JobSandbox())
|
||||
return false;
|
||||
// for LUA code to find where to store files
|
||||
b_isandbox_set = true;
|
||||
}
|
||||
@@ -1578,9 +1600,9 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
|
||||
|
||||
// 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];
|
||||
struct nlmsghdr *nlh;
|
||||
@@ -1595,7 +1617,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
|
||||
genl->cmd = cmd;
|
||||
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)
|
||||
{
|
||||
@@ -1619,7 +1641,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
|
||||
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");
|
||||
}
|
||||
@@ -1651,7 +1673,7 @@ static int wlan_id_cb(const struct nlmsghdr *nlh, void *data)
|
||||
static uint16_t wlan_get_family_id(struct mnl_socket* nl)
|
||||
{
|
||||
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)
|
||||
@@ -1686,42 +1708,130 @@ static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
struct wlan_interface_collection *wc = (struct wlan_interface_collection*)data;
|
||||
if (wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
|
||||
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);
|
||||
if (ret>=0 && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), scan_info_attr_cb, wc->wlan+wc->count);
|
||||
if (ret>=0 && *wc->wlan[wc->count].ssid && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
|
||||
wc->count++;
|
||||
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)
|
||||
{
|
||||
if (!(*nl = mnl_socket_open(NETLINK_GENERIC)))
|
||||
@@ -1755,7 +1865,7 @@ static bool wlan_info_rate_limited(struct mnl_socket* nl, uint16_t wlan_family_i
|
||||
// do not purge too often to save resources
|
||||
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;
|
||||
}
|
||||
return bres;
|
||||
@@ -1781,10 +1891,6 @@ bool wlan_info_init(void)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool wlan_info_get(void)
|
||||
{
|
||||
return wlan_info(nl_wifi, id_nl80211, &wlans);
|
||||
}
|
||||
bool wlan_info_get_rate_limited(void)
|
||||
{
|
||||
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);
|
||||
bool wlan_info_init(void);
|
||||
bool wlan_info_get(void);
|
||||
bool wlan_info_get_rate_limited(void);
|
||||
const char *wlan_ssid_search_ifname(const char *ifname);
|
||||
const char *wlan_ssid_search_ifidx(int ifidx);
|
||||
|
||||
369
nfq2/desync.c
369
nfq2/desync.c
@@ -240,29 +240,27 @@ static void auto_hostlist_reset_fail_counter(struct desync_profile *dp, const ch
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_retransmission(const t_ctrack *ctrack)
|
||||
static bool is_retransmission(const t_ctrack_position *pos)
|
||||
{
|
||||
return !((ctrack->pos.uppos_orig_prev - ctrack->pos.pos_orig) & 0x80000000);
|
||||
return !((pos->uppos_prev - pos->pos) & 0x80000000);
|
||||
}
|
||||
|
||||
// return true if retrans trigger fires
|
||||
static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int threshold, const char *client_ip_port, t_l7proto l7proto)
|
||||
{
|
||||
if (ctrack && ctrack->dp && ctrack->hostname_ah_check && ctrack->req_retrans_counter != RETRANS_COUNTER_STOP)
|
||||
if (ctrack && ctrack->dp && ctrack->hostname_ah_check && !ctrack->failure_detect_finalized && ctrack->req_retrans_counter != RETRANS_COUNTER_STOP)
|
||||
{
|
||||
if (l4proto == IPPROTO_TCP)
|
||||
if (l4proto == IPPROTO_TCP && ctrack->pos.state!=SYN)
|
||||
{
|
||||
if (ctrack->retrans_detect_finalized)
|
||||
return false;
|
||||
if (!seq_within(ctrack->pos.seq_last, ctrack->pos.seq0, ctrack->pos.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq))
|
||||
if (!seq_within(ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq))
|
||||
{
|
||||
ctrack->retrans_detect_finalized = true;
|
||||
DLOG("retrans : tcp seq %u not within the req range %u-%u. stop tracking.\n", ctrack->pos.seq_last, ctrack->pos.seq0, ctrack->pos.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq);
|
||||
ctrack->failure_detect_finalized = true;
|
||||
DLOG("retrans : tcp seq %u not within range %u-%u. stop tracking.\n", ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq);
|
||||
ctrack_stop_retrans_counter(ctrack);
|
||||
auto_hostlist_reset_fail_counter(ctrack->dp, ctrack->hostname, client_ip_port, l7proto);
|
||||
return false;
|
||||
}
|
||||
if (!is_retransmission(ctrack))
|
||||
if (!is_retransmission(&ctrack->pos.client))
|
||||
return false;
|
||||
}
|
||||
ctrack->req_retrans_counter++;
|
||||
@@ -270,7 +268,7 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
|
||||
{
|
||||
DLOG("retrans threshold reached : %u/%u\n", ctrack->req_retrans_counter, threshold);
|
||||
ctrack_stop_retrans_counter(ctrack);
|
||||
ctrack->retrans_detect_finalized = true;
|
||||
ctrack->failure_detect_finalized = true;
|
||||
return true;
|
||||
}
|
||||
DLOG("retrans counter : %u/%u\n", ctrack->req_retrans_counter, threshold);
|
||||
@@ -325,23 +323,55 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_client_ip_port(const struct sockaddr *client, char *client_ip_port, size_t client_ip_port_size)
|
||||
{
|
||||
if (*params.hostlist_auto_debuglog)
|
||||
ntop46_port((struct sockaddr*)client, client_ip_port, client_ip_port_size);
|
||||
else
|
||||
*client_ip_port = 0;
|
||||
}
|
||||
static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto, const struct sockaddr *client)
|
||||
{
|
||||
if (params.server) return; // no autohostlists in server mode
|
||||
|
||||
char client_ip_port[48];
|
||||
if (*params.hostlist_auto_debuglog)
|
||||
ntop46_port((struct sockaddr*)client, client_ip_port, sizeof(client_ip_port));
|
||||
else
|
||||
*client_ip_port = 0;
|
||||
fill_client_ip_port(client, client_ip_port, sizeof(client_ip_port));
|
||||
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, proto, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto))
|
||||
{
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : retrans threshold reached", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(ctrack->dp), client_ip_port, l7proto_str(ctrack->l7proto));
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
}
|
||||
}
|
||||
static void process_udp_fail(t_ctrack *ctrack, const t_ctrack_positions *tpos, const struct sockaddr *client)
|
||||
{
|
||||
// no autohostlists in server mode
|
||||
if (!params.server && ctrack && ctrack->dp && ctrack->hostname && ctrack->hostname_ah_check &&
|
||||
!ctrack->failure_detect_finalized && ctrack->dp->hostlist_auto_udp_out)
|
||||
{
|
||||
char client_ip_port[48];
|
||||
|
||||
if (!tpos) tpos = &ctrack->pos;
|
||||
//printf("UDP_POS %u %u\n",tpos->client.pcounter, tpos->server.pcounter);
|
||||
if (tpos->server.pcounter > ctrack->dp->hostlist_auto_udp_in)
|
||||
{
|
||||
// success
|
||||
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)
|
||||
{
|
||||
// failure
|
||||
ctrack->failure_detect_finalized = true;
|
||||
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",
|
||||
ctrack->hostname, ctrack->dp->n, PROFILE_NAME(ctrack->dp), client_ip_port, l7proto_str(ctrack->l7proto),
|
||||
tpos->server.pcounter, ctrack->dp->hostlist_auto_udp_in,
|
||||
tpos->client.pcounter, ctrack->dp->hostlist_auto_udp_out);
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool send_delayed(t_ctrack *ctrack)
|
||||
{
|
||||
@@ -353,23 +383,22 @@ static bool send_delayed(t_ctrack *ctrack)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rawpacket_queue_csum_fix(struct rawpacket_tailhead *q, const struct dissect *dis, const t_ctrack_position *pos, const struct sockaddr_storage* dst, uint32_t fwmark, uint32_t desync_fwmark, const char *ifin, const char *ifout)
|
||||
static bool rawpacket_queue_csum_fix(struct rawpacket_tailhead *q, const struct dissect *dis, const t_ctrack_positions *tpos, const struct sockaddr_storage* dst, uint32_t fwmark, uint32_t desync_fwmark, const char *ifin, const char *ifout)
|
||||
{
|
||||
// this breaks const pointer to l4 header
|
||||
if (dis->tcp)
|
||||
verdict_tcp_csum_fix(VERDICT_PASS, (struct tcphdr *)dis->tcp, dis->transport_len, dis->ip, dis->ip6);
|
||||
else if (dis->udp)
|
||||
verdict_udp_csum_fix(VERDICT_PASS, (struct udphdr *)dis->udp, dis->transport_len, dis->ip, dis->ip6);
|
||||
return rawpacket_queue(q, dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, pos);
|
||||
return rawpacket_queue(q, dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, tpos);
|
||||
}
|
||||
|
||||
|
||||
static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
||||
static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, uint32_t seq, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
||||
{
|
||||
ReasmClear(reasm);
|
||||
if (sz <= szMax)
|
||||
{
|
||||
uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->pos.seq_last : 0;
|
||||
if (ReasmInit(reasm, sz, seq))
|
||||
{
|
||||
ReasmFeed(reasm, seq, data_payload, len_payload);
|
||||
@@ -383,15 +412,24 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, si
|
||||
DLOG("unexpected large payload for reassemble: size=%zu\n", sz);
|
||||
return false;
|
||||
}
|
||||
static bool reasm_orig_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)
|
||||
{
|
||||
return reasm_start(ctrack, &ctrack->reasm_orig, proto, sz, szMax, data_payload, len_payload);
|
||||
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);
|
||||
}
|
||||
static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, 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)
|
||||
{
|
||||
if (ctrack && !ReasmIsEmpty(reasm))
|
||||
{
|
||||
uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->pos.seq_last : (uint32_t)reasm->size_present;
|
||||
if (ReasmFeed(reasm, seq, data_payload, len_payload))
|
||||
{
|
||||
DLOG("reassemble : feeding data payload size=%zu. now we have %zu/%zu\n", len_payload, reasm->size_present, reasm->size);
|
||||
@@ -406,29 +444,30 @@ static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, con
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static bool reasm_orig_feed(t_ctrack *ctrack, uint8_t proto, const uint8_t *data_payload, size_t len_payload)
|
||||
static bool reasm_client_feed(t_ctrack *ctrack, uint8_t proto, const uint8_t *data_payload, size_t len_payload)
|
||||
{
|
||||
return reasm_feed(ctrack, &ctrack->reasm_orig, proto, data_payload, len_payload);
|
||||
if (!ctrack) return false;
|
||||
return reasm_feed(ctrack, &ctrack->reasm_client, proto, (proto == IPPROTO_TCP) ? ctrack->pos.client.seq_last : (uint32_t)ctrack->reasm_client.size_present, data_payload, len_payload);
|
||||
}
|
||||
static void reasm_orig_stop(t_ctrack *ctrack, const char *dlog_msg)
|
||||
static void reasm_client_stop(t_ctrack *ctrack, const char *dlog_msg)
|
||||
{
|
||||
if (ctrack)
|
||||
{
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_orig))
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_client))
|
||||
{
|
||||
DLOG("%s", dlog_msg);
|
||||
ReasmClear(&ctrack->reasm_orig);
|
||||
ReasmClear(&ctrack->reasm_client);
|
||||
}
|
||||
send_delayed(ctrack);
|
||||
}
|
||||
}
|
||||
static void reasm_orig_cancel(t_ctrack *ctrack)
|
||||
static void reasm_client_cancel(t_ctrack *ctrack)
|
||||
{
|
||||
reasm_orig_stop(ctrack, "reassemble session cancelled\n");
|
||||
reasm_client_stop(ctrack, "reassemble session cancelled\n");
|
||||
}
|
||||
static void reasm_orig_fin(t_ctrack *ctrack)
|
||||
static void reasm_client_fin(t_ctrack *ctrack)
|
||||
{
|
||||
reasm_orig_stop(ctrack, "reassemble session finished\n");
|
||||
reasm_client_stop(ctrack, "reassemble session finished\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -438,7 +477,7 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
|
||||
// if used in postnat chain, dropping initial packet will cause conntrack connection teardown
|
||||
// so we need to workaround this.
|
||||
// SYN and SYN,ACK checks are for conntrack-less mode
|
||||
if (ctrack && (params.server ? ctrack->pos.pcounter_reply : ctrack->pos.pcounter_orig) == 1 || dis->tcp && (tcp_syn_segment(dis->tcp) || tcp_synack_segment(dis->tcp)))
|
||||
if (ctrack && (params.server ? ctrack->pos.server.pcounter : ctrack->pos.client.pcounter) == 1 || dis->tcp && (tcp_syn_segment(dis->tcp) || tcp_synack_segment(dis->tcp)))
|
||||
{
|
||||
if (dis->len_pkt > *len_mod_pkt)
|
||||
DLOG_ERR("linux postnat conntrack workaround cannot be applied\n");
|
||||
@@ -466,30 +505,34 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
|
||||
return VERDICT_DROP;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t pos_get(const t_ctrack_position *pos, char mode, bool bReply)
|
||||
static bool pos_overflow(const t_ctrack_position *pos, char mode)
|
||||
{
|
||||
return (mode=='s' || mode=='p') && pos && pos->rseq_over_2G;
|
||||
}
|
||||
static uint64_t pos_get(const t_ctrack_position *pos, char mode)
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case 'n': return bReply ? pos->pcounter_reply : pos->pcounter_orig;
|
||||
case 'd': return bReply ? pos->pdcounter_reply : pos->pdcounter_orig;
|
||||
case 's': return bReply ? (pos->ack_last - pos->ack0) : (pos->seq_last - pos->seq0);
|
||||
case 'b': return bReply ? pos->pbcounter_reply : pos->pbcounter_orig;
|
||||
case 'n': return pos->pcounter;
|
||||
case 'd': return pos->pdcounter;
|
||||
case 's': return pos->seq_last - pos->seq0;
|
||||
case 'p': return pos->pos - pos->seq0;
|
||||
case 'b': return pos->pbcounter;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static bool check_pos_from(const t_ctrack_position *pos, bool bReply, const struct packet_range *range)
|
||||
static bool check_pos_from(const t_ctrack_position *pos, const struct packet_range *range)
|
||||
{
|
||||
uint64_t ps;
|
||||
if (range->from.mode == 'x') return false;
|
||||
if ((range->from.mode == 'x') || pos_overflow(pos,range->from.mode)) return false;
|
||||
if (range->from.mode != 'a')
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
ps = pos_get(pos, range->from.mode, bReply);
|
||||
ps = pos_get(pos, range->from.mode);
|
||||
return ps >= range->from.pos;
|
||||
}
|
||||
else
|
||||
@@ -497,15 +540,15 @@ static bool check_pos_from(const t_ctrack_position *pos, bool bReply, const stru
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool check_pos_to(const t_ctrack_position *pos, bool bReply, const struct packet_range *range)
|
||||
static bool check_pos_to(const t_ctrack_position *pos, const struct packet_range *range)
|
||||
{
|
||||
uint64_t ps;
|
||||
if (range->to.mode == 'x') return false;
|
||||
if (range->to.mode == 'x' || pos_overflow(pos,range->to.mode)) return false;
|
||||
if (range->to.mode != 'a')
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
ps = pos_get(pos, range->to.mode, bReply);
|
||||
ps = pos_get(pos, range->to.mode);
|
||||
return (ps < range->to.pos) || !range->upper_cutoff && (ps == range->to.pos);
|
||||
}
|
||||
else
|
||||
@@ -513,14 +556,14 @@ static bool check_pos_to(const t_ctrack_position *pos, bool bReply, const struct
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool check_pos_cutoff(const t_ctrack_position *pos, bool bReply, const struct packet_range *range)
|
||||
static bool check_pos_cutoff(const t_ctrack_position *pos, const struct packet_range *range)
|
||||
{
|
||||
bool bto = check_pos_to(pos, bReply, range);
|
||||
return pos ? !bto : (!bto || !check_pos_from(pos, bReply, range));
|
||||
bool bto = check_pos_to(pos, range);
|
||||
return pos ? !bto : (!bto || !check_pos_from(pos, range));
|
||||
}
|
||||
static bool check_pos_range(const t_ctrack_position *pos, bool bReply, const struct packet_range *range)
|
||||
static bool check_pos_range(const t_ctrack_position *pos, const struct packet_range *range)
|
||||
{
|
||||
return check_pos_from(pos, bReply, range) && check_pos_to(pos, bReply, range);
|
||||
return check_pos_from(pos, range) && check_pos_to(pos, range);
|
||||
}
|
||||
|
||||
|
||||
@@ -654,7 +697,7 @@ static uint8_t desync(
|
||||
const char *ifout,
|
||||
bool bIncoming,
|
||||
t_ctrack *ctrack,
|
||||
const t_ctrack_position *pos,
|
||||
const t_ctrack_positions *tpos,
|
||||
t_l7payload l7payload,
|
||||
t_l7proto l7proto,
|
||||
const struct dissect *dis,
|
||||
@@ -667,11 +710,12 @@ static uint8_t desync(
|
||||
struct func_list *func;
|
||||
int ref_arg = LUA_NOREF, status;
|
||||
bool b, b_cutoff_all, b_unwanted_payload;
|
||||
t_lua_desync_context ctx = { .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false, .incoming = bIncoming };
|
||||
t_lua_desync_context ctx = { .magic = 0, .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false, .incoming = bIncoming };
|
||||
const char *sDirection = bIncoming ? "in" : "out";
|
||||
struct packet_range *range;
|
||||
size_t l;
|
||||
char instance[256];
|
||||
const t_ctrack_position *pos, *rpos;
|
||||
|
||||
if (ctrack)
|
||||
{
|
||||
@@ -686,8 +730,10 @@ static uint8_t desync(
|
||||
DLOG("lua out cutoff\n");
|
||||
return verdict;
|
||||
}
|
||||
if (!pos) pos = &ctrack->pos;
|
||||
if (!tpos) tpos = &ctrack->pos;
|
||||
}
|
||||
pos = tpos ? (bIncoming ^ params.server) ? &tpos->server : &tpos->client : NULL;
|
||||
rpos = tpos ? (bIncoming ^ params.server) ? &tpos->client : &tpos->server : NULL;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
@@ -709,12 +755,14 @@ static uint8_t desync(
|
||||
{
|
||||
if (lua_instance_cutoff_check(&ctx, bIncoming))
|
||||
DLOG("* lua '%s' : voluntary cutoff\n", instance);
|
||||
else if (check_pos_cutoff(pos, bIncoming, range))
|
||||
else if (check_pos_cutoff(pos, range))
|
||||
{
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu is beyond range %c%u%c%c%u (ctrack %s)\n",
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu overflow %u %u is beyond range %c%u%c%c%u (ctrack %s)\n",
|
||||
instance, sDirection,
|
||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
||||
range->from.mode, pos_get(pos, range->from.mode),
|
||||
range->to.mode, pos_get(pos, range->to.mode),
|
||||
pos_overflow(pos, range->from.mode),
|
||||
pos_overflow(pos, range->to.mode),
|
||||
range->from.mode, range->from.pos,
|
||||
range->upper_cutoff ? '<' : '-',
|
||||
range->to.mode, range->to.pos,
|
||||
@@ -737,7 +785,7 @@ static uint8_t desync(
|
||||
// create arg table that persists across multiple desync function calls
|
||||
lua_newtable(params.L);
|
||||
lua_pushf_dissect(dis);
|
||||
lua_pushf_ctrack(ctrack, pos);
|
||||
lua_pushf_ctrack(ctrack, tpos, bIncoming);
|
||||
lua_pushf_int("profile_n", dp->n);
|
||||
if (dp->name) lua_pushf_str("profile_name", dp->name);
|
||||
if (dp->n_tpl) lua_pushf_int("template_n", dp->n_tpl);
|
||||
@@ -769,8 +817,8 @@ static uint8_t desync(
|
||||
if (dis->tcp)
|
||||
{
|
||||
// recommended mss value for generated packets
|
||||
if (pos && pos->mss_orig)
|
||||
lua_pushf_int("tcp_mss", pos->mss_orig);
|
||||
if (rpos && rpos->mss)
|
||||
lua_pushf_int("tcp_mss", rpos->mss);
|
||||
else
|
||||
lua_pushf_global("tcp_mss", "DEFAULT_MSS");
|
||||
}
|
||||
@@ -786,12 +834,12 @@ static uint8_t desync(
|
||||
if (!lua_instance_cutoff_check(&ctx, bIncoming))
|
||||
{
|
||||
range = bIncoming ? &func->range_in : &func->range_out;
|
||||
if (check_pos_range(pos, bIncoming, range))
|
||||
if (check_pos_range(pos, range))
|
||||
{
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu in range %c%u%c%c%u\n",
|
||||
instance, sDirection,
|
||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
||||
range->from.mode, pos_get(pos, range->from.mode),
|
||||
range->to.mode, pos_get(pos, range->to.mode),
|
||||
range->from.mode, range->from.pos,
|
||||
range->upper_cutoff ? '<' : '-',
|
||||
range->to.mode, range->to.pos);
|
||||
@@ -808,12 +856,18 @@ static uint8_t desync(
|
||||
}
|
||||
lua_pushlightuserdata(params.L, &ctx);
|
||||
lua_rawgeti(params.L, LUA_REGISTRYINDEX, ref_arg);
|
||||
lua_pushf_args(&func->args, -1);
|
||||
lua_pushf_args(&func->args, -1, true);
|
||||
lua_pushf_str("func", func->func);
|
||||
lua_pushf_int("func_n", ctx.func_n);
|
||||
lua_pushf_str("func_instance", instance);
|
||||
int initial_stack_top = lua_gettop(params.L);
|
||||
|
||||
// lua should not store and access ctx outside of this call
|
||||
// if this happens make our best to prevent access to bad memory
|
||||
// this is not crash-proof but better than nothing
|
||||
ctx.magic = MAGIC_CTX; // mark struct as valid
|
||||
status = lua_pcall(params.L, 2, LUA_MULTRET, 0);
|
||||
ctx.magic = 0; // mark struct as invalid
|
||||
|
||||
if (status)
|
||||
{
|
||||
lua_dlog_error();
|
||||
@@ -836,8 +890,8 @@ static uint8_t desync(
|
||||
else
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu out of range %c%u%c%c%u\n",
|
||||
instance, sDirection,
|
||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
||||
range->from.mode, pos_get(pos, range->from.mode),
|
||||
range->to.mode, pos_get(pos, range->to.mode),
|
||||
range->from.mode, range->from.pos,
|
||||
range->upper_cutoff ? '<' : '-',
|
||||
range->to.mode, range->to.pos);
|
||||
@@ -932,11 +986,28 @@ 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(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||
uint32_t fwmark,
|
||||
const char *ifin, const char *ifout,
|
||||
const t_ctrack_position *pos,
|
||||
const t_ctrack_positions *tpos,
|
||||
const struct dissect *dis,
|
||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
{
|
||||
@@ -1093,49 +1164,48 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
// process reply packets for auto hostlist mode
|
||||
// by looking at RSTs or HTTP replies we decide whether original request looks like DPI blocked
|
||||
// we only process first-sequence replies. do not react to subsequent redirects or RSTs
|
||||
if (!params.server && ctrack && ctrack->hostname && ctrack->hostname_ah_check && (ctrack->pos.ack_last - ctrack->pos.ack0) == 1)
|
||||
if (!params.server && ctrack && ctrack->hostname_ah_check && !ctrack->failure_detect_finalized && dp->hostlist_auto_incoming_maxseq)
|
||||
{
|
||||
bool bFail = false;
|
||||
|
||||
char client_ip_port[48];
|
||||
if (*params.hostlist_auto_debuglog)
|
||||
ntop46_port((struct sockaddr*)&dst, client_ip_port, sizeof(client_ip_port));
|
||||
else
|
||||
*client_ip_port = 0;
|
||||
|
||||
if (dis->tcp->th_flags & TH_RST)
|
||||
uint32_t rseq = ctrack->pos.server.seq_last - ctrack->pos.server.seq0;
|
||||
if (rseq)
|
||||
{
|
||||
DLOG("incoming RST detected for hostname %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : incoming RST", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto));
|
||||
bFail = true;
|
||||
}
|
||||
else if (dis->len_payload && l7proto == L7_HTTP)
|
||||
{
|
||||
if (l7payload == L7P_HTTP_REPLY)
|
||||
char client_ip_port[48];
|
||||
fill_client_ip_port((struct sockaddr*)&dst, client_ip_port, sizeof(client_ip_port));
|
||||
if (seq_within(ctrack->pos.server.seq_last, ctrack->pos.server.seq0 + 1, ctrack->pos.server.seq0 + dp->hostlist_auto_incoming_maxseq))
|
||||
{
|
||||
DLOG("incoming HTTP reply detected for hostname %s\n", ctrack->hostname);
|
||||
bFail = HttpReplyLooksLikeDPIRedirect(dis->data_payload, dis->len_payload, ctrack->hostname);
|
||||
bool bFail = false;
|
||||
|
||||
if (dis->tcp->th_flags & TH_RST)
|
||||
{
|
||||
DLOG("incoming RST detected for hostname %s rseq %u\n", ctrack->hostname, rseq);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : rseq %u : incoming RST", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto), rseq);
|
||||
bFail = true;
|
||||
}
|
||||
else if (dis->len_payload && l7payload == L7P_HTTP_REPLY)
|
||||
{
|
||||
DLOG("incoming HTTP reply detected for hostname %s rseq %u\n", ctrack->hostname, rseq);
|
||||
bFail = HttpReplyLooksLikeDPIRedirect(dis->data_payload, dis->len_payload, ctrack->hostname);
|
||||
if (bFail)
|
||||
{
|
||||
DLOG("redirect to another domain detected. possibly DPI redirect.\n");
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : rseq %u : redirect to another domain", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto), rseq);
|
||||
}
|
||||
else
|
||||
DLOG("local or in-domain redirect detected. it's not a DPI redirect.\n");
|
||||
}
|
||||
if (bFail)
|
||||
{
|
||||
DLOG("redirect to another domain detected. possibly DPI redirect.\n");
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : redirect to another domain", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto));
|
||||
auto_hostlist_failed(dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, l7proto);
|
||||
ctrack->failure_detect_finalized = true;
|
||||
}
|
||||
else
|
||||
DLOG("local or in-domain redirect detected. it's not a DPI redirect.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// received not http reply. do not monitor this connection anymore
|
||||
DLOG("incoming unknown HTTP data detected for hostname %s\n", ctrack->hostname);
|
||||
// incoming_maxseq exceeded. treat connection as successful
|
||||
auto_hostlist_reset_fail_counter(dp, ctrack->hostname, client_ip_port, l7proto);
|
||||
ctrack->failure_detect_finalized = true;
|
||||
}
|
||||
}
|
||||
if (bFail)
|
||||
auto_hostlist_failed(dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, l7proto);
|
||||
else
|
||||
if (dis->len_payload)
|
||||
auto_hostlist_reset_fail_counter(dp, ctrack->hostname, client_ip_port, l7proto);
|
||||
if (dis->tcp->th_flags & TH_RST)
|
||||
ctrack->hostname_ah_check = false; // do not react to further dup RSTs
|
||||
}
|
||||
}
|
||||
// not reverse
|
||||
@@ -1144,18 +1214,17 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
struct blob_collection_head *fake;
|
||||
uint8_t *p, *phost = NULL;
|
||||
int i;
|
||||
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
|
||||
if (replay_piece_count)
|
||||
{
|
||||
rdata_payload = ctrack_replay->reasm_orig.packet;
|
||||
rlen_payload = ctrack_replay->reasm_orig.size_present;
|
||||
rdata_payload = ctrack_replay->reasm_client.packet;
|
||||
rlen_payload = ctrack_replay->reasm_client.size_present;
|
||||
}
|
||||
else if (reasm_orig_feed(ctrack, IPPROTO_TCP, dis->data_payload, dis->len_payload))
|
||||
else if (reasm_client_feed(ctrack, IPPROTO_TCP, dis->data_payload, dis->len_payload))
|
||||
{
|
||||
rdata_payload = ctrack->reasm_orig.packet;
|
||||
rlen_payload = ctrack->reasm_orig.size_present;
|
||||
rdata_payload = ctrack->reasm_client.packet;
|
||||
rlen_payload = ctrack->reasm_client.size_present;
|
||||
}
|
||||
|
||||
process_retrans_fail(ctrack, IPPROTO_TCP, (struct sockaddr*)&src);
|
||||
@@ -1170,7 +1239,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
}
|
||||
|
||||
// we do not reassemble http
|
||||
reasm_orig_cancel(ctrack);
|
||||
reasm_client_cancel(ctrack);
|
||||
|
||||
bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host));
|
||||
if (!bHaveHost)
|
||||
@@ -1196,14 +1265,14 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
if (ctrack && !(params.reasm_payload_disable && l7_payload_match(l7payload, params.reasm_payload_disable)))
|
||||
{
|
||||
// do not reasm retransmissions
|
||||
if (!bReqFull && ReasmIsEmpty(&ctrack->reasm_orig) && !is_retransmission(ctrack))
|
||||
if (!bReqFull && ReasmIsEmpty(&ctrack->reasm_client) && !is_retransmission(&ctrack->pos.client))
|
||||
{
|
||||
// do not reconstruct unexpected large payload (they are feeding garbage ?)
|
||||
if (!reasm_orig_start(ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload))
|
||||
if (!reasm_client_start(ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload))
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_orig))
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_client))
|
||||
{
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
{
|
||||
@@ -1214,16 +1283,16 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
DLOG_ERR("rawpacket_queue failed !\n");
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
if (ReasmIsFull(&ctrack->reasm_orig))
|
||||
if (ReasmIsFull(&ctrack->reasm_client))
|
||||
{
|
||||
replay_queue(&ctrack->delayed);
|
||||
reasm_orig_fin(ctrack);
|
||||
reasm_client_fin(ctrack);
|
||||
}
|
||||
return VERDICT_DROP;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ctrack && (ctrack->pos.seq_last - ctrack->pos.seq0)==1 && IsMTProto(dis->data_payload, dis->len_payload))
|
||||
else if (ctrack && (ctrack->pos.client.seq_last - ctrack->pos.client.seq0)==1 && IsMTProto(dis->data_payload, dis->len_payload))
|
||||
{
|
||||
DLOG("packet contains telegram mtproto2 initial\n");
|
||||
// mtproto detection requires aes. react only on the first tcp data packet. do not detect if ctrack unavailable.
|
||||
@@ -1252,8 +1321,8 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
bool bDiscoveredL7;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != L7_UNKNOWN;
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
if (bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != L7_UNKNOWN)
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
@@ -1301,6 +1370,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
if (!dp) goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
dp_changed(ctrack_replay);
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
@@ -1343,19 +1413,19 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2));
|
||||
DLOG("dpi desync src=%s dst=%s track_direction=%s fixed_direction=%s connection_proto=%s payload_type=%s\n", s1, s2, bReverse ? "in" : "out", bReverseFixed ? "in" : "out", l7proto_str(l7proto), l7payload_str(l7payload));
|
||||
}
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, pos, l7payload, l7proto, dis, sdip4, sdip6, sdport, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, rdata_payload, rlen_payload, NULL, 0);
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, tpos, l7payload, l7proto, dis, sdip4, sdip6, sdport, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, rdata_payload, rlen_payload, NULL, 0);
|
||||
|
||||
pass:
|
||||
return (!bReverseFixed && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
||||
pass_reasm_cancel:
|
||||
reasm_orig_cancel(ctrack);
|
||||
reasm_client_cancel(ctrack);
|
||||
goto pass;
|
||||
}
|
||||
|
||||
// return : true - should continue, false - should stop with verdict
|
||||
static void quic_reasm_cancel(t_ctrack *ctrack, const char *reason)
|
||||
{
|
||||
reasm_orig_cancel(ctrack);
|
||||
reasm_client_cancel(ctrack);
|
||||
DLOG("%s\n", reason);
|
||||
}
|
||||
|
||||
@@ -1364,7 +1434,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||
uint32_t fwmark,
|
||||
const char *ifin, const char *ifout,
|
||||
const t_ctrack_position *pos,
|
||||
const t_ctrack_positions *tpos,
|
||||
const struct dissect *dis,
|
||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
{
|
||||
@@ -1550,8 +1620,8 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
|
||||
if (replay_piece_count)
|
||||
{
|
||||
clean_len = ctrack_replay->reasm_orig.size_present;
|
||||
pclean = ctrack_replay->reasm_orig.packet;
|
||||
clean_len = ctrack_replay->reasm_client.size_present;
|
||||
pclean = ctrack_replay->reasm_client.packet;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1561,13 +1631,13 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
if (pclean)
|
||||
{
|
||||
bool reasm_disable = params.reasm_payload_disable && l7_payload_match(l7payload, params.reasm_payload_disable);
|
||||
if (ctrack && !reasm_disable && !ReasmIsEmpty(&ctrack->reasm_orig))
|
||||
if (ctrack && !reasm_disable && !ReasmIsEmpty(&ctrack->reasm_client))
|
||||
{
|
||||
if (ReasmHasSpace(&ctrack->reasm_orig, clean_len))
|
||||
if (ReasmHasSpace(&ctrack->reasm_client, clean_len))
|
||||
{
|
||||
reasm_orig_feed(ctrack, IPPROTO_UDP, clean, clean_len);
|
||||
pclean = ctrack->reasm_orig.packet;
|
||||
clean_len = ctrack->reasm_orig.size_present;
|
||||
reasm_client_feed(ctrack, IPPROTO_UDP, clean, clean_len);
|
||||
pclean = ctrack->reasm_client.packet;
|
||||
clean_len = ctrack->reasm_client.size_present;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1592,13 +1662,13 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
|
||||
if (ctrack && !reasm_disable)
|
||||
{
|
||||
if (bIsHello && !bReqFull && ReasmIsEmpty(&ctrack->reasm_orig))
|
||||
if (bIsHello && !bReqFull && ReasmIsEmpty(&ctrack->reasm_client))
|
||||
{
|
||||
// preallocate max buffer to avoid reallocs that cause memory copy
|
||||
if (!reasm_orig_start(ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
|
||||
if (!reasm_client_start(ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_orig))
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_client))
|
||||
{
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
{
|
||||
@@ -1612,7 +1682,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
if (bReqFull)
|
||||
{
|
||||
replay_queue(&ctrack->delayed);
|
||||
reasm_orig_fin(ctrack);
|
||||
reasm_client_fin(ctrack);
|
||||
}
|
||||
return ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt);
|
||||
}
|
||||
@@ -1634,10 +1704,10 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
DLOG("QUIC initial contains CRYPTO with partial fragment coverage\n");
|
||||
if (ctrack && !reasm_disable)
|
||||
{
|
||||
if (ReasmIsEmpty(&ctrack->reasm_orig))
|
||||
if (ReasmIsEmpty(&ctrack->reasm_client))
|
||||
{
|
||||
// preallocate max buffer to avoid reallocs that cause memory copy
|
||||
if (!reasm_orig_start(ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
|
||||
if (!reasm_client_start(ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
@@ -1671,7 +1741,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
// received payload without host. it means we are out of the request retransmission phase. stop counter
|
||||
ctrack_stop_retrans_counter(ctrack);
|
||||
|
||||
reasm_orig_cancel(ctrack);
|
||||
reasm_client_cancel(ctrack);
|
||||
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
|
||||
@@ -1696,8 +1766,8 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
bool bDiscoveredL7;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
bDiscoveredL7 = !ctrack_replay->l7proto_discovered && l7proto != L7_UNKNOWN;
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && l7proto != L7_UNKNOWN))
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
@@ -1745,6 +1815,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
dp_changed(ctrack_replay);
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
@@ -1773,20 +1844,14 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
else
|
||||
{
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
if (ctrack_replay->hostname_ah_check)
|
||||
{
|
||||
// first request is not retrans
|
||||
if (!bDiscoveredHostname && !reasm_offset)
|
||||
process_retrans_fail(ctrack_replay, IPPROTO_UDP, (struct sockaddr*)&src);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
process_udp_fail(ctrack_replay, tpos, (struct sockaddr*)&src);
|
||||
} // len_payload
|
||||
|
||||
if (bCheckDone && !bCheckResult)
|
||||
{
|
||||
DLOG("not applying tampering because of negative hostlist check\n");
|
||||
@@ -1799,12 +1864,12 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2));
|
||||
DLOG("dpi desync src=%s dst=%s track_direction=%s fixed_direction=%s connection_proto=%s payload_type=%s\n", s1, s2, bReverse ? "in" : "out", bReverseFixed ? "in" : "out", l7proto_str(l7proto), l7payload_str(l7payload));
|
||||
}
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, pos, l7payload, l7proto, dis, sdip4, sdip6, sdport, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, NULL, 0, data_decrypt, len_decrypt);
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, tpos, l7payload, l7proto, dis, sdip4, sdip6, sdport, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, NULL, 0, data_decrypt, len_decrypt);
|
||||
|
||||
pass:
|
||||
return (!bReverse && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
||||
pass_reasm_cancel:
|
||||
reasm_orig_cancel(ctrack);
|
||||
reasm_client_cancel(ctrack);
|
||||
goto pass;
|
||||
}
|
||||
|
||||
@@ -1848,7 +1913,7 @@ static void packet_debug(bool replay, const struct dissect *dis)
|
||||
|
||||
static uint8_t dpi_desync_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset, uint32_t fwmark, const char *ifin, const char *ifout,
|
||||
const t_ctrack_position *pos,
|
||||
const t_ctrack_positions *tpos,
|
||||
const uint8_t *data_pkt, size_t len_pkt,
|
||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
{
|
||||
@@ -1864,7 +1929,7 @@ static uint8_t dpi_desync_packet_play(
|
||||
case IPPROTO_TCP:
|
||||
if (dis.tcp)
|
||||
{
|
||||
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, pos, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||
// we fix csum before pushing to replay queue
|
||||
if (!replay_piece_count) verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
@@ -1872,7 +1937,7 @@ static uint8_t dpi_desync_packet_play(
|
||||
case IPPROTO_UDP:
|
||||
if (dis.udp)
|
||||
{
|
||||
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, pos, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||
// we fix csum before pushing to replay queue
|
||||
if (!replay_piece_count) verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
@@ -1902,7 +1967,7 @@ static bool replay_queue(struct rawpacket_tailhead *q)
|
||||
{
|
||||
DLOG("REPLAYING delayed packet #%u offset %zu\n", i+1, offset);
|
||||
modlen = sizeof(mod);
|
||||
uint8_t verdict = dpi_desync_packet_play(i, count, offset, rp->fwmark_orig, rp->ifin, rp->ifout, rp->pos_present ? &rp->pos : NULL, rp->packet, rp->len, mod, &modlen);
|
||||
uint8_t verdict = dpi_desync_packet_play(i, count, offset, rp->fwmark_orig, rp->ifin, rp->ifout, rp->tpos_present ? &rp->tpos : NULL, rp->packet, rp->len, mod, &modlen);
|
||||
switch (verdict & VERDICT_MASK)
|
||||
{
|
||||
case VERDICT_MODIFY:
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
|
||||
#ifdef __linux__
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 0x40000000
|
||||
#else
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 512
|
||||
#else
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 0
|
||||
#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);
|
||||
|
||||
@@ -514,7 +514,7 @@ bool pf_is_empty(const port_filter *pf)
|
||||
|
||||
bool packet_pos_parse(const char *s, struct packet_pos *pos)
|
||||
{
|
||||
if (*s!='n' && *s!='d' && *s!='s' && *s!='b' && *s!='x' && *s!='a') return false;
|
||||
if (*s!='n' && *s!='d' && *s!='s' && *s!='p' && *s!='b' && *s!='x' && *s!='a') return false;
|
||||
pos->mode=*s;
|
||||
if (pos->mode=='x' || pos->mode=='a')
|
||||
{
|
||||
|
||||
193
nfq2/lua.c
193
nfq2/lua.c
@@ -690,6 +690,22 @@ static int luacall_clock_gettime(lua_State *L)
|
||||
}
|
||||
LUA_STACK_GUARD_RETURN(L,2)
|
||||
}
|
||||
|
||||
static t_lua_desync_context *lua_desync_ctx()
|
||||
{
|
||||
if (lua_isnil(params.L,1))
|
||||
luaL_error(params.L, "missing ctx");
|
||||
if (!lua_islightuserdata(params.L,1))
|
||||
luaL_error(params.L, "bad ctx - invalid data type");
|
||||
|
||||
t_lua_desync_context *ctx = lua_touserdata(params.L,1);
|
||||
// ensure it's really ctx. LUA could pass us any lightuserdata pointer
|
||||
if (ctx->magic!=MAGIC_CTX)
|
||||
luaL_error(params.L, "bad ctx - magic bytes invalid");
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static int luacall_instance_cutoff(lua_State *L)
|
||||
{
|
||||
// out : instance_name.profile_number[0]
|
||||
@@ -699,16 +715,12 @@ static int luacall_instance_cutoff(lua_State *L)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (lua_isnil(L,1))
|
||||
// this can happen in orchestrated function. they do not have their own ctx and they cant cutoff
|
||||
DLOG("instance cutoff not possible because missing ctx\n");
|
||||
else
|
||||
{
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "instance_cutoff expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
const t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
bool bIn,bOut;
|
||||
@@ -720,7 +732,6 @@ static int luacall_instance_cutoff(lua_State *L)
|
||||
}
|
||||
else
|
||||
bIn = bOut = true;
|
||||
|
||||
if (ctx->ctrack)
|
||||
{
|
||||
DLOG("instance cutoff for '%s' in=%u out=%u\n",ctx->instance,bIn,bOut);
|
||||
@@ -785,11 +796,7 @@ static int luacall_lua_cutoff(lua_State *L)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "lua_cutoff expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
bool bIn,bOut;
|
||||
@@ -821,11 +828,7 @@ static int luacall_execution_plan(lua_State *L)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "execution_plan expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
@@ -841,7 +844,7 @@ static int luacall_execution_plan(lua_State *L)
|
||||
range = ctx->incoming ? &func->range_in : &func->range_out;
|
||||
lua_pushinteger(params.L, n - ctx->func_n);
|
||||
lua_createtable(params.L, 0, 6);
|
||||
lua_pushf_args(&func->args, -1);
|
||||
lua_pushf_args(&func->args, -1, false);
|
||||
lua_pushf_str("func", func->func);
|
||||
lua_pushf_int("func_n", ctx->func_n);
|
||||
lua_pushf_str("func_instance", instance);
|
||||
@@ -862,11 +865,7 @@ static int luacall_execution_plan_cancel(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"execution_plan_cancel",1);
|
||||
|
||||
t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "execution_plan_cancel expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
DLOG("execution plan cancel from '%s'\n",ctx->instance);
|
||||
|
||||
@@ -881,11 +880,7 @@ static int luacall_raw_packet(lua_State *L)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "raw_packet expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
const t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
lua_pushlstring(L, (const char*)ctx->dis->data_pkt, ctx->dis->len_pkt);
|
||||
|
||||
@@ -929,6 +924,18 @@ void lua_pushi_lint(lua_Integer idx, int64_t v)
|
||||
lua_pushlint(params.L, v);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushf_number(const char *field, lua_Number v)
|
||||
{
|
||||
lua_pushstring(params.L, field);
|
||||
lua_pushnumber(params.L, v);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushi_number(lua_Integer idx, lua_Number v)
|
||||
{
|
||||
lua_pushinteger(params.L, idx);
|
||||
lua_pushnumber(params.L, v);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushf_bool(const char *field, bool b)
|
||||
{
|
||||
lua_pushstring(params.L, field);
|
||||
@@ -1239,13 +1246,15 @@ void lua_push_dissect(const struct dissect *dis)
|
||||
|
||||
if (dis)
|
||||
{
|
||||
lua_createtable(params.L, 0, 7);
|
||||
lua_createtable(params.L, 0, 9);
|
||||
lua_pushf_iphdr(dis->ip, dis->len_l3);
|
||||
lua_pushf_ip6hdr(dis->ip6, dis->len_l3);
|
||||
lua_pushf_tcphdr(dis->tcp, dis->len_l4);
|
||||
lua_pushf_udphdr(dis->udp, dis->len_l4);
|
||||
lua_pushf_int("l4proto",dis->proto);
|
||||
lua_pushf_int("transport_len",dis->transport_len);
|
||||
lua_pushf_int("l3_len",dis->len_l3);
|
||||
lua_pushf_int("l4_len",dis->len_l4);
|
||||
lua_pushf_raw("payload",dis->data_payload,dis->len_payload);
|
||||
}
|
||||
else
|
||||
@@ -1260,23 +1269,45 @@ void lua_pushf_dissect(const struct dissect *dis)
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
void lua_pushf_ctrack_pos(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
if (!pos) pos = &ctrack->pos;
|
||||
lua_pushf_lint("pcounter", pos->pcounter);
|
||||
lua_pushf_lint("pdcounter", pos->pdcounter);
|
||||
lua_pushf_lint("pbcounter", pos->pbcounter);
|
||||
if (ctrack->ipproto == IPPROTO_TCP)
|
||||
{
|
||||
lua_pushliteral(params.L, "tcp");
|
||||
lua_createtable(params.L, 0, 11);
|
||||
lua_pushf_lint("seq0", pos->seq0);
|
||||
lua_pushf_lint("seq", pos->seq_last);
|
||||
lua_pushf_lint("rseq", pos->seq_last - pos->seq0);
|
||||
lua_pushf_bool("rseq_over_2G", pos->rseq_over_2G);
|
||||
lua_pushf_int("pos", pos->pos - pos->seq0);
|
||||
lua_pushf_int("uppos", pos->uppos - pos->seq0);
|
||||
lua_pushf_int("uppos_prev", pos->uppos_prev - pos->seq0);
|
||||
lua_pushf_int("winsize", pos->winsize);
|
||||
lua_pushf_int("winsize_calc", pos->winsize_calc);
|
||||
lua_pushf_int("scale", pos->scale);
|
||||
lua_pushf_int("mss", pos->mss);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_positions *tpos, bool bIncoming)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
if (!tpos) tpos = &ctrack->pos;
|
||||
|
||||
lua_pushliteral(params.L, "track");
|
||||
if (ctrack)
|
||||
{
|
||||
lua_createtable(params.L, 0, 13 + (ctrack->ipproto == IPPROTO_TCP));
|
||||
lua_createtable(params.L, 0, 9);
|
||||
|
||||
lua_pushf_lint("pcounter_orig", pos->pcounter_orig);
|
||||
lua_pushf_lint("pdcounter_orig", pos->pdcounter_orig);
|
||||
lua_pushf_lint("pbcounter_orig", pos->pbcounter_orig);
|
||||
lua_pushf_lint("pcounter_reply", pos->pcounter_reply);
|
||||
lua_pushf_lint("pdcounter_reply", pos->pdcounter_reply);
|
||||
lua_pushf_lint("pbcounter_reply", pos->pbcounter_reply);
|
||||
if (ctrack->incoming_ttl)
|
||||
lua_pushf_int("incoming_ttl", ctrack->incoming_ttl);
|
||||
else
|
||||
@@ -1287,31 +1318,38 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
lua_pushf_reg("lua_state", ctrack->lua_state);
|
||||
lua_pushf_bool("lua_in_cutoff", ctrack->b_lua_in_cutoff);
|
||||
lua_pushf_bool("lua_out_cutoff", ctrack->b_lua_out_cutoff);
|
||||
lua_pushf_lint("t_start", (lua_Number)ctrack->t_start.tv_sec + ctrack->t_start.tv_nsec/1000000000.);
|
||||
|
||||
if (ctrack->ipproto == IPPROTO_TCP)
|
||||
{
|
||||
lua_pushliteral(params.L, "tcp");
|
||||
lua_createtable(params.L, 0, 18);
|
||||
lua_pushf_lint("seq0", pos->seq0);
|
||||
lua_pushf_lint("seq", pos->seq_last);
|
||||
lua_pushf_lint("ack0", pos->ack0);
|
||||
lua_pushf_lint("ack", pos->ack_last);
|
||||
lua_pushf_int("pos_orig", pos->pos_orig - pos->seq0);
|
||||
lua_pushf_int("uppos_orig", pos->uppos_orig - pos->seq0);
|
||||
lua_pushf_int("uppos_orig_prev", pos->uppos_orig_prev - pos->seq0);
|
||||
lua_pushf_int("winsize_orig", pos->winsize_orig);
|
||||
lua_pushf_int("winsize_orig_calc", pos->winsize_orig_calc);
|
||||
lua_pushf_int("scale_orig", pos->scale_orig);
|
||||
lua_pushf_int("mss_orig", pos->mss_orig);
|
||||
lua_pushf_int("pos_reply", pos->pos_reply - pos->ack0);
|
||||
lua_pushf_int("uppos_reply", pos->uppos_reply - pos->ack0);
|
||||
lua_pushf_int("uppos_reply_prev", pos->uppos_reply_prev - pos->ack0);
|
||||
lua_pushf_int("winsize_reply", pos->winsize_reply);
|
||||
lua_pushf_int("winsize_reply_calc", pos->winsize_reply_calc);
|
||||
lua_pushf_int("scale_reply", pos->scale_reply);
|
||||
lua_pushf_int("mss_reply", pos->mss_reply);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
lua_pushliteral(params.L, "pos");
|
||||
lua_createtable(params.L, 0, 5);
|
||||
|
||||
// orig, reply related to connection logical direction
|
||||
// for tcp orig is client (who connects), reply is server (who listens).
|
||||
// for orig is the first seen party, reply is another party
|
||||
lua_pushf_number("dt",
|
||||
(lua_Number)tpos->t_last.tv_sec - (lua_Number)ctrack->t_start.tv_sec +
|
||||
(tpos->t_last.tv_nsec - ctrack->t_start.tv_nsec)/1000000000.);
|
||||
|
||||
lua_pushliteral(params.L, "client");
|
||||
lua_newtable(params.L);
|
||||
lua_pushf_ctrack_pos(ctrack, &tpos->client);
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
lua_pushliteral(params.L, "server");
|
||||
lua_newtable(params.L);
|
||||
lua_pushf_ctrack_pos(ctrack, &tpos->server);
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
// direct and reverse are adjusted for server mode. in server mode orig and reply are exchanged.
|
||||
lua_pushliteral(params.L, "direct");
|
||||
lua_getfield(params.L, -2, (params.server ^ bIncoming) ? "server" : "client");
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
lua_pushliteral(params.L, "reverse");
|
||||
lua_getfield(params.L, -2, (params.server ^ bIncoming) ? "client" : "server");
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
else
|
||||
lua_pushnil(params.L);
|
||||
@@ -1320,7 +1358,7 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
|
||||
void lua_pushf_args(const struct str2_list_head *args, int idx_desync)
|
||||
void lua_pushf_args(const struct str2_list_head *args, int idx_desync, bool subst_prefix)
|
||||
{
|
||||
// var=val - pass val string
|
||||
// var=%val - subst 'val' blob
|
||||
@@ -1341,17 +1379,22 @@ void lua_pushf_args(const struct str2_list_head *args, int idx_desync)
|
||||
{
|
||||
var = arg->str1;
|
||||
val = arg->str2 ? arg->str2 : "";
|
||||
if (val[0]=='\\' && (val[1]=='%' || val[1]=='#'))
|
||||
// escape char
|
||||
lua_pushf_str(var, val+1);
|
||||
else if (val[0]=='%')
|
||||
lua_pushf_blob(idx_desync, var, val+1);
|
||||
else if (val[0]=='#')
|
||||
if (subst_prefix)
|
||||
{
|
||||
lua_push_blob(idx_desync, val+1);
|
||||
lua_Integer len = lua_rawlen(params.L, -1);
|
||||
lua_pop(params.L,1);
|
||||
lua_pushf_int(var, len);
|
||||
if (val[0]=='\\' && (val[1]=='%' || val[1]=='#'))
|
||||
// escape char
|
||||
lua_pushf_str(var, val+1);
|
||||
else if (val[0]=='%')
|
||||
lua_pushf_blob(idx_desync, var, val+1);
|
||||
else if (val[0]=='#')
|
||||
{
|
||||
lua_push_blob(idx_desync, val+1);
|
||||
lua_Integer len = lua_rawlen(params.L, -1);
|
||||
lua_pop(params.L,1);
|
||||
lua_pushf_int(var, len);
|
||||
}
|
||||
else
|
||||
lua_pushf_str(var, val);
|
||||
}
|
||||
else
|
||||
lua_pushf_str(var, val);
|
||||
@@ -2090,7 +2133,7 @@ static int luacall_csum_ip4_fix(lua_State *L)
|
||||
}
|
||||
static int luacall_csum_tcp_fix(lua_State *L)
|
||||
{
|
||||
// csum_ip4_fix(ip_header, tcp_header, payload) returns tcp_header
|
||||
// csum_tcp_fix(ip_header, tcp_header, payload) returns tcp_header
|
||||
lua_check_argc(L,"csum_tcp_fix",3);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
@@ -2131,7 +2174,7 @@ static int luacall_csum_tcp_fix(lua_State *L)
|
||||
}
|
||||
static int luacall_csum_udp_fix(lua_State *L)
|
||||
{
|
||||
// csum_ip4_fix(ip_header, tcp_header, payload) returns tcp_header
|
||||
// csum_udp_fix(ip_header, udp_header, payload) returns udp_header
|
||||
lua_check_argc(L,"csum_udp_fix",3);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
@@ -2955,9 +2998,11 @@ static void lua_init_const(void)
|
||||
{"IP_OFFMASK",IP_OFFMASK},
|
||||
{"IP_FLAGMASK",IP_RF|IP_DF|IP_MF},
|
||||
{"IPTOS_ECN_MASK",IPTOS_ECN_MASK},
|
||||
{"IPTOS_ECN_NOT_ECT",0},
|
||||
{"IPTOS_ECN_ECT1",IPTOS_ECN_ECT1},
|
||||
{"IPTOS_ECN_ECT0",IPTOS_ECN_ECT0},
|
||||
{"IPTOS_ECN_CE",IPTOS_ECN_CE},
|
||||
{"IPTOS_DSCP_MASK",0xF0},
|
||||
{"IP6F_MORE_FRAG",0x0001}, // in ip6.h it's defined depending of machine byte order
|
||||
|
||||
{"IPPROTO_IP",IPPROTO_IP},
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#endif
|
||||
|
||||
// pushing and not popping inside luacall cause memory leak
|
||||
// these macros ensure correct stack position or throw error if not
|
||||
#define LUA_STACK_GUARD_ENTER(L) int _lsg=lua_gettop(L);
|
||||
#define LUA_STACK_GUARD_LEAVE(L,N) if ((_lsg+N)!=lua_gettop(L)) luaL_error(L,"stack guard failure");
|
||||
#define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N;
|
||||
@@ -68,6 +69,8 @@ void lua_pushf_int(const char *field, lua_Integer v);
|
||||
void lua_pushi_int(lua_Integer idx, lua_Integer v);
|
||||
void lua_pushf_lint(const char *field, int64_t v);
|
||||
void lua_pushi_lint(lua_Integer idx, int64_t v);
|
||||
void lua_pushf_number(const char *field, lua_Number v);
|
||||
void lua_pushi_number(lua_Integer idx, lua_Number v);
|
||||
void lua_push_raw(const void *v, size_t l);
|
||||
void lua_pushf_raw(const char *field, const void *v, size_t l);
|
||||
void lua_pushi_raw(lua_Integer idx, const void *v, size_t l);
|
||||
@@ -86,8 +89,8 @@ void lua_pushf_iphdr(const struct ip *ip, size_t len);
|
||||
void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len);
|
||||
void lua_push_dissect(const struct dissect *dis);
|
||||
void lua_pushf_dissect(const struct dissect *dis);
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos);
|
||||
void lua_pushf_args(const struct str2_list_head *args, int idx_desync);
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_positions *tpos, bool bIncoming);
|
||||
void lua_pushf_args(const struct str2_list_head *args, int idx_desync, bool subst_prefix);
|
||||
void lua_pushf_pos(const char *name, const struct packet_pos *pos);
|
||||
void lua_pushf_range(const char *name, const struct packet_range *range);
|
||||
void lua_pushf_global(const char *field, const char *global);
|
||||
@@ -98,7 +101,9 @@ bool lua_reconstruct_tcphdr(int idx, struct tcphdr *tcp, size_t *len);
|
||||
bool lua_reconstruct_udphdr(int idx, struct udphdr *udp);
|
||||
bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next);
|
||||
|
||||
#define MAGIC_CTX 0xE73DC935
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
unsigned int func_n;
|
||||
const char *func, *instance;
|
||||
const struct desync_profile *dp;
|
||||
|
||||
44
nfq2/nfqws.c
44
nfq2/nfqws.c
@@ -630,6 +630,7 @@ static int win_main()
|
||||
{
|
||||
res=w_win32_error; goto ex;
|
||||
}
|
||||
|
||||
if (!win_sandbox())
|
||||
{
|
||||
res=w_win32_error;
|
||||
@@ -637,7 +638,6 @@ static int win_main()
|
||||
goto ex;
|
||||
}
|
||||
|
||||
|
||||
// init LUA only here because of possible sandbox. no LUA code with high privs
|
||||
if (!params.L && !lua_init())
|
||||
{
|
||||
@@ -1435,11 +1435,14 @@ static void exithelp(void)
|
||||
" --hostlist-auto-fail-time=<int>\t\t\t; all failed attemps must be within these seconds (default : %d)\n"
|
||||
" --hostlist-auto-retrans-threshold=<int>\t\t; how many request retransmissions cause attempt to fail (default : %d)\n"
|
||||
" --hostlist-auto-retrans-maxseq=<int>\t\t\t; count retransmissions only within this relative sequence (default : %u)\n"
|
||||
" --hostlist-auto-incoming-maxseq=<int>\t\t\t; treat tcp connection as successful if incoming relative sequence exceedes this threshold (default : %u)\n"
|
||||
" --hostlist-auto-udp-out=<int>\t\t\t\t; udp failure condition : sent at least `udp_out` packets (default : %u)\n"
|
||||
" --hostlist-auto-udp-in=<int>\t\t\t\t; udp failure condition : received not more than `udp_in` packets (default : %u)\n"
|
||||
" --hostlist-auto-debug=<logfile>\t\t\t; debug auto hostlist positives (global parameter)\n"
|
||||
"\nLUA PACKET PASS MODE:\n"
|
||||
" --payload=type[,type]\t\t\t\t\t; set payload types following LUA functions should process : %s\n"
|
||||
" --out-range=[(n|a|d|s)<int>](-|<)[(n|a|d|s)<int>]\t; set outgoing packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, b - byte count, x - never, a - always\n"
|
||||
" --in-range=[(n|a|d|s)<int>](-|<)[(n|a|d|s)<int>]\t; set incoming packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, b - byte count, x - never, a - always\n"
|
||||
" --out-range=[(n|a|d|s|p)<int>](-|<)[(n|a|d|s|p)<int>]\t; set outgoing packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, p - data position relative sequence, b - byte count, x - never, a - always\n"
|
||||
" --in-range=[(n|a|d|s|p)<int>](-|<)[(n|a|d|s|p)<int>]\t; set incoming packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, p - data position relative sequence, b - byte count, x - never, a - always\n"
|
||||
"\nLUA DESYNC ACTION:\n"
|
||||
" --lua-desync=<functon>[:param1=val1[:param2=val2]]\t; call LUA function when packet received\n",
|
||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||
@@ -1450,7 +1453,9 @@ static void exithelp(void)
|
||||
LUA_GC_INTERVAL,
|
||||
all_protos,
|
||||
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT,
|
||||
HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT, HOSTLIST_AUTO_RETRANS_MAXSEQ,
|
||||
HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
|
||||
HOSTLIST_AUTO_RETRANS_MAXSEQ, HOSTLIST_AUTO_INCOMING_MAXSEQ,
|
||||
HOSTLIST_AUTO_UDP_OUT, HOSTLIST_AUTO_UDP_IN,
|
||||
all_payloads
|
||||
);
|
||||
exit(1);
|
||||
@@ -1548,6 +1553,9 @@ enum opt_indices {
|
||||
IDX_HOSTLIST_AUTO_FAIL_TIME,
|
||||
IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD,
|
||||
IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ,
|
||||
IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ,
|
||||
IDX_HOSTLIST_AUTO_UDP_IN,
|
||||
IDX_HOSTLIST_AUTO_UDP_OUT,
|
||||
IDX_HOSTLIST_AUTO_DEBUG,
|
||||
IDX_NEW,
|
||||
IDX_SKIP,
|
||||
@@ -1633,6 +1641,9 @@ static const struct option long_options[] = {
|
||||
[IDX_HOSTLIST_AUTO_FAIL_TIME] = {"hostlist-auto-fail-time", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD] = {"hostlist-auto-retrans-threshold", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ] = {"hostlist-auto-retrans-maxseq", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ] = {"hostlist-auto-incoming-maxseq", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_UDP_IN] = {"hostlist-auto-udp-in", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_UDP_OUT] = {"hostlist-auto-udp-out", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_DEBUG] = {"hostlist-auto-debug", required_argument, 0, 0},
|
||||
[IDX_NEW] = {"new", no_argument, 0, 0},
|
||||
[IDX_SKIP] = {"skip", no_argument, 0, 0},
|
||||
@@ -1695,22 +1706,6 @@ static const struct option long_options[] = {
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/*
|
||||
t_reassemble t;
|
||||
ReasmInit(&t,16,-10);
|
||||
memset(t.packet,0,16);
|
||||
bool b;
|
||||
b=ReasmFeed(&t,-10,"0123456789",10);
|
||||
printf("b=%u size=%zu seq=%d s=%s\n",b,t.size_present,t.seq,t.packet);
|
||||
b=ReasmFeed(&t,0,"YOREK",5);
|
||||
printf("b=%u size=%zu seq=%d s=%s\n",b,t.size_present,t.seq,t.packet);
|
||||
b=ReasmFeed(&t,-12,"XOR",3);
|
||||
printf("b=%u size=%zu seq=%d s=%s\n",b,t.size_present,t.seq,t.packet);
|
||||
b=ReasmFeed(&t,3,"abc",3);
|
||||
printf("b=%u size=%zu seq=%d s=%s\n",b,t.size_present,t.seq,t.packet);
|
||||
return 0;
|
||||
*/
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
if (service_run(argc, argv))
|
||||
{
|
||||
@@ -2100,6 +2095,15 @@ int main(int argc, char **argv)
|
||||
case IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ:
|
||||
dp->hostlist_auto_retrans_maxseq = (uint32_t)atoi(optarg);
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ:
|
||||
dp->hostlist_auto_incoming_maxseq = (uint32_t)atoi(optarg);
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_UDP_OUT:
|
||||
dp->hostlist_auto_udp_out = atoi(optarg);
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_UDP_IN:
|
||||
dp->hostlist_auto_udp_in = atoi(optarg);
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_DEBUG:
|
||||
{
|
||||
FILE *F = fopen(optarg, "a+t");
|
||||
|
||||
@@ -12,4 +12,4 @@ extern bool bQuit;
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
// when something changes that can break LUA compatibility this version should be increased
|
||||
#define LUA_COMPAT_VER 2
|
||||
#define LUA_COMPAT_VER 3
|
||||
|
||||
@@ -26,7 +26,7 @@ void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
|
||||
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
|
||||
}
|
||||
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_position *pos)
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos)
|
||||
{
|
||||
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
|
||||
if (!rp) return NULL;
|
||||
@@ -54,13 +54,13 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
|
||||
rp->len_payload=len_payload;
|
||||
|
||||
// make a copy for replay
|
||||
if (pos)
|
||||
if (tpos)
|
||||
{
|
||||
rp->pos = *pos;
|
||||
rp->pos_present = true;
|
||||
rp->tpos = *tpos;
|
||||
rp->tpos_present = true;
|
||||
}
|
||||
else
|
||||
rp->pos_present = false;
|
||||
rp->tpos_present = false;
|
||||
|
||||
TAILQ_INSERT_TAIL(q, rp, next);
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ struct rawpacket
|
||||
uint32_t fwmark;
|
||||
size_t len, len_payload;
|
||||
uint8_t *packet;
|
||||
t_ctrack_position pos;
|
||||
bool pos_present;
|
||||
t_ctrack_positions tpos;
|
||||
bool tpos_present;
|
||||
TAILQ_ENTRY(rawpacket) next;
|
||||
};
|
||||
TAILQ_HEAD(rawpacket_tailhead, rawpacket);
|
||||
@@ -26,6 +26,6 @@ void rawpacket_queue_init(struct rawpacket_tailhead *q);
|
||||
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
|
||||
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
|
||||
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_position *pos);
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos);
|
||||
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
|
||||
void rawpacket_free(struct rawpacket *rp);
|
||||
|
||||
@@ -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);
|
||||
|
||||
static char log_buf[1024];
|
||||
static char log_buf[4096];
|
||||
static size_t log_buf_sz=0;
|
||||
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
|
||||
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 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_buf_sz = 0;
|
||||
@@ -343,6 +350,9 @@ void dp_init(struct desync_profile *dp)
|
||||
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
|
||||
dp->hostlist_auto_retrans_maxseq = HOSTLIST_AUTO_RETRANS_MAXSEQ;
|
||||
dp->hostlist_auto_incoming_maxseq = HOSTLIST_AUTO_INCOMING_MAXSEQ;
|
||||
dp->hostlist_auto_udp_out = HOSTLIST_AUTO_UDP_OUT;
|
||||
dp->hostlist_auto_udp_in = HOSTLIST_AUTO_UDP_IN;
|
||||
dp->filter_ipv4 = dp->filter_ipv6 = true;
|
||||
}
|
||||
static void dp_clear_dynamic(struct desync_profile *dp)
|
||||
|
||||
@@ -30,7 +30,10 @@
|
||||
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
||||
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
||||
#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_UDP_OUT 4
|
||||
#define HOSTLIST_AUTO_UDP_IN 1
|
||||
|
||||
#define IPCACHE_LIFETIME 7200
|
||||
|
||||
@@ -40,7 +43,7 @@
|
||||
#define BLOB_EXTRA_BYTES 128
|
||||
|
||||
// this MSS is used for ipv6 in windows and linux
|
||||
#define DEFAULT_MSS 1360
|
||||
#define DEFAULT_MSS 1220
|
||||
|
||||
#define RECONSTRUCT_MAX_SIZE 16384
|
||||
|
||||
@@ -79,7 +82,8 @@ struct desync_profile
|
||||
// pointer to autohostlist. NULL if no autohostlist for the profile.
|
||||
struct hostlist_file *hostlist_auto;
|
||||
int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold;
|
||||
uint32_t hostlist_auto_retrans_maxseq;
|
||||
int hostlist_auto_udp_in, hostlist_auto_udp_out;
|
||||
uint32_t hostlist_auto_retrans_maxseq, hostlist_auto_incoming_maxseq;
|
||||
|
||||
hostfail_pool *hostlist_auto_fail_counters;
|
||||
|
||||
|
||||
@@ -368,8 +368,10 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
|
||||
|
||||
// extract 2nd level domains
|
||||
const char *dhost, *drhost;
|
||||
if (!FindNLD((uint8_t*)host,strlen(host),2,(const uint8_t**)&dhost,NULL) || !FindNLD((uint8_t*)redirect_host,strlen(redirect_host),2,(const uint8_t**)&drhost,NULL))
|
||||
if (!FindNLD((uint8_t*)redirect_host,strlen(redirect_host),2,(const uint8_t**)&drhost,NULL))
|
||||
return false;
|
||||
if (!FindNLD((uint8_t*)host,strlen(host),2,(const uint8_t**)&dhost,NULL))
|
||||
return true; // no SLD redirects to SLD
|
||||
|
||||
// compare 2nd level domains
|
||||
return strcasecmp(dhost, drhost)!=0;
|
||||
|
||||
Reference in New Issue
Block a user