Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-14 06:13:09 +00:00

nfqws2: autohostlist incoming failure triggers change

This commit is contained in:
bol-van
2025-12-10 23:11:28 +03:00
parent 2dd8533fb5
commit d1690aadcf
7 changed files with 41 additions and 31 deletions

View File

@@ -85,3 +85,5 @@ v0.7
* nfqws2, zapret-lib : fix non-working % and # arg substitution under orchestrator
* nfqws2, zapret-lib : structure conntrack in/out positions. pass in desync.track.pos.{client,server,direct,reverse} position tables
* nfqws2: autohostlist: trigger RST and http redirect failures only within specified relative sequence
* nfqws2: autohostlist: trigger http redirect failure if payload is http_req without connection proto check

View File

@@ -140,7 +140,7 @@ static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bRever
scale = tcp_find_scale_factor(tcp);
mss = ntohs(tcp_find_mss(tcp));
direct->seq_last = ntohl(tcp->th_seq);
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)

View File

@@ -63,7 +63,7 @@ typedef struct
bool dp_search_complete;
uint8_t req_retrans_counter; // number of request retransmissions
bool retrans_detect_finalized;
bool failure_detect_finalized;
uint8_t incoming_ttl;

View File

@@ -252,12 +252,12 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
{
if (l4proto == IPPROTO_TCP)
{
if (ctrack->retrans_detect_finalized)
if (ctrack->failure_detect_finalized)
return false;
if (!seq_within(ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq))
{
ctrack->retrans_detect_finalized = true;
DLOG("retrans : tcp seq %u not within the req range %u-%u. stop tracking.\n", ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq);
ctrack->failure_detect_finalized = true;
DLOG("retrans : tcp seq %u not within range %u-%u. stop tracking.\n", ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq);
ctrack_stop_retrans_counter(ctrack);
auto_hostlist_reset_fail_counter(ctrack->dp, ctrack->hostname, client_ip_port, l7proto);
return false;
@@ -270,7 +270,7 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
{
DLOG("retrans threshold reached : %u/%u\n", ctrack->req_retrans_counter, threshold);
ctrack_stop_retrans_counter(ctrack);
ctrack->retrans_detect_finalized = true;
ctrack->failure_detect_finalized = true;
return true;
}
DLOG("retrans counter : %u/%u\n", ctrack->req_retrans_counter, threshold);
@@ -1097,49 +1097,48 @@ static uint8_t dpi_desync_tcp_packet_play(
// process reply packets for auto hostlist mode
// by looking at RSTs or HTTP replies we decide whether original request looks like DPI blocked
// we only process first-sequence replies. do not react to subsequent redirects or RSTs
if (!params.server && ctrack && ctrack->hostname && ctrack->hostname_ah_check && (ctrack->pos.server.seq_last - ctrack->pos.server.seq0) == 1)
if (!params.server && ctrack && ctrack->hostname_ah_check && !ctrack->failure_detect_finalized)
{
bool bFail = false;
char client_ip_port[48];
if (*params.hostlist_auto_debuglog)
ntop46_port((struct sockaddr*)&dst, client_ip_port, sizeof(client_ip_port));
else
*client_ip_port = 0;
if (seq_within(ctrack->pos.server.seq_last, ctrack->pos.server.seq0, ctrack->pos.server.seq0 + dp->hostlist_auto_incoming_maxseq))
{
bool bFail = false;
uint32_t rseq = ctrack->pos.server.seq_last - ctrack->pos.server.seq0;
if (dis->tcp->th_flags & TH_RST)
{
DLOG("incoming RST detected for hostname %s\n", ctrack->hostname);
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : incoming RST", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto));
bFail = true;
}
else if (dis->len_payload && l7proto == L7_HTTP)
{
if (l7payload == L7P_HTTP_REPLY)
if (dis->tcp->th_flags & TH_RST)
{
DLOG("incoming HTTP reply detected for hostname %s\n", ctrack->hostname);
DLOG("incoming RST detected for hostname %s rseq %u\n", ctrack->hostname, rseq);
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : rseq %u : incoming RST", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto), rseq);
bFail = true;
}
else if (dis->len_payload && l7payload == L7P_HTTP_REPLY)
{
DLOG("incoming HTTP reply detected for hostname %s rseq\n", ctrack->hostname, rseq);
bFail = HttpReplyLooksLikeDPIRedirect(dis->data_payload, dis->len_payload, ctrack->hostname);
if (bFail)
{
DLOG("redirect to another domain detected. possibly DPI redirect.\n");
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : redirect to another domain", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto));
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : rseq %u : redirect to another domain", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto), rseq);
}
else
DLOG("local or in-domain redirect detected. it's not a DPI redirect.\n");
}
else
if (bFail)
{
// received not http reply. do not monitor this connection anymore
DLOG("incoming unknown HTTP data detected for hostname %s\n", ctrack->hostname);
auto_hostlist_failed(dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, l7proto);
ctrack->failure_detect_finalized = true;
}
}
if (bFail)
auto_hostlist_failed(dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, l7proto);
else
if (dis->len_payload)
auto_hostlist_reset_fail_counter(dp, ctrack->hostname, client_ip_port, l7proto);
if (dis->tcp->th_flags & TH_RST)
ctrack->hostname_ah_check = false; // do not react to further dup RSTs
{
// incoming_maxseq exceeded. treat connection as successful
auto_hostlist_reset_fail_counter(dp, ctrack->hostname, client_ip_port, l7proto);
ctrack->failure_detect_finalized = true;
}
}
}
// not reverse

View File

@@ -1435,6 +1435,7 @@ static void exithelp(void)
" --hostlist-auto-fail-time=<int>\t\t\t; all failed attemps must be within these seconds (default : %d)\n"
" --hostlist-auto-retrans-threshold=<int>\t\t; how many request retransmissions cause attempt to fail (default : %d)\n"
" --hostlist-auto-retrans-maxseq=<int>\t\t\t; count retransmissions only within this relative sequence (default : %u)\n"
" --hostlist-auto-incoming-maxseq=<int>\t\t\t; treat tcp connection as successful if incoming relative sequence exceedes this threshold (default : %u)\n"
" --hostlist-auto-debug=<logfile>\t\t\t; debug auto hostlist positives (global parameter)\n"
"\nLUA PACKET PASS MODE:\n"
" --payload=type[,type]\t\t\t\t\t; set payload types following LUA functions should process : %s\n"
@@ -1450,7 +1451,8 @@ static void exithelp(void)
LUA_GC_INTERVAL,
all_protos,
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT,
HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT, HOSTLIST_AUTO_RETRANS_MAXSEQ,
HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
HOSTLIST_AUTO_RETRANS_MAXSEQ, HOSTLIST_AUTO_INCOMING_MAXSEQ,
all_payloads
);
exit(1);
@@ -1548,6 +1550,7 @@ enum opt_indices {
IDX_HOSTLIST_AUTO_FAIL_TIME,
IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD,
IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ,
IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ,
IDX_HOSTLIST_AUTO_DEBUG,
IDX_NEW,
IDX_SKIP,
@@ -1633,6 +1636,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_INCOMING_MAXSEQ] = {"hostlist-auto-incoming-maxseq", required_argument, 0, 0},
[IDX_HOSTLIST_AUTO_DEBUG] = {"hostlist-auto-debug", required_argument, 0, 0},
[IDX_NEW] = {"new", no_argument, 0, 0},
[IDX_SKIP] = {"skip", no_argument, 0, 0},
@@ -2100,6 +2104,9 @@ int main(int argc, char **argv)
case IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ:
dp->hostlist_auto_retrans_maxseq = (uint32_t)atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ:
dp->hostlist_auto_incoming_maxseq = (uint32_t)atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_DEBUG:
{
FILE *F = fopen(optarg, "a+t");

View File

@@ -343,6 +343,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_incoming_maxseq = HOSTLIST_AUTO_INCOMING_MAXSEQ;
dp->filter_ipv4 = dp->filter_ipv6 = true;
}
static void dp_clear_dynamic(struct desync_profile *dp)

View File

@@ -31,6 +31,7 @@
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
#define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3
#define HOSTLIST_AUTO_RETRANS_MAXSEQ 65536
#define HOSTLIST_AUTO_INCOMING_MAXSEQ 4096
#define IPCACHE_LIFETIME 7200
@@ -79,7 +80,7 @@ struct desync_profile
// pointer to autohostlist. NULL if no autohostlist for the profile.
struct hostlist_file *hostlist_auto;
int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold;
uint32_t hostlist_auto_retrans_maxseq;
uint32_t hostlist_auto_retrans_maxseq, hostlist_auto_incoming_maxseq;
hostfail_pool *hostlist_auto_fail_counters;