From 2a5c0369095a4f1ab52cc6bcc9de5f093df3e061 Mon Sep 17 00:00:00 2001 From: bol-van Date: Tue, 23 Dec 2025 15:13:19 +0300 Subject: [PATCH] nfqws2,zapret-auto: reset retransmitter --- docs/changes.txt | 2 + lua/zapret-auto.lua | 4 ++ lua/zapret-lib.lua | 21 +++------ nfq2/conntrack.c | 99 ++++++++++++++++++++++--------------------- nfq2/conntrack.h | 9 ++-- nfq2/conntrack_base.h | 2 + nfq2/darkmagic.c | 27 ++++++++++++ nfq2/darkmagic.h | 2 + nfq2/desync.c | 69 +++++++++++++++++++++++------- nfq2/lua.c | 3 +- nfq2/nfqws.c | 6 +++ nfq2/params.c | 1 + nfq2/params.h | 1 + 13 files changed, 160 insertions(+), 86 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 2b8edc9..4d680bf 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -130,3 +130,5 @@ v0.7.6 * nfqws2: reevaluate profile on l7/host discovery in any direction * nfqws2: dtls protocol detection +* nfqws2: autohostlist reset retransmitter to break long wait +* zapret-auto: stadard_failure_detector reset retransmitter to break long wait diff --git a/lua/zapret-auto.lua b/lua/zapret-auto.lua index 539f36b..42de9eb 100644 --- a/lua/zapret-auto.lua +++ b/lua/zapret-auto.lua @@ -158,6 +158,10 @@ function standard_failure_detector(desync, crec) dis_reverse(dis) dis.tcp.th_flags = TH_RST dis.tcp.th_win = desync.track and desync.track.pos.reverse.tcp.winsize or 64 + dis.tcp.options = {} + if dis.ip6 then + dis.ip6.ip6_flow = desync.track.pos.reverse.ip6_flow + end DLOG("standard_failure_detector: sending RST to retransmitter") rawsend_dissect(dis) end diff --git a/lua/zapret-lib.lua b/lua/zapret-lib.lua index 5b79d11..2ea723b 100644 --- a/lua/zapret-lib.lua +++ b/lua/zapret-lib.lua @@ -764,29 +764,18 @@ end -- reverses ip addresses, ports and seq/ack function dis_reverse(dis) - local temp if dis.ip then - temp = dis.ip.ip_src - dis.ip.ip_src = dis.ip.ip_dst - dis.ip.ip_dst = temp + dis.ip.ip_src, dis.ip.ip_dst = dis.ip.ip_dst, dis.ip.ip_src end if dis.ip6 then - temp = dis.ip6.ip6_src - dis.ip6.ip6_src = dis.ip6.ip6_dst - dis.ip6.ip6_dst = temp + dis.ip6.ip6_src, dis.ip6.ip6_dst = dis.ip6.ip6_dst, dis.ip6.ip6_src end if dis.tcp then - temp = dis.tcp.th_sport - dis.tcp.th_sport = dis.tcp.th_dport - dis.tcp.th_dport = temp - temp = dis.tcp.th_ack - dis.tcp.th_ack = dis.tcp.th_seq - dis.tcp.th_seq = temp + dis.tcp.th_sport, dis.tcp.th_dport = dis.tcp.th_dport, dis.tcp.th_sport + dis.tcp.th_ack, dis.tcp.th_seq = dis.tcp.th_seq, dis.tcp.th_ack end if dis.udp then - temp = dis.udp.uh_sport - dis.udp.uh_sport = dis.udp.uh_dport - dis.udp.uh_dport = temp + dis.udp.uh_sport, dis.udp.uh_dport = dis.udp.uh_dport, dis.udp.uh_sport end end diff --git a/nfq2/conntrack.c b/nfq2/conntrack.c index 5558479..2ee4c54 100644 --- a/nfq2/conntrack.c +++ b/nfq2/conntrack.c @@ -70,24 +70,24 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s p->pool = NULL; } -void ConntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr) +void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis) { memset(c, 0, sizeof(*c)); - if (ip) + if (dis->ip) { c->l3proto = IPPROTO_IP; - c->dst.ip = bReverse ? ip->ip_src : ip->ip_dst; - c->src.ip = bReverse ? ip->ip_dst : ip->ip_src; + c->dst.ip = bReverse ? dis->ip->ip_src : dis->ip->ip_dst; + c->src.ip = bReverse ? dis->ip->ip_dst : dis->ip->ip_src; } - else if (ip6) + else if (dis->ip6) { c->l3proto = IPPROTO_IPV6; - c->dst.ip6 = bReverse ? ip6->ip6_src : ip6->ip6_dst; - c->src.ip6 = bReverse ? ip6->ip6_dst : ip6->ip6_src; + c->dst.ip6 = bReverse ? dis->ip6->ip6_src : dis->ip6->ip6_dst; + c->src.ip6 = bReverse ? dis->ip6->ip6_dst : dis->ip6->ip6_src; } else c->l3proto = -1; - extract_ports(tcphdr, udphdr, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport); + extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport); } @@ -127,7 +127,7 @@ 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) +static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *dis) { uint8_t scale; uint16_t mss; @@ -136,21 +136,23 @@ static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bRever 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)); + if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow); - direct->seq_last = ntohl(tcp->th_seq); - direct->pos = direct->seq_last + len_payload; - reverse->pos = reverse->seq_last = ntohl(tcp->th_ack); + scale = tcp_find_scale_factor(dis->tcp); + mss = ntohs(tcp_find_mss(dis->tcp)); + + direct->seq_last = ntohl(dis->tcp->th_seq); + direct->pos = direct->seq_last + dis->len_payload; + reverse->pos = reverse->seq_last = ntohl(dis->tcp->th_ack); if (t->pos.state == SYN) direct->uppos_prev = direct->uppos = direct->pos; - else if (len_payload) + else if (dis->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 = ntohs(dis->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; @@ -162,8 +164,7 @@ static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bRever 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) +static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis) { uint8_t scale; uint16_t mss; @@ -171,34 +172,34 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr if (bReverse) { t->pos.server.pcounter++; - t->pos.server.pdcounter += !!len_payload; - t->pos.server.pbcounter += len_payload; + t->pos.server.pdcounter += !!dis->len_payload; + t->pos.server.pbcounter += dis->len_payload; } else { t->pos.client.pcounter++; - t->pos.client.pdcounter += !!len_payload; - t->pos.client.pbcounter += len_payload; + t->pos.client.pdcounter += !!dis->len_payload; + t->pos.client.pbcounter += dis->len_payload; } - if (tcphdr) + if (dis->tcp) { - if (tcp_syn_segment(tcphdr)) + if (tcp_syn_segment(dis->tcp)) { if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry - t->pos.client.seq0 = ntohl(tcphdr->th_seq); + t->pos.client.seq0 = ntohl(dis->tcp->th_seq); } - else if (tcp_synack_segment(tcphdr)) + else if (tcp_synack_segment(dis->tcp)) { // ignore SA dups - uint32_t seq0 = ntohl(tcphdr->th_ack) - 1; + uint32_t seq0 = ntohl(dis->tcp->th_ack) - 1; if (t->pos.state != SYN && t->pos.client.seq0 != seq0) ConntrackReInitTrack(t); // erase current entry if (!t->pos.client.seq0) t->pos.client.seq0 = seq0; - t->pos.server.seq0 = ntohl(tcphdr->th_seq); + t->pos.server.seq0 = ntohl(dis->tcp->th_seq); } - else if (tcphdr->th_flags & (TH_FIN | TH_RST)) + else if (dis->tcp->th_flags & (TH_FIN | TH_RST)) { t->pos.state = FIN; } @@ -207,11 +208,11 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr if (t->pos.state == SYN) { t->pos.state = ESTABLISHED; - if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(tcphdr->th_ack) - 1; + if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(dis->tcp->th_ack) - 1; } } - ConntrackApplyPos(tcphdr, t, bReverse, len_payload); + ConntrackApplyPos(t, bReverse, dis); } clock_gettime(CLOCK_REALTIME, &t->pos.t_last); @@ -219,12 +220,12 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr 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) +static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse) { t_conn conn, connswp; t_conntrack_pool *ctr; - ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr); + ConntrackExtractConn(&conn, false, dis); if ((ctr = ConntrackPoolSearch(*pp, &conn))) { if (bReverse) *bReverse = false; @@ -243,22 +244,22 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip } return false; } -bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse) +bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse) { - return ConntrackPoolDoubleSearchPool(&p->pool, ip, ip6, tcphdr, udphdr, ctrack, bReverse); + return ConntrackPoolDoubleSearchPool(&p->pool, dis, ctrack, bReverse); } -static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse) +static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse) { t_conn conn, connswp; t_conntrack_pool *ctr; bool b_rev; - uint8_t proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : IPPROTO_NONE; + uint8_t proto = dis->tcp ? IPPROTO_TCP : dis->udp ? IPPROTO_UDP : IPPROTO_NONE; - ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr); + ConntrackExtractConn(&conn, false, dis); if ((ctr = ConntrackPoolSearch(*pp, &conn))) { - ConntrackFeedPacket(&ctr->track, (b_rev = false), tcphdr, len_payload); + ConntrackFeedPacket(&ctr->track, (b_rev = false), dis); goto ok; } else @@ -266,16 +267,16 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, co connswap(&conn, &connswp); if ((ctr = ConntrackPoolSearch(*pp, &connswp))) { - ConntrackFeedPacket(&ctr->track, (b_rev = true), tcphdr, len_payload); + ConntrackFeedPacket(&ctr->track, (b_rev = true), dis); goto ok; } } - b_rev = tcphdr && tcp_synack_segment(tcphdr); - if ((tcphdr && tcp_syn_segment(tcphdr)) || b_rev || udphdr) + b_rev = dis->tcp && tcp_synack_segment(dis->tcp); + if ((dis->tcp && tcp_syn_segment(dis->tcp)) || b_rev || dis->udp) { if ((ctr = ConntrackNew(pp, b_rev ? &connswp : &conn))) { - ConntrackFeedPacket(&ctr->track, b_rev, tcphdr, len_payload); + ConntrackFeedPacket(&ctr->track, b_rev, dis); goto ok; } } @@ -286,16 +287,16 @@ ok: if (bReverse) *bReverse = b_rev; return true; } -bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse) +bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse) { - return ConntrackPoolFeedPool(&p->pool, ip, ip6, tcphdr, udphdr, len_payload, ctrack, bReverse); + return ConntrackPoolFeedPool(&p->pool, dis, ctrack, bReverse); } -static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr) +static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct dissect *dis) { t_conn conn, connswp; t_conntrack_pool *t; - ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr); + ConntrackExtractConn(&conn, false, dis); if (!(t = ConntrackPoolSearch(*pp, &conn))) { connswap(&conn, &connswp); @@ -305,9 +306,9 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, co HASH_DEL(*pp, t); ConntrackFreeElem(t); return true; } -bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr) +bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis) { - return ConntrackPoolDropPool(&p->pool, ip, ip6, tcphdr, udphdr); + return ConntrackPoolDropPool(&p->pool, dis); } void ConntrackPoolPurge(t_conntrack *p) diff --git a/nfq2/conntrack.h b/nfq2/conntrack.h index cf856ec..01f99af 100644 --- a/nfq2/conntrack.h +++ b/nfq2/conntrack.h @@ -19,6 +19,7 @@ #include "conntrack_base.h" #include "packet_queue.h" #include "protocol.h" +#include "darkmagic.h" //#define HASH_BLOOM 20 #define HASH_NONFATAL_OOM 1 @@ -100,11 +101,11 @@ typedef struct void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp); void ConntrackPoolDestroy(t_conntrack *p); -bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse); +bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse); // do not create, do not update. only find existing -bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse); -bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr); -void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr); +bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse); +bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis); +void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis); void ConntrackPoolDump(const t_conntrack *p); void ConntrackPoolPurge(t_conntrack *p); void ConntrackClearHostname(t_ctrack *track); diff --git a/nfq2/conntrack_base.h b/nfq2/conntrack_base.h index c9824c5..d3d6ca2 100644 --- a/nfq2/conntrack_base.h +++ b/nfq2/conntrack_base.h @@ -1,5 +1,6 @@ #pragma once +#include #include #define CTRACK_T_SYN 60 @@ -17,6 +18,7 @@ typedef struct 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. + uint32_t ip6flow; // tcp only state, not used in udp uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current diff --git a/nfq2/darkmagic.c b/nfq2/darkmagic.c index 5f1fbc7..07e7172 100644 --- a/nfq2/darkmagic.c +++ b/nfq2/darkmagic.c @@ -547,6 +547,33 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis) } } +void reverse_ip(struct ip *ip, struct ip6_hdr *ip6) +{ + if (ip) + { + struct in_addr temp = ip->ip_src; + ip->ip_src = ip->ip_dst; + ip->ip_dst = temp; + ip4_fix_checksum(ip); + } + if (ip6) + { + struct in6_addr temp = ip6->ip6_src; + ip6->ip6_src = ip6->ip6_dst; + ip6->ip6_dst = temp; + } +} +void reverse_tcp(struct tcphdr *tcp) +{ + uint16_t tport = tcp->th_sport; + tcp->th_sport = tcp->th_dport; + tcp->th_dport = tport; + + uint32_t tseq = tcp->th_seq; + tcp->th_seq = tcp->th_ack; + tcp->th_ack = tseq; +} + uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6) { diff --git a/nfq2/darkmagic.h b/nfq2/darkmagic.h index a1b3b1c..25b7761 100644 --- a/nfq2/darkmagic.h +++ b/nfq2/darkmagic.h @@ -162,6 +162,8 @@ struct dissect size_t len_payload; }; void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis); +void reverse_ip(struct ip *ip, struct ip6_hdr *ip6); +void reverse_tcp(struct tcphdr *tcp); uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6); diff --git a/nfq2/desync.c b/nfq2/desync.c index 372c81b..2baca46 100644 --- a/nfq2/desync.c +++ b/nfq2/desync.c @@ -246,11 +246,13 @@ static bool is_retransmission(const t_ctrack_position *pos) } // 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) +static bool auto_hostlist_retrans + (t_ctrack *ctrack, const struct dissect *dis, int threshold, const char *client_ip_port, t_l7proto l7proto, + const struct sockaddr *client, const char *ifclient) { if (ctrack && ctrack->dp && ctrack->hostname_ah_check && !ctrack->failure_detect_finalized && ctrack->req_retrans_counter != RETRANS_COUNTER_STOP) { - if (l4proto == IPPROTO_TCP && ctrack->pos.state!=SYN) + if (dis->proto == IPPROTO_TCP && ctrack->pos.state!=SYN) { if (!seq_within(ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq)) { @@ -269,6 +271,46 @@ 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->failure_detect_finalized = true; + if (dis->tcp && ctrack->dp->hostlist_auto_retrans_reset && (dis->ip || dis->ip6)) + { + uint8_t pkt[sizeof(struct ip6_hdr)+sizeof(struct tcphdr)]; + struct ip *ip; + struct ip6_hdr *ip6; + struct tcphdr *tcp; + uint16_t pktlen; + + if (dis->ip) + { + ip = (struct ip*)pkt; ip6=NULL; + pktlen = sizeof(struct iphdr) + sizeof(struct tcphdr); + *ip = *dis->ip; + ip->ip_hl = sizeof(struct iphdr)/4; // remove ip options + ip->ip_len = htons(pktlen); + ip->ip_id=0; + tcp = (struct tcphdr*)(ip+1); + *tcp = *dis->tcp; + } + else if (dis->ip6) + { + ip6 = (struct ip6_hdr*)pkt; ip=NULL; + pktlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); + *ip6 = *dis->ip6; + ip6->ip6_plen = htons(sizeof(struct tcphdr)); + ip6->ip6_nxt = IPPROTO_TCP; + ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(ctrack->pos.server.ip6flow); + tcp = (struct tcphdr*)(ip6+1); + *tcp = *dis->tcp; + } + reverse_ip(ip,ip6); // also fixes ip4 checksum + reverse_tcp(tcp); + tcp->th_off = sizeof(struct tcphdr)/4; // remove tcp options + tcp->th_flags = TH_RST; + tcp->th_win = ctrack->pos.server.winsize; + tcp_fix_checksum(tcp, sizeof(struct tcphdr), ip, ip6); + + DLOG("sending RST to retransmitter\n"); + rawsend(client,0,ifclient,pkt,pktlen); + } return true; } DLOG("retrans counter : %u/%u\n", ctrack->req_retrans_counter, threshold); @@ -330,13 +372,13 @@ static void fill_client_ip_port(const struct sockaddr *client, char *client_ip_p else *client_ip_port = 0; } -static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto, const struct sockaddr *client) +static void process_retrans_fail(t_ctrack *ctrack, const struct dissect *dis, struct sockaddr *client, const char *ifclient) { if (params.server) return; // no autohostlists in server mode char client_ip_port[48]; 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)) + if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, dis, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto, client, ifclient)) { 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); @@ -1036,7 +1078,7 @@ static uint8_t dpi_desync_tcp_packet_play( // in replay mode conntrack_replay is not NULL and ctrack is NULL //ConntrackPoolDump(¶ms.conntrack); - if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, &ctrack_replay, &bReverse) || bReverse) + if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis, &ctrack_replay, &bReverse) || bReverse) return verdict; bReverseFixed = bReverse ^ params.server; setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport); @@ -1068,7 +1110,7 @@ static uint8_t dpi_desync_tcp_packet_play( if (!params.ctrack_disable) { ConntrackPoolPurge(¶ms.conntrack); - if (ConntrackPoolFeed(¶ms.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, dis->len_payload, &ctrack, &bReverse)) + if (ConntrackPoolFeed(¶ms.conntrack, dis, &ctrack, &bReverse)) { dp = ctrack->dp; ctrack_replay = ctrack; @@ -1228,7 +1270,7 @@ static uint8_t dpi_desync_tcp_packet_play( rlen_payload = ctrack->reasm_client.size_present; } - process_retrans_fail(ctrack, IPPROTO_TCP, (struct sockaddr*)&src); + process_retrans_fail(ctrack, dis, (struct sockaddr*)&src, ifin); if (IsHttp(rdata_payload, rlen_payload)) { DLOG("packet contains HTTP request\n"); @@ -1498,7 +1540,7 @@ static uint8_t dpi_desync_udp_packet_play( // in replay mode conntrack_replay is not NULL and ctrack is NULL //ConntrackPoolDump(¶ms.conntrack); - if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis->ip, dis->ip6, NULL, dis->udp, &ctrack_replay, &bReverse) || bReverse) + if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis, &ctrack_replay, &bReverse) || bReverse) return verdict; bReverseFixed = bReverse ^ params.server; setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport); @@ -1530,7 +1572,7 @@ static uint8_t dpi_desync_udp_packet_play( if (!params.ctrack_disable) { ConntrackPoolPurge(¶ms.conntrack); - if (ConntrackPoolFeed(¶ms.conntrack, dis->ip, dis->ip6, NULL, dis->udp, dis->len_payload, &ctrack, &bReverse)) + if (ConntrackPoolFeed(¶ms.conntrack, dis, &ctrack, &bReverse)) { dp = ctrack->dp; ctrack_replay = ctrack; @@ -1836,13 +1878,8 @@ static uint8_t dpi_desync_udp_packet_play( ctrack_replay->bCheckExcluded = bCheckExcluded; } } - if (bCheckResult) - ctrack_stop_retrans_counter(ctrack_replay); - else - { - if (ctrack_replay) - ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded; - } + if (!bCheckResult && ctrack_replay) + ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded; } process_udp_fail(ctrack_replay, tpos, (struct sockaddr*)&src); diff --git a/nfq2/lua.c b/nfq2/lua.c index fe4d70c..15b844f 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -1279,7 +1279,7 @@ void lua_pushf_ctrack_pos(const t_ctrack *ctrack, const t_ctrack_position *pos) if (ctrack->ipproto == IPPROTO_TCP) { lua_pushliteral(params.L, "tcp"); - lua_createtable(params.L, 0, 11); + lua_createtable(params.L, 0, 12); lua_pushf_lint("seq0", pos->seq0); lua_pushf_lint("seq", pos->seq_last); lua_pushf_lint("rseq", pos->seq_last - pos->seq0); @@ -1291,6 +1291,7 @@ void lua_pushf_ctrack_pos(const t_ctrack *ctrack, const t_ctrack_position *pos) lua_pushf_int("winsize_calc", pos->winsize_calc); lua_pushf_int("scale", pos->scale); lua_pushf_int("mss", pos->mss); + lua_pushf_int("ip6flow", pos->ip6flow); lua_rawset(params.L,-3); } diff --git a/nfq2/nfqws.c b/nfq2/nfqws.c index a36ddb3..3c4637f 100644 --- a/nfq2/nfqws.c +++ b/nfq2/nfqws.c @@ -1436,6 +1436,7 @@ static void exithelp(void) " --hostlist-auto-fail-time=\t\t\t; all failed attemps must be within these seconds (default : %d)\n" " --hostlist-auto-retrans-threshold=\t\t; how many request retransmissions cause attempt to fail (default : %d)\n" " --hostlist-auto-retrans-maxseq=\t\t\t; count retransmissions only within this relative sequence (default : %u)\n" + " --hostlist-auto-retrans-reset=[0|1]\t\t\t; send RST to retransmitter to break long wait (default: 1)\n" " --hostlist-auto-incoming-maxseq=\t\t\t; treat tcp connection as successful if incoming relative sequence exceedes this threshold (default : %u)\n" " --hostlist-auto-udp-out=\t\t\t\t; udp failure condition : sent at least `udp_out` packets (default : %u)\n" " --hostlist-auto-udp-in=\t\t\t\t; udp failure condition : received not more than `udp_in` packets (default : %u)\n" @@ -1554,6 +1555,7 @@ enum opt_indices { IDX_HOSTLIST_AUTO_FAIL_TIME, IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD, IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ, + IDX_HOSTLIST_AUTO_RETRANS_RESET, IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ, IDX_HOSTLIST_AUTO_UDP_IN, IDX_HOSTLIST_AUTO_UDP_OUT, @@ -1642,6 +1644,7 @@ 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_RETRANS_RESET] = {"hostlist-auto-retrans-reset", optional_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}, @@ -2100,6 +2103,9 @@ int main(int argc, char **argv) case IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ: dp->hostlist_auto_incoming_maxseq = (uint32_t)atoi(optarg); break; + case IDX_HOSTLIST_AUTO_RETRANS_RESET: + dp->hostlist_auto_retrans_reset = !optarg || !!atoi(optarg); + break; case IDX_HOSTLIST_AUTO_UDP_OUT: dp->hostlist_auto_udp_out = atoi(optarg); break; diff --git a/nfq2/params.c b/nfq2/params.c index 6c371df..977a3a1 100644 --- a/nfq2/params.c +++ b/nfq2/params.c @@ -350,6 +350,7 @@ 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_retrans_reset = true; 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; diff --git a/nfq2/params.h b/nfq2/params.h index 0a742f4..6b28872 100644 --- a/nfq2/params.h +++ b/nfq2/params.h @@ -84,6 +84,7 @@ struct desync_profile int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold; int hostlist_auto_udp_in, hostlist_auto_udp_out; uint32_t hostlist_auto_retrans_maxseq, hostlist_auto_incoming_maxseq; + bool hostlist_auto_retrans_reset; hostfail_pool *hostlist_auto_fail_counters;