From 8cd2904614cdb181e796dd20e409a9b5a0a33402 Mon Sep 17 00:00:00 2001 From: bol-van Date: Thu, 11 Dec 2025 00:20:03 +0300 Subject: [PATCH] nfqws2: push desync.track.pos.dt as float with nsec accuracy --- docs/changes.txt | 1 + nfq2/conntrack.c | 22 +++++++++++++--------- nfq2/conntrack.h | 2 +- nfq2/conntrack_base.h | 2 +- nfq2/lua.c | 18 ++++++++++++++++-- nfq2/lua.h | 2 ++ 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 86162da..75998bd 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -87,3 +87,4 @@ v0.7 * 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 diff --git a/nfq2/conntrack.c b/nfq2/conntrack.c index 363c07f..737dad1 100644 --- a/nfq2/conntrack.c +++ b/nfq2/conntrack.c @@ -103,7 +103,6 @@ static void ConntrackInitTrack(t_ctrack *t) memset(t, 0, sizeof(*t)); t->l7proto = L7_UNKNOWN; t->pos.client.scale = t->pos.server.scale = SCALE_NONE; - time(&t->t_start); rawpacket_queue_init(&t->delayed); lua_newtable(params.L); t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX); @@ -222,8 +221,9 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr t->pos.client.pos += 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) @@ -319,13 +319,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) || @@ -337,7 +339,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; } } @@ -349,8 +351,10 @@ 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)); @@ -358,7 +362,7 @@ void ConntrackPoolDump(const t_conntrack *p) 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.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.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) diff --git a/nfq2/conntrack.h b/nfq2/conntrack.h index 291f46e..cf856ec 100644 --- a/nfq2/conntrack.h +++ b/nfq2/conntrack.h @@ -54,7 +54,7 @@ typedef struct bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache uint8_t ipproto; - time_t t_start; + 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_positions pos; diff --git a/nfq2/conntrack_base.h b/nfq2/conntrack_base.h index ec7f64d..cc01115 100644 --- a/nfq2/conntrack_base.h +++ b/nfq2/conntrack_base.h @@ -32,7 +32,7 @@ typedef struct typedef struct { - time_t t_last; + struct timespec t_last; t_connstate state; t_ctrack_position client, server; } diff --git a/nfq2/lua.c b/nfq2/lua.c index 8ed2258..ac6f139 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -929,6 +929,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); @@ -1308,7 +1320,7 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_positions *tpos, bo 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", ctrack->t_start); + lua_pushf_lint("t_start", (lua_Number)ctrack->t_start.tv_sec + ctrack->t_start.tv_nsec/1000000000.); lua_pushliteral(params.L, "pos"); lua_createtable(params.L, 0, 5); @@ -1316,7 +1328,9 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_positions *tpos, bo // 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_lint("dt", tpos->t_last - ctrack->t_start); + 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); diff --git a/nfq2/lua.h b/nfq2/lua.h index 4aa1685..1d047df 100644 --- a/nfq2/lua.h +++ b/nfq2/lua.h @@ -69,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);