From 245ce415501c2e84440a7e54bdd909b478926137 Mon Sep 17 00:00:00 2001 From: bol-van Date: Mon, 22 Sep 2025 17:06:30 +0300 Subject: [PATCH] nfqws: altorder mod for hostfakesplit --- nfq/desync.c | 93 ++++++++++++++++++++++++++-------------------------- nfq/nfqws.c | 8 ++++- nfq/params.h | 1 + 3 files changed, 55 insertions(+), 47 deletions(-) diff --git a/nfq/desync.c b/nfq/desync.c index b5f4ce64..13d1e29d 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -1111,8 +1111,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint bool bFake=false; struct sockaddr_storage src, dst; - uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100]; - size_t pkt1_len, pkt2_len; + uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100], pkt3[DPI_DESYNC_MAX_FAKE_LEN+100]; + size_t pkt1_len, pkt2_len, pkt3_len; uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor; uint32_t *timestamps; bool bSack,DF; @@ -2017,6 +2017,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint ip_id = IP4_IP_ID_FIX(dis->ip); + // before_host segment pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, @@ -2031,6 +2032,16 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) goto send_orig; + // pkt3: after_host segment + pkt3_len = sizeof(pkt3); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, + net32_add(dis->tcp->th_seq,pos_endhost), dis->tcp->th_ack, + dis->tcp->th_win, scale_factor, timestamps, + DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), + fooling_orig,0,0,0, + seg+pos_endhost, seg_len-pos_endhost, pkt3, &pkt3_len)) + goto send_orig; + if (!(fakehost=malloc(host_size+1))) { DLOG("fakehost out of memory\n"); @@ -2068,22 +2079,25 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint fakehost[host_size]=0; DLOG("generated fake host: %s\n",fakehost); + // pkt2: fake_host segment pkt2_len = sizeof(pkt2); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_fake,IP4_TOS(dis->ip),ip_id_fake,IP6_FLOW(dis->ip6), dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, fakehost, host_size, pkt2, &pkt2_len)) - { - free(fakehost); - goto send_orig; - } + goto send_orig_clean; DLOG("sending hostfakesplit fake host %zu-%zu len=%zu : ",pos_host,pos_endhost-1,host_size); hexdump_limited_dlog(fakehost,host_size,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len)) + if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len)) + goto send_orig_clean; + + if (dp->hfs_mod.ordering==1) { - free(fakehost); - goto send_orig; + DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ",pos_endhost,seg_len-1,seg_len-pos_endhost); + hexdump_limited_dlog(seg+pos_endhost,seg_len-pos_endhost,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt3, pkt3_len)) + goto send_orig_clean; } sz = pos_split_host ? pos_split_host-pos_host : host_size; @@ -2094,17 +2108,12 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint DF,ttl_orig,IP4_TOS(dis->ip),ip_id_fake,IP6_FLOW(dis->ip6), fooling_orig,0,0,0, seg+pos_host, sz, pkt1, &pkt1_len)) - { - free(fakehost); - goto send_orig; - } + goto send_orig_clean; + DLOG("sending hostfakesplit real host %s%zu-%zu len=%zu : ",pos_split_host ? "part 1 " : "",pos_host,pos_host+sz-1,sz); hexdump_limited_dlog(seg+pos_host,sz,PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - { - free(fakehost); - goto send_orig; - } + goto send_orig_clean; if (pos_split_host) { @@ -2116,39 +2125,31 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint DF,ttl_orig,IP4_TOS(dis->ip),net16_add(ip_id_fake,1),IP6_FLOW(dis->ip6), fooling_orig,0,0,0, seg+pos_split_host, sz, pkt1, &pkt1_len)) - { - free(fakehost); - goto send_orig; - } + goto send_orig_clean; DLOG("sending hostfakesplit real host part 2 %zu-%zu len=%zu : ",pos_split_host,pos_endhost-1,sz); hexdump_limited_dlog(seg+pos_split_host,sz,PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - { - free(fakehost); - goto send_orig; - } + goto send_orig_clean; } - DLOG("sending hostfakesplit fake(2) host %zu-%zu len=%zu : ",pos_host,pos_endhost-1,host_size); - hexdump_limited_dlog(fakehost,host_size,PKTDATA_MAXDUMP); DLOG("\n"); - free(fakehost); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len)) - goto send_orig; - - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, - net32_add(dis->tcp->th_seq,pos_endhost), dis->tcp->th_ack, - dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,0,0,0, - seg+pos_endhost, seg_len-pos_endhost, pkt1, &pkt1_len)) - goto send_orig; - DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ",pos_endhost,seg_len-1,seg_len-pos_endhost); - hexdump_limited_dlog(seg+pos_endhost,seg_len-pos_endhost,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; + if (dp->hfs_mod.ordering==0) + { + DLOG("sending hostfakesplit fake(2) host %zu-%zu len=%zu : ",pos_host,pos_endhost-1,host_size); + hexdump_limited_dlog(fakehost,host_size,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len)) + goto send_orig_clean; + + DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ",pos_endhost,seg_len-1,seg_len-pos_endhost); + hexdump_limited_dlog(seg+pos_endhost,seg_len-pos_endhost,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt3, pkt3_len)) + goto send_orig_clean; + } + free(fakehost); return VERDICT_DROP; +send_orig_clean: + free(fakehost); + goto send_orig; } break; case DESYNC_MULTISPLIT: @@ -2509,7 +2510,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6); - uint8_t pkt3[DPI_DESYNC_MAX_FAKE_LEN+100], *pkt_orig; + uint8_t *pkt_orig; size_t pkt_orig_len; ip_id = IP4_IP_ID_FIX(dis->ip); @@ -2592,7 +2593,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint bool bFake = false; struct sockaddr_storage src, dst; - uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100]; + uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100], pkt3[DPI_DESYNC_MAX_FAKE_LEN+100]; size_t pkt1_len, pkt2_len; uint8_t ttl_orig,ttl_fake; bool DF; @@ -3159,7 +3160,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint { verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6); - uint8_t pkt3[DPI_DESYNC_MAX_FAKE_LEN+100], *pkt_orig; + uint8_t *pkt_orig; size_t pkt_orig_len; // freebsd do not set ip.id diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 465b5d2b..9f370f1a 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -1127,6 +1127,12 @@ static bool parse_hostfakesplit_mod(char *opt, struct hostfakesplit_mod *hfs_mod hfs_mod->host[sizeof(hfs_mod->host)-1-1]=0; hfs_mod->host_size = strlen(hfs_mod->host); // cache value } + else if (!strcmp(p,"altorder")) + { + if (!e2 || !e2[1] || e2[1]==',') goto err; + hfs_mod->ordering = atoi(e2+1); + if (hfs_mod->ordering<0 || hfs_mod->ordering>1) goto err; + } else if (strcmp(p,"none")) goto err; @@ -1685,7 +1691,7 @@ static void exithelp(void) " --dpi-desync-split-seqovl-pattern=|0xHEX ; pattern for the fake part of overlap\n" " --dpi-desync-fakedsplit-pattern=|0xHEX ; fake pattern for fakedsplit/fakeddisorder\n" " --dpi-desync-hostfakesplit-midhost=marker+N|marker-N ; additionally split real hostname at specified marker. must be within host..endhost or won't be splitted.\n" - " --dpi-desync-hostfakesplit-mod=mod[,mod]\t; can be none or host=\n" + " --dpi-desync-hostfakesplit-mod=mod[,mod]\t; mods can be none,host=,altorder=0|1\n" " --dpi-desync-ipfrag-pos-tcp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n" " --dpi-desync-ipfrag-pos-udp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n" " --dpi-desync-ts-increment=\t\t; ts fooling TSval signed increment. default %d\n" diff --git a/nfq/params.h b/nfq/params.h index 1b6ccc84..778ec54a 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -83,6 +83,7 @@ struct hostfakesplit_mod { char host[128]; size_t host_size; + int ordering; }; typedef enum {SS_NONE=0,SS_SYN,SS_SYNACK,SS_ACKSYN} t_synack_split;