mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-13 22:03:09 +00:00
nfqws2,zapret-lib.lua,zapret-auto.lua: restructure conntrack record
This commit is contained in:
@@ -81,6 +81,7 @@ v0.6.1
|
|||||||
* zapret-lib: detect_payload_str - sample lua payload detector
|
* zapret-lib: detect_payload_str - sample lua payload detector
|
||||||
* blockcheck2: unterminated string fix
|
* blockcheck2: unterminated string fix
|
||||||
|
|
||||||
v0.6.2
|
v0.7
|
||||||
|
|
||||||
* nfqws2, zapret-lib : fix non-working % and # arg substitution under orchestrator
|
* 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
|
||||||
|
|||||||
@@ -5,3 +5,7 @@ v2
|
|||||||
* removed "stun_binding_req" specialized payload. replaced with common "stun" - any stun packets, not only binding request.
|
* 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.
|
every LUA relying on desync.l7payload should be revised.
|
||||||
nfqws2 --payload option and init.d custom scripts must be updated.
|
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
|
||||||
|
|||||||
@@ -141,11 +141,11 @@ function standard_failure_detector(desync, crec, arg)
|
|||||||
if desync.outgoing then
|
if desync.outgoing then
|
||||||
if udp_out then
|
if udp_out then
|
||||||
local udp_in = udp_in or 0
|
local udp_in = udp_in or 0
|
||||||
trigger = desync.track.pcounter_orig>=udp_out and desync.track.pcounter_reply<=udp_in
|
trigger = desync.track.pos.direct.pcounter>=udp_out and desync.track.pos.reverse.pcounter<=udp_in
|
||||||
if trigger then
|
if trigger then
|
||||||
crec.nocheck = true
|
crec.nocheck = true
|
||||||
if b_debug then
|
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: udp_out "..desync.track.pos.direct.pcounter..">="..udp_out.." udp_in "..desync.track.pos.reverse.pcounter.."<="..udp_in)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -37,16 +37,24 @@ function pktdebug(ctx, desync)
|
|||||||
end
|
end
|
||||||
-- basic desync function
|
-- basic desync function
|
||||||
-- prints function args
|
-- prints function args
|
||||||
function argdebug(ctx,desync)
|
function argdebug(ctx, desync)
|
||||||
var_debug(desync.arg)
|
var_debug(desync.arg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- basic desync function
|
-- basic desync function
|
||||||
-- prints conntrack positions to DLOG
|
-- prints conntrack positions to DLOG
|
||||||
function posdebug(ctx,desync)
|
function posdebug(ctx, desync)
|
||||||
local s="posdebug:"
|
if not desync.track then
|
||||||
for i,pos in pairs({'n','d','b','s'}) do
|
DLOG("posdebug: no track")
|
||||||
s=s.." "..pos..pos_get(desync,pos)
|
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
|
end
|
||||||
s=s.." payload "..#desync.dis.payload
|
s=s.." payload "..#desync.dis.payload
|
||||||
if desync.reasm_data then
|
if desync.reasm_data then
|
||||||
@@ -231,20 +239,31 @@ end
|
|||||||
-- pos is {mode,pos}
|
-- pos is {mode,pos}
|
||||||
-- range is {from={mode,pos}, to={mode,pos}, upper_cutoff}
|
-- range is {from={mode,pos}, to={mode,pos}, upper_cutoff}
|
||||||
-- upper_cutoff = true means non-inclusive upper boundary
|
-- upper_cutoff = true means non-inclusive upper boundary
|
||||||
function pos_get(desync, mode)
|
function pos_get_pos(track_pos, mode)
|
||||||
if desync.track then
|
if track_pos then
|
||||||
if mode=='n' 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
|
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
|
elseif mode=='b' then
|
||||||
return desync.outgoing and desync.track.pbcounter_orig or desync.track.pbcounter_reply
|
return track_pos.pbcounter
|
||||||
elseif mode=='s' and desync.track.tcp then
|
elseif track_pos.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)
|
if mode=='s' then
|
||||||
|
return track_pos.tcp.rseq
|
||||||
|
elseif mode=='p' then
|
||||||
|
return track_pos.tcp.pos
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return 0
|
return 0
|
||||||
end
|
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)
|
function pos_check_from(desync, range)
|
||||||
if range.from.mode == 'x' then return false end
|
if range.from.mode == 'x' then return false end
|
||||||
if range.from.mode ~= 'a' then
|
if range.from.mode ~= 'a' then
|
||||||
|
|||||||
134
nfq2/conntrack.c
134
nfq2/conntrack.c
@@ -37,7 +37,7 @@ void ConntrackClearHostname(t_ctrack *track)
|
|||||||
static void ConntrackClearTrack(t_ctrack *track)
|
static void ConntrackClearTrack(t_ctrack *track)
|
||||||
{
|
{
|
||||||
ConntrackClearHostname(track);
|
ConntrackClearHostname(track);
|
||||||
ReasmClear(&track->reasm_orig);
|
ReasmClear(&track->reasm_client);
|
||||||
rawpacket_queue_destroy(&track->delayed);
|
rawpacket_queue_destroy(&track->delayed);
|
||||||
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_state);
|
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_state);
|
||||||
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_instance_cutoff);
|
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_instance_cutoff);
|
||||||
@@ -102,8 +102,8 @@ static void ConntrackInitTrack(t_ctrack *t)
|
|||||||
{
|
{
|
||||||
memset(t, 0, sizeof(*t));
|
memset(t, 0, sizeof(*t));
|
||||||
t->l7proto = L7_UNKNOWN;
|
t->l7proto = L7_UNKNOWN;
|
||||||
t->pos.scale_orig = t->pos.scale_reply = SCALE_NONE;
|
t->pos.client.scale = t->pos.server.scale = SCALE_NONE;
|
||||||
time(&t->pos.t_start);
|
time(&t->t_start);
|
||||||
rawpacket_queue_init(&t->delayed);
|
rawpacket_queue_init(&t->delayed);
|
||||||
lua_newtable(params.L);
|
lua_newtable(params.L);
|
||||||
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
||||||
@@ -128,6 +128,36 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
|||||||
return ctnew;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
// 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)
|
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
|
||||||
{
|
{
|
||||||
@@ -136,16 +166,16 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
|
|
||||||
if (bReverse)
|
if (bReverse)
|
||||||
{
|
{
|
||||||
t->pos.pcounter_reply++;
|
t->pos.server.pcounter++;
|
||||||
t->pos.pdcounter_reply += !!len_payload;
|
t->pos.server.pdcounter += !!len_payload;
|
||||||
t->pos.pbcounter_reply += len_payload;
|
t->pos.server.pbcounter += len_payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t->pos.pcounter_orig++;
|
t->pos.client.pcounter++;
|
||||||
t->pos.pdcounter_orig += !!len_payload;
|
t->pos.client.pdcounter += !!len_payload;
|
||||||
t->pos.pbcounter_orig += len_payload;
|
t->pos.client.pbcounter += len_payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcphdr)
|
if (tcphdr)
|
||||||
@@ -153,16 +183,16 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
if (tcp_syn_segment(tcphdr))
|
if (tcp_syn_segment(tcphdr))
|
||||||
{
|
{
|
||||||
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
|
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))
|
else if (tcp_synack_segment(tcphdr))
|
||||||
{
|
{
|
||||||
// ignore SA dups
|
// ignore SA dups
|
||||||
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
|
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
|
ConntrackReInitTrack(t); // erase current entry
|
||||||
if (!t->pos.seq0) t->pos.seq0 = seq0;
|
if (!t->pos.client.seq0) t->pos.client.seq0 = seq0;
|
||||||
t->pos.ack0 = ntohl(tcphdr->th_seq);
|
t->pos.server.seq0 = ntohl(tcphdr->th_seq);
|
||||||
}
|
}
|
||||||
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
|
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
|
||||||
{
|
{
|
||||||
@@ -173,61 +203,23 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
if (t->pos.state == SYN)
|
if (t->pos.state == SYN)
|
||||||
{
|
{
|
||||||
t->pos.state = ESTABLISHED;
|
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));
|
ConntrackApplyPos(tcphdr, t, bReverse, len_payload);
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
if (bReverse)
|
if (bReverse)
|
||||||
{
|
{
|
||||||
t->pos.ack_last = t->pos.pos_reply;
|
t->pos.server.seq_last = t->pos.server.pos;
|
||||||
t->pos.pos_reply += len_payload;
|
t->pos.server.pos += len_payload;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t->pos.seq_last = t->pos.pos_orig;
|
t->pos.client.seq_last = t->pos.client.pos;
|
||||||
t->pos.pos_orig += len_payload;
|
t->pos.client.pos += len_payload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,24 +354,24 @@ void ConntrackPoolDump(const t_conntrack *p)
|
|||||||
HASH_ITER(hh, p->pool, t, tmp) {
|
HASH_ITER(hh, p->pool, t, tmp) {
|
||||||
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
|
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
|
||||||
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
|
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),
|
proto_name(t->conn.l4proto),
|
||||||
sa1, t->conn.sport, sa2, t->conn.dport,
|
sa1, t->conn.sport, sa2, t->conn.dport,
|
||||||
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
|
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.t_start, (unsigned long long)(t->track.pos.t_last - t->track.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.client.pdcounter, (unsigned long long)t->track.pos.client.pcounter, (unsigned long long)t->track.pos.client.pbcounter,
|
||||||
(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.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)
|
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",
|
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.seq0, t->track.pos.seq_last - t->track.pos.seq0, t->track.pos.pos_orig - t->track.pos.seq0,
|
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.ack0, t->track.pos.ack_last - t->track.pos.ack0, t->track.pos.pos_reply - t->track.pos.ack0,
|
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.mss_orig, t->track.pos.mss_reply,
|
t->track.pos.client.mss, t->track.pos.server.mss,
|
||||||
t->track.pos.winsize_orig, t->track.pos.scale_orig == SCALE_NONE ? -1 : t->track.pos.scale_orig,
|
t->track.pos.client.winsize, t->track.pos.client.scale == SCALE_NONE ? -1 : t->track.pos.client.scale,
|
||||||
t->track.pos.winsize_reply, t->track.pos.scale_reply == SCALE_NONE ? -1 : t->track.pos.scale_reply);
|
t->track.pos.server.winsize, t->track.pos.server.scale == SCALE_NONE ? -1 : t->track.pos.server.scale);
|
||||||
else
|
else
|
||||||
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
|
printf("rseq=%u client.pos=%u rack=%u server.pos=%u",
|
||||||
t->track.pos.seq_last, t->track.pos.pos_orig,
|
t->track.pos.client.seq_last, t->track.pos.client.pos,
|
||||||
t->track.pos.ack_last, t->track.pos.pos_reply);
|
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",
|
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));
|
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,8 +54,10 @@ typedef struct
|
|||||||
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
|
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
|
||||||
uint8_t ipproto;
|
uint8_t ipproto;
|
||||||
|
|
||||||
|
time_t t_start;
|
||||||
|
|
||||||
// this block of data can change between delayed (queued) packets. need to remeber this data for each packet for further replay
|
// 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
|
struct desync_profile *dp; // desync profile cache
|
||||||
bool dp_search_complete;
|
bool dp_search_complete;
|
||||||
@@ -78,7 +80,7 @@ typedef struct
|
|||||||
int lua_state; // registry index of associated LUA object
|
int lua_state; // registry index of associated LUA object
|
||||||
int lua_instance_cutoff; // registry index of per connection function instance cutoff table
|
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;
|
struct rawpacket_tailhead delayed;
|
||||||
} t_ctrack;
|
} t_ctrack;
|
||||||
|
|
||||||
|
|||||||
@@ -14,21 +14,26 @@ typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
time_t t_last, t_start;
|
uint64_t pcounter; // packet counter
|
||||||
|
uint64_t pdcounter; // data packet counter (with payload)
|
||||||
uint64_t pcounter_orig, pcounter_reply; // packet counter
|
uint64_t pbcounter; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||||
uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload)
|
uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||||
uint64_t pbcounter_orig, pbcounter_reply; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
uint32_t uppos; // max seen position. useful to detect retransmissions
|
||||||
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_prev; // previous max seen position. useful to detect retransmissions
|
||||||
uint32_t uppos_orig, uppos_reply; // 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 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
|
|
||||||
|
|
||||||
// tcp only state, not used in udp
|
// tcp only state, not used in udp
|
||||||
t_connstate state;
|
uint32_t seq0; // starting seq and ack
|
||||||
uint32_t seq0, ack0; // starting seq and ack
|
uint16_t winsize; // last seen window size
|
||||||
uint16_t winsize_orig, winsize_reply; // last seen window size
|
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
|
||||||
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
|
uint32_t winsize_calc; // calculated window size
|
||||||
uint32_t winsize_orig_calc, winsize_reply_calc; // calculated window size
|
uint16_t mss;
|
||||||
uint16_t mss_orig, mss_reply;
|
|
||||||
} t_ctrack_position;
|
} t_ctrack_position;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
time_t t_last;
|
||||||
|
t_connstate state;
|
||||||
|
t_ctrack_position client, server;
|
||||||
|
}
|
||||||
|
t_ctrack_positions;
|
||||||
|
|||||||
180
nfq2/desync.c
180
nfq2/desync.c
@@ -240,9 +240,9 @@ 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
|
// return true if retrans trigger fires
|
||||||
@@ -254,15 +254,15 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
|
|||||||
{
|
{
|
||||||
if (ctrack->retrans_detect_finalized)
|
if (ctrack->retrans_detect_finalized)
|
||||||
return false;
|
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;
|
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);
|
DLOG("retrans : tcp seq %u not within the req 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);
|
ctrack_stop_retrans_counter(ctrack);
|
||||||
auto_hostlist_reset_fail_counter(ctrack->dp, ctrack->hostname, client_ip_port, l7proto);
|
auto_hostlist_reset_fail_counter(ctrack->dp, ctrack->hostname, client_ip_port, l7proto);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!is_retransmission(ctrack))
|
if (!is_retransmission(&ctrack->pos.client))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ctrack->req_retrans_counter++;
|
ctrack->req_retrans_counter++;
|
||||||
@@ -353,23 +353,22 @@ static bool send_delayed(t_ctrack *ctrack)
|
|||||||
return true;
|
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
|
// this breaks const pointer to l4 header
|
||||||
if (dis->tcp)
|
if (dis->tcp)
|
||||||
verdict_tcp_csum_fix(VERDICT_PASS, (struct tcphdr *)dis->tcp, dis->transport_len, dis->ip, dis->ip6);
|
verdict_tcp_csum_fix(VERDICT_PASS, (struct tcphdr *)dis->tcp, dis->transport_len, dis->ip, dis->ip6);
|
||||||
else if (dis->udp)
|
else if (dis->udp)
|
||||||
verdict_udp_csum_fix(VERDICT_PASS, (struct udphdr *)dis->udp, dis->transport_len, dis->ip, dis->ip6);
|
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);
|
ReasmClear(reasm);
|
||||||
if (sz <= szMax)
|
if (sz <= szMax)
|
||||||
{
|
{
|
||||||
uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->pos.seq_last : 0;
|
|
||||||
if (ReasmInit(reasm, sz, seq))
|
if (ReasmInit(reasm, sz, seq))
|
||||||
{
|
{
|
||||||
ReasmFeed(reasm, seq, data_payload, len_payload);
|
ReasmFeed(reasm, seq, data_payload, len_payload);
|
||||||
@@ -383,15 +382,15 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, si
|
|||||||
DLOG("unexpected large payload for reassemble: size=%zu\n", sz);
|
DLOG("unexpected large payload for reassemble: size=%zu\n", sz);
|
||||||
return false;
|
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;
|
||||||
|
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))
|
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))
|
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);
|
DLOG("reassemble : feeding data payload size=%zu. now we have %zu/%zu\n", len_payload, reasm->size_present, reasm->size);
|
||||||
@@ -406,29 +405,30 @@ static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, con
|
|||||||
}
|
}
|
||||||
return false;
|
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 (ctrack)
|
||||||
{
|
{
|
||||||
if (!ReasmIsEmpty(&ctrack->reasm_orig))
|
if (!ReasmIsEmpty(&ctrack->reasm_client))
|
||||||
{
|
{
|
||||||
DLOG("%s", dlog_msg);
|
DLOG("%s", dlog_msg);
|
||||||
ReasmClear(&ctrack->reasm_orig);
|
ReasmClear(&ctrack->reasm_client);
|
||||||
}
|
}
|
||||||
send_delayed(ctrack);
|
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 +438,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
|
// if used in postnat chain, dropping initial packet will cause conntrack connection teardown
|
||||||
// so we need to workaround this.
|
// so we need to workaround this.
|
||||||
// SYN and SYN,ACK checks are for conntrack-less mode
|
// 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)
|
if (dis->len_pkt > *len_mod_pkt)
|
||||||
DLOG_ERR("linux postnat conntrack workaround cannot be applied\n");
|
DLOG_ERR("linux postnat conntrack workaround cannot be applied\n");
|
||||||
@@ -467,21 +467,22 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint64_t pos_get(const t_ctrack_position *pos, char mode, bool bReply)
|
static uint64_t pos_get(const t_ctrack_position *pos, char mode)
|
||||||
{
|
{
|
||||||
if (pos)
|
if (pos)
|
||||||
{
|
{
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case 'n': return bReply ? pos->pcounter_reply : pos->pcounter_orig;
|
case 'n': return pos->pcounter;
|
||||||
case 'd': return bReply ? pos->pdcounter_reply : pos->pdcounter_orig;
|
case 'd': return pos->pdcounter;
|
||||||
case 's': return bReply ? (pos->ack_last - pos->ack0) : (pos->seq_last - pos->seq0);
|
case 's': return pos->seq_last - pos->seq0;
|
||||||
case 'b': return bReply ? pos->pbcounter_reply : pos->pbcounter_orig;
|
case 'p': return pos->pos - pos->seq0;
|
||||||
|
case 'b': return pos->pbcounter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
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;
|
uint64_t ps;
|
||||||
if (range->from.mode == 'x') return false;
|
if (range->from.mode == 'x') return false;
|
||||||
@@ -489,7 +490,7 @@ static bool check_pos_from(const t_ctrack_position *pos, bool bReply, const stru
|
|||||||
{
|
{
|
||||||
if (pos)
|
if (pos)
|
||||||
{
|
{
|
||||||
ps = pos_get(pos, range->from.mode, bReply);
|
ps = pos_get(pos, range->from.mode);
|
||||||
return ps >= range->from.pos;
|
return ps >= range->from.pos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -497,7 +498,7 @@ static bool check_pos_from(const t_ctrack_position *pos, bool bReply, const stru
|
|||||||
}
|
}
|
||||||
return true;
|
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;
|
uint64_t ps;
|
||||||
if (range->to.mode == 'x') return false;
|
if (range->to.mode == 'x') return false;
|
||||||
@@ -505,7 +506,7 @@ static bool check_pos_to(const t_ctrack_position *pos, bool bReply, const struct
|
|||||||
{
|
{
|
||||||
if (pos)
|
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);
|
return (ps < range->to.pos) || !range->upper_cutoff && (ps == range->to.pos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -513,14 +514,14 @@ static bool check_pos_to(const t_ctrack_position *pos, bool bReply, const struct
|
|||||||
}
|
}
|
||||||
return true;
|
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);
|
bool bto = check_pos_to(pos, range);
|
||||||
return pos ? !bto : (!bto || !check_pos_from(pos, bReply, 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 +655,7 @@ static uint8_t desync(
|
|||||||
const char *ifout,
|
const char *ifout,
|
||||||
bool bIncoming,
|
bool bIncoming,
|
||||||
t_ctrack *ctrack,
|
t_ctrack *ctrack,
|
||||||
const t_ctrack_position *pos,
|
const t_ctrack_positions *tpos,
|
||||||
t_l7payload l7payload,
|
t_l7payload l7payload,
|
||||||
t_l7proto l7proto,
|
t_l7proto l7proto,
|
||||||
const struct dissect *dis,
|
const struct dissect *dis,
|
||||||
@@ -672,6 +673,7 @@ static uint8_t desync(
|
|||||||
struct packet_range *range;
|
struct packet_range *range;
|
||||||
size_t l;
|
size_t l;
|
||||||
char instance[256];
|
char instance[256];
|
||||||
|
const t_ctrack_position *pos, *rpos;
|
||||||
|
|
||||||
if (ctrack)
|
if (ctrack)
|
||||||
{
|
{
|
||||||
@@ -686,8 +688,10 @@ static uint8_t desync(
|
|||||||
DLOG("lua out cutoff\n");
|
DLOG("lua out cutoff\n");
|
||||||
return verdict;
|
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)
|
LUA_STACK_GUARD_ENTER(params.L)
|
||||||
|
|
||||||
@@ -709,12 +713,12 @@ static uint8_t desync(
|
|||||||
{
|
{
|
||||||
if (lua_instance_cutoff_check(&ctx, bIncoming))
|
if (lua_instance_cutoff_check(&ctx, bIncoming))
|
||||||
DLOG("* lua '%s' : voluntary cutoff\n", instance);
|
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 is beyond range %c%u%c%c%u (ctrack %s)\n",
|
||||||
instance, sDirection,
|
instance, sDirection,
|
||||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
range->from.mode, pos_get(pos, range->from.mode),
|
||||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
range->to.mode, pos_get(pos, range->to.mode),
|
||||||
range->from.mode, range->from.pos,
|
range->from.mode, range->from.pos,
|
||||||
range->upper_cutoff ? '<' : '-',
|
range->upper_cutoff ? '<' : '-',
|
||||||
range->to.mode, range->to.pos,
|
range->to.mode, range->to.pos,
|
||||||
@@ -737,7 +741,7 @@ static uint8_t desync(
|
|||||||
// create arg table that persists across multiple desync function calls
|
// create arg table that persists across multiple desync function calls
|
||||||
lua_newtable(params.L);
|
lua_newtable(params.L);
|
||||||
lua_pushf_dissect(dis);
|
lua_pushf_dissect(dis);
|
||||||
lua_pushf_ctrack(ctrack, pos);
|
lua_pushf_ctrack(ctrack, tpos, bIncoming);
|
||||||
lua_pushf_int("profile_n", dp->n);
|
lua_pushf_int("profile_n", dp->n);
|
||||||
if (dp->name) lua_pushf_str("profile_name", dp->name);
|
if (dp->name) lua_pushf_str("profile_name", dp->name);
|
||||||
if (dp->n_tpl) lua_pushf_int("template_n", dp->n_tpl);
|
if (dp->n_tpl) lua_pushf_int("template_n", dp->n_tpl);
|
||||||
@@ -769,8 +773,8 @@ static uint8_t desync(
|
|||||||
if (dis->tcp)
|
if (dis->tcp)
|
||||||
{
|
{
|
||||||
// recommended mss value for generated packets
|
// recommended mss value for generated packets
|
||||||
if (pos && pos->mss_orig)
|
if (rpos && rpos->mss)
|
||||||
lua_pushf_int("tcp_mss", pos->mss_orig);
|
lua_pushf_int("tcp_mss", rpos->mss);
|
||||||
else
|
else
|
||||||
lua_pushf_global("tcp_mss", "DEFAULT_MSS");
|
lua_pushf_global("tcp_mss", "DEFAULT_MSS");
|
||||||
}
|
}
|
||||||
@@ -786,12 +790,12 @@ static uint8_t desync(
|
|||||||
if (!lua_instance_cutoff_check(&ctx, bIncoming))
|
if (!lua_instance_cutoff_check(&ctx, bIncoming))
|
||||||
{
|
{
|
||||||
range = bIncoming ? &func->range_in : &func->range_out;
|
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",
|
DLOG("* lua '%s' : %s pos %c%llu %c%llu in range %c%u%c%c%u\n",
|
||||||
instance, sDirection,
|
instance, sDirection,
|
||||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
range->from.mode, pos_get(pos, range->from.mode),
|
||||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
range->to.mode, pos_get(pos, range->to.mode),
|
||||||
range->from.mode, range->from.pos,
|
range->from.mode, range->from.pos,
|
||||||
range->upper_cutoff ? '<' : '-',
|
range->upper_cutoff ? '<' : '-',
|
||||||
range->to.mode, range->to.pos);
|
range->to.mode, range->to.pos);
|
||||||
@@ -836,8 +840,8 @@ static uint8_t desync(
|
|||||||
else
|
else
|
||||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu out of range %c%u%c%c%u\n",
|
DLOG("* lua '%s' : %s pos %c%llu %c%llu out of range %c%u%c%c%u\n",
|
||||||
instance, sDirection,
|
instance, sDirection,
|
||||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
range->from.mode, pos_get(pos, range->from.mode),
|
||||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
range->to.mode, pos_get(pos, range->to.mode),
|
||||||
range->from.mode, range->from.pos,
|
range->from.mode, range->from.pos,
|
||||||
range->upper_cutoff ? '<' : '-',
|
range->upper_cutoff ? '<' : '-',
|
||||||
range->to.mode, range->to.pos);
|
range->to.mode, range->to.pos);
|
||||||
@@ -936,7 +940,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
|||||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||||
uint32_t fwmark,
|
uint32_t fwmark,
|
||||||
const char *ifin, const char *ifout,
|
const char *ifin, const char *ifout,
|
||||||
const t_ctrack_position *pos,
|
const t_ctrack_positions *tpos,
|
||||||
const struct dissect *dis,
|
const struct dissect *dis,
|
||||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||||
{
|
{
|
||||||
@@ -1093,7 +1097,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
|||||||
// process reply packets for auto hostlist mode
|
// process reply packets for auto hostlist mode
|
||||||
// by looking at RSTs or HTTP replies we decide whether original request looks like DPI blocked
|
// 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
|
// 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 && ctrack->hostname_ah_check && (ctrack->pos.server.seq_last - ctrack->pos.server.seq0) == 1)
|
||||||
{
|
{
|
||||||
bool bFail = false;
|
bool bFail = false;
|
||||||
|
|
||||||
@@ -1149,13 +1153,13 @@ static uint8_t dpi_desync_tcp_packet_play(
|
|||||||
|
|
||||||
if (replay_piece_count)
|
if (replay_piece_count)
|
||||||
{
|
{
|
||||||
rdata_payload = ctrack_replay->reasm_orig.packet;
|
rdata_payload = ctrack_replay->reasm_client.packet;
|
||||||
rlen_payload = ctrack_replay->reasm_orig.size_present;
|
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;
|
rdata_payload = ctrack->reasm_client.packet;
|
||||||
rlen_payload = ctrack->reasm_orig.size_present;
|
rlen_payload = ctrack->reasm_client.size_present;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_retrans_fail(ctrack, IPPROTO_TCP, (struct sockaddr*)&src);
|
process_retrans_fail(ctrack, IPPROTO_TCP, (struct sockaddr*)&src);
|
||||||
@@ -1170,7 +1174,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we do not reassemble http
|
// we do not reassemble http
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_client_cancel(ctrack);
|
||||||
|
|
||||||
bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host));
|
bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host));
|
||||||
if (!bHaveHost)
|
if (!bHaveHost)
|
||||||
@@ -1196,14 +1200,14 @@ static uint8_t dpi_desync_tcp_packet_play(
|
|||||||
if (ctrack && !(params.reasm_payload_disable && l7_payload_match(l7payload, params.reasm_payload_disable)))
|
if (ctrack && !(params.reasm_payload_disable && l7_payload_match(l7payload, params.reasm_payload_disable)))
|
||||||
{
|
{
|
||||||
// do not reasm retransmissions
|
// 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 ?)
|
// 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;
|
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))
|
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||||
{
|
{
|
||||||
@@ -1214,16 +1218,16 @@ static uint8_t dpi_desync_tcp_packet_play(
|
|||||||
DLOG_ERR("rawpacket_queue failed !\n");
|
DLOG_ERR("rawpacket_queue failed !\n");
|
||||||
goto pass_reasm_cancel;
|
goto pass_reasm_cancel;
|
||||||
}
|
}
|
||||||
if (ReasmIsFull(&ctrack->reasm_orig))
|
if (ReasmIsFull(&ctrack->reasm_client))
|
||||||
{
|
{
|
||||||
replay_queue(&ctrack->delayed);
|
replay_queue(&ctrack->delayed);
|
||||||
reasm_orig_fin(ctrack);
|
reasm_client_fin(ctrack);
|
||||||
}
|
}
|
||||||
return VERDICT_DROP;
|
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");
|
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.
|
// mtproto detection requires aes. react only on the first tcp data packet. do not detect if ctrack unavailable.
|
||||||
@@ -1343,19 +1347,19 @@ static uint8_t dpi_desync_tcp_packet_play(
|
|||||||
ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2));
|
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));
|
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:
|
pass:
|
||||||
return (!bReverseFixed && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
return (!bReverseFixed && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
||||||
pass_reasm_cancel:
|
pass_reasm_cancel:
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_client_cancel(ctrack);
|
||||||
goto pass;
|
goto pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return : true - should continue, false - should stop with verdict
|
// return : true - should continue, false - should stop with verdict
|
||||||
static void quic_reasm_cancel(t_ctrack *ctrack, const char *reason)
|
static void quic_reasm_cancel(t_ctrack *ctrack, const char *reason)
|
||||||
{
|
{
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_client_cancel(ctrack);
|
||||||
DLOG("%s\n", reason);
|
DLOG("%s\n", reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1364,7 +1368,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
|||||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||||
uint32_t fwmark,
|
uint32_t fwmark,
|
||||||
const char *ifin, const char *ifout,
|
const char *ifin, const char *ifout,
|
||||||
const t_ctrack_position *pos,
|
const t_ctrack_positions *tpos,
|
||||||
const struct dissect *dis,
|
const struct dissect *dis,
|
||||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||||
{
|
{
|
||||||
@@ -1550,8 +1554,8 @@ static uint8_t dpi_desync_udp_packet_play(
|
|||||||
|
|
||||||
if (replay_piece_count)
|
if (replay_piece_count)
|
||||||
{
|
{
|
||||||
clean_len = ctrack_replay->reasm_orig.size_present;
|
clean_len = ctrack_replay->reasm_client.size_present;
|
||||||
pclean = ctrack_replay->reasm_orig.packet;
|
pclean = ctrack_replay->reasm_client.packet;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1561,13 +1565,13 @@ static uint8_t dpi_desync_udp_packet_play(
|
|||||||
if (pclean)
|
if (pclean)
|
||||||
{
|
{
|
||||||
bool reasm_disable = params.reasm_payload_disable && l7_payload_match(l7payload, params.reasm_payload_disable);
|
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);
|
reasm_client_feed(ctrack, IPPROTO_UDP, clean, clean_len);
|
||||||
pclean = ctrack->reasm_orig.packet;
|
pclean = ctrack->reasm_client.packet;
|
||||||
clean_len = ctrack->reasm_orig.size_present;
|
clean_len = ctrack->reasm_client.size_present;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1592,13 +1596,13 @@ static uint8_t dpi_desync_udp_packet_play(
|
|||||||
|
|
||||||
if (ctrack && !reasm_disable)
|
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
|
// 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;
|
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))
|
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||||
{
|
{
|
||||||
@@ -1612,7 +1616,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
|||||||
if (bReqFull)
|
if (bReqFull)
|
||||||
{
|
{
|
||||||
replay_queue(&ctrack->delayed);
|
replay_queue(&ctrack->delayed);
|
||||||
reasm_orig_fin(ctrack);
|
reasm_client_fin(ctrack);
|
||||||
}
|
}
|
||||||
return ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt);
|
return ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt);
|
||||||
}
|
}
|
||||||
@@ -1634,10 +1638,10 @@ static uint8_t dpi_desync_udp_packet_play(
|
|||||||
DLOG("QUIC initial contains CRYPTO with partial fragment coverage\n");
|
DLOG("QUIC initial contains CRYPTO with partial fragment coverage\n");
|
||||||
if (ctrack && !reasm_disable)
|
if (ctrack && !reasm_disable)
|
||||||
{
|
{
|
||||||
if (ReasmIsEmpty(&ctrack->reasm_orig))
|
if (ReasmIsEmpty(&ctrack->reasm_client))
|
||||||
{
|
{
|
||||||
// preallocate max buffer to avoid reallocs that cause memory copy
|
// 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;
|
goto pass_reasm_cancel;
|
||||||
}
|
}
|
||||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||||
@@ -1671,7 +1675,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
|
// received payload without host. it means we are out of the request retransmission phase. stop counter
|
||||||
ctrack_stop_retrans_counter(ctrack);
|
ctrack_stop_retrans_counter(ctrack);
|
||||||
|
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_client_cancel(ctrack);
|
||||||
|
|
||||||
t_protocol_probe testers[] = {
|
t_protocol_probe testers[] = {
|
||||||
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
|
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
|
||||||
@@ -1799,12 +1803,12 @@ static uint8_t dpi_desync_udp_packet_play(
|
|||||||
ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2));
|
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));
|
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:
|
pass:
|
||||||
return (!bReverse && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
return (!bReverse && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
||||||
pass_reasm_cancel:
|
pass_reasm_cancel:
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_client_cancel(ctrack);
|
||||||
goto pass;
|
goto pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1848,7 +1852,7 @@ static void packet_debug(bool replay, const struct dissect *dis)
|
|||||||
|
|
||||||
static uint8_t dpi_desync_packet_play(
|
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,
|
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,
|
const uint8_t *data_pkt, size_t len_pkt,
|
||||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||||
{
|
{
|
||||||
@@ -1864,7 +1868,7 @@ static uint8_t dpi_desync_packet_play(
|
|||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
if (dis.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
|
// 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);
|
if (!replay_piece_count) verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
||||||
}
|
}
|
||||||
@@ -1872,7 +1876,7 @@ static uint8_t dpi_desync_packet_play(
|
|||||||
case IPPROTO_UDP:
|
case IPPROTO_UDP:
|
||||||
if (dis.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
|
// 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);
|
if (!replay_piece_count) verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
||||||
}
|
}
|
||||||
@@ -1902,7 +1906,7 @@ static bool replay_queue(struct rawpacket_tailhead *q)
|
|||||||
{
|
{
|
||||||
DLOG("REPLAYING delayed packet #%u offset %zu\n", i+1, offset);
|
DLOG("REPLAYING delayed packet #%u offset %zu\n", i+1, offset);
|
||||||
modlen = sizeof(mod);
|
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)
|
switch (verdict & VERDICT_MASK)
|
||||||
{
|
{
|
||||||
case VERDICT_MODIFY:
|
case VERDICT_MODIFY:
|
||||||
|
|||||||
@@ -514,7 +514,7 @@ bool pf_is_empty(const port_filter *pf)
|
|||||||
|
|
||||||
bool packet_pos_parse(const char *s, struct packet_pos *pos)
|
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;
|
pos->mode=*s;
|
||||||
if (pos->mode=='x' || pos->mode=='a')
|
if (pos->mode=='x' || pos->mode=='a')
|
||||||
{
|
{
|
||||||
|
|||||||
92
nfq2/lua.c
92
nfq2/lua.c
@@ -1260,23 +1260,44 @@ void lua_pushf_dissect(const struct dissect *dis)
|
|||||||
lua_rawset(params.L,-3);
|
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)
|
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, 10);
|
||||||
|
lua_pushf_lint("seq0", pos->seq0);
|
||||||
|
lua_pushf_lint("seq", pos->seq_last);
|
||||||
|
lua_pushf_lint("rseq", pos->seq_last - pos->seq0);
|
||||||
|
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");
|
lua_pushliteral(params.L, "track");
|
||||||
if (ctrack)
|
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)
|
if (ctrack->incoming_ttl)
|
||||||
lua_pushf_int("incoming_ttl", ctrack->incoming_ttl);
|
lua_pushf_int("incoming_ttl", ctrack->incoming_ttl);
|
||||||
else
|
else
|
||||||
@@ -1287,31 +1308,36 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
|||||||
lua_pushf_reg("lua_state", ctrack->lua_state);
|
lua_pushf_reg("lua_state", ctrack->lua_state);
|
||||||
lua_pushf_bool("lua_in_cutoff", ctrack->b_lua_in_cutoff);
|
lua_pushf_bool("lua_in_cutoff", ctrack->b_lua_in_cutoff);
|
||||||
lua_pushf_bool("lua_out_cutoff", ctrack->b_lua_out_cutoff);
|
lua_pushf_bool("lua_out_cutoff", ctrack->b_lua_out_cutoff);
|
||||||
|
lua_pushf_lint("t_start", ctrack->t_start);
|
||||||
|
|
||||||
if (ctrack->ipproto == IPPROTO_TCP)
|
lua_pushliteral(params.L, "pos");
|
||||||
{
|
lua_createtable(params.L, 0, 5);
|
||||||
lua_pushliteral(params.L, "tcp");
|
|
||||||
lua_createtable(params.L, 0, 18);
|
// orig, reply related to connection logical direction
|
||||||
lua_pushf_lint("seq0", pos->seq0);
|
// for tcp orig is client (who connects), reply is server (who listens).
|
||||||
lua_pushf_lint("seq", pos->seq_last);
|
// for orig is the first seen party, reply is another party
|
||||||
lua_pushf_lint("ack0", pos->ack0);
|
lua_pushf_lint("dt", tpos->t_last - ctrack->t_start);
|
||||||
lua_pushf_lint("ack", pos->ack_last);
|
|
||||||
lua_pushf_int("pos_orig", pos->pos_orig - pos->seq0);
|
lua_pushliteral(params.L, "client");
|
||||||
lua_pushf_int("uppos_orig", pos->uppos_orig - pos->seq0);
|
lua_newtable(params.L);
|
||||||
lua_pushf_int("uppos_orig_prev", pos->uppos_orig_prev - pos->seq0);
|
lua_pushf_ctrack_pos(ctrack, &tpos->client);
|
||||||
lua_pushf_int("winsize_orig", pos->winsize_orig);
|
lua_rawset(params.L,-3);
|
||||||
lua_pushf_int("winsize_orig_calc", pos->winsize_orig_calc);
|
|
||||||
lua_pushf_int("scale_orig", pos->scale_orig);
|
lua_pushliteral(params.L, "server");
|
||||||
lua_pushf_int("mss_orig", pos->mss_orig);
|
lua_newtable(params.L);
|
||||||
lua_pushf_int("pos_reply", pos->pos_reply - pos->ack0);
|
lua_pushf_ctrack_pos(ctrack, &tpos->server);
|
||||||
lua_pushf_int("uppos_reply", pos->uppos_reply - pos->ack0);
|
lua_rawset(params.L,-3);
|
||||||
lua_pushf_int("uppos_reply_prev", pos->uppos_reply_prev - pos->ack0);
|
|
||||||
lua_pushf_int("winsize_reply", pos->winsize_reply);
|
// direct and reverse are adjusted for server mode. in server mode orig and reply are exchanged.
|
||||||
lua_pushf_int("winsize_reply_calc", pos->winsize_reply_calc);
|
lua_pushliteral(params.L, "direct");
|
||||||
lua_pushf_int("scale_reply", pos->scale_reply);
|
lua_getfield(params.L, -2, (params.server ^ bIncoming) ? "server" : "client");
|
||||||
lua_pushf_int("mss_reply", pos->mss_reply);
|
lua_rawset(params.L,-3);
|
||||||
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
|
else
|
||||||
lua_pushnil(params.L);
|
lua_pushnil(params.L);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// pushing and not popping inside luacall cause memory leak
|
// 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_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_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;
|
#define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N;
|
||||||
@@ -86,8 +87,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_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len);
|
||||||
void lua_push_dissect(const struct dissect *dis);
|
void lua_push_dissect(const struct dissect *dis);
|
||||||
void lua_pushf_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_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);
|
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_pos(const char *name, const struct packet_pos *pos);
|
||||||
void lua_pushf_range(const char *name, const struct packet_range *range);
|
void lua_pushf_range(const char *name, const struct packet_range *range);
|
||||||
void lua_pushf_global(const char *field, const char *global);
|
void lua_pushf_global(const char *field, const char *global);
|
||||||
|
|||||||
@@ -1438,8 +1438,8 @@ static void exithelp(void)
|
|||||||
" --hostlist-auto-debug=<logfile>\t\t\t; debug auto hostlist positives (global parameter)\n"
|
" --hostlist-auto-debug=<logfile>\t\t\t; debug auto hostlist positives (global parameter)\n"
|
||||||
"\nLUA PACKET PASS MODE:\n"
|
"\nLUA PACKET PASS MODE:\n"
|
||||||
" --payload=type[,type]\t\t\t\t\t; set payload types following LUA functions should process : %s\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"
|
" --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)<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"
|
" --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"
|
"\nLUA DESYNC ACTION:\n"
|
||||||
" --lua-desync=<functon>[:param1=val1[:param2=val2]]\t; call LUA function when packet received\n",
|
" --lua-desync=<functon>[:param1=val1[:param2=val2]]\t; call LUA function when packet received\n",
|
||||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ extern bool bQuit;
|
|||||||
int main(int argc, char *argv[]);
|
int main(int argc, char *argv[]);
|
||||||
|
|
||||||
// when something changes that can break LUA compatibility this version should be increased
|
// 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);
|
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));
|
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
|
||||||
if (!rp) return NULL;
|
if (!rp) return NULL;
|
||||||
@@ -54,13 +54,13 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
|
|||||||
rp->len_payload=len_payload;
|
rp->len_payload=len_payload;
|
||||||
|
|
||||||
// make a copy for replay
|
// make a copy for replay
|
||||||
if (pos)
|
if (tpos)
|
||||||
{
|
{
|
||||||
rp->pos = *pos;
|
rp->tpos = *tpos;
|
||||||
rp->pos_present = true;
|
rp->tpos_present = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rp->pos_present = false;
|
rp->tpos_present = false;
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(q, rp, next);
|
TAILQ_INSERT_TAIL(q, rp, next);
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ struct rawpacket
|
|||||||
uint32_t fwmark;
|
uint32_t fwmark;
|
||||||
size_t len, len_payload;
|
size_t len, len_payload;
|
||||||
uint8_t *packet;
|
uint8_t *packet;
|
||||||
t_ctrack_position pos;
|
t_ctrack_positions tpos;
|
||||||
bool pos_present;
|
bool tpos_present;
|
||||||
TAILQ_ENTRY(rawpacket) next;
|
TAILQ_ENTRY(rawpacket) next;
|
||||||
};
|
};
|
||||||
TAILQ_HEAD(rawpacket_tailhead, rawpacket);
|
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);
|
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
|
||||||
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
|
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
|
||||||
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
|
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
|
||||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_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);
|
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
|
||||||
void rawpacket_free(struct rawpacket *rp);
|
void rawpacket_free(struct rawpacket *rp);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
#define BLOB_EXTRA_BYTES 128
|
#define BLOB_EXTRA_BYTES 128
|
||||||
|
|
||||||
// this MSS is used for ipv6 in windows and linux
|
// this MSS is used for ipv6 in windows and linux
|
||||||
#define DEFAULT_MSS 1360
|
#define DEFAULT_MSS 1220
|
||||||
|
|
||||||
#define RECONSTRUCT_MAX_SIZE 16384
|
#define RECONSTRUCT_MAX_SIZE 16384
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user