From 14e9fc4d433c0e6ce35fb6331e69cf98cc44e80b Mon Sep 17 00:00:00 2001 From: bol-van Date: Wed, 13 Nov 2024 11:54:40 +0300 Subject: [PATCH] nfqws: deprecate single split modes, optimize code --- nfq/desync.c | 183 ++++++++++++++++++++++++------------------------- nfq/desync.h | 2 - nfq/nfqws.c | 73 ++++++-------------- nfq/params.h | 2 - nfq/protocol.c | 3 +- 5 files changed, 110 insertions(+), 153 deletions(-) diff --git a/nfq/desync.c b/nfq/desync.c index 53aba77..86a1ce1 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -97,11 +97,11 @@ bool desync_only_first_stage(enum dpi_desync_mode mode) } bool desync_valid_second_stage(enum dpi_desync_mode mode) { - return mode==DESYNC_NONE || mode==DESYNC_FAKEDDISORDER || mode==DESYNC_DISORDER2 || mode==DESYNC_FAKEDSPLIT || mode==DESYNC_SPLIT2 || mode==DESYNC_MULTISPLIT || mode==DESYNC_MULTIDISORDER || mode==DESYNC_IPFRAG2 || mode==DESYNC_UDPLEN || mode==DESYNC_TAMPER; + return mode==DESYNC_NONE || mode==DESYNC_FAKEDDISORDER || mode==DESYNC_FAKEDSPLIT || mode==DESYNC_MULTISPLIT || mode==DESYNC_MULTIDISORDER || mode==DESYNC_IPFRAG2 || mode==DESYNC_UDPLEN || mode==DESYNC_TAMPER; } bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode) { - return mode==DESYNC_NONE || mode==DESYNC_FAKEDDISORDER || mode==DESYNC_DISORDER2 || mode==DESYNC_FAKEDSPLIT || mode==DESYNC_SPLIT2 || mode==DESYNC_MULTISPLIT || mode==DESYNC_MULTIDISORDER || mode==DESYNC_IPFRAG2; + return mode==DESYNC_NONE || mode==DESYNC_FAKEDDISORDER || mode==DESYNC_FAKEDSPLIT || mode==DESYNC_MULTISPLIT || mode==DESYNC_MULTIDISORDER || mode==DESYNC_IPFRAG2; } bool desync_valid_second_stage_udp(enum dpi_desync_mode mode) { @@ -125,15 +125,11 @@ enum dpi_desync_mode desync_mode_from_string(const char *s) return DESYNC_SYNDATA; else if (!strcmp(s,"fakeddisorder") || !strcmp(s,"disorder")) return DESYNC_FAKEDDISORDER; - else if (!strcmp(s,"disorder2")) - return DESYNC_DISORDER2; else if (!strcmp(s,"fakedsplit") || !strcmp(s,"split")) return DESYNC_FAKEDSPLIT; - else if (!strcmp(s,"split2")) - return DESYNC_SPLIT2; - else if (!strcmp(s,"multisplit")) + else if (!strcmp(s,"multisplit") || !strcmp(s,"split2")) return DESYNC_MULTISPLIT; - else if (!strcmp(s,"multidisorder")) + else if (!strcmp(s,"multidisorder") || !strcmp(s,"disorder2")) return DESYNC_MULTIDISORDER; else if (!strcmp(s,"ipfrag2")) return DESYNC_IPFRAG2; @@ -1118,29 +1114,32 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint DLOG("dpi desync src=%s dst=%s\n",s1,s2); } - const struct proto_pos *spos; switch(l7proto) { case HTTP: fake = dp->fake_http; fake_size = dp->fake_http_size; - spos = &dp->split_http; break; case TLS: fake = dp->fake_tls; fake_size = dp->fake_tls_size; - spos = &dp->split_tls; break; default: fake = dp->fake_unknown; fake_size = dp->fake_unknown_size; - spos = &dp->split_unknown; break; } + const struct proto_pos defpos={marker:PM_ABS,pos:2}; if (dp->desync_mode==DESYNC_MULTISPLIT || dp->desync_mode==DESYNC_MULTIDISORDER || dp->desync_mode2==DESYNC_MULTISPLIT || dp->desync_mode2==DESYNC_MULTIDISORDER) { split_pos=0; ResolveMultiPos(rdata_payload, rlen_payload, l7proto, dp->splits, dp->split_count, multisplit_pos, &multisplit_count); + if (!multisplit_count) + { + multisplit_pos[multisplit_count] = ResolvePos(rdata_payload, rlen_payload, l7proto, &defpos); + if (!multisplit_pos[multisplit_count]) multisplit_pos[multisplit_count] = 1; + multisplit_count++; + } if (params.debug) { if (multisplit_count) @@ -1174,12 +1173,20 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } } } - else if (dp->desync_mode==DESYNC_FAKEDSPLIT || dp->desync_mode==DESYNC_SPLIT2 || dp->desync_mode==DESYNC_FAKEDDISORDER || dp->desync_mode==DESYNC_DISORDER2 || - dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_SPLIT2 || dp->desync_mode2==DESYNC_FAKEDDISORDER || dp->desync_mode2==DESYNC_DISORDER2) + else if (dp->desync_mode==DESYNC_FAKEDSPLIT || dp->desync_mode==DESYNC_FAKEDDISORDER || dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_FAKEDDISORDER) { multisplit_count=0; - split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, spos); - if (!split_pos) split_pos = dp->split_unknown.pos; + // first look for non-abs split + for(i=0,split_pos=0;isplit_count && !split_pos;i++) + if (dp->splits[i].marker!=PM_ABS) + split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, dp->splits+i); + // second look for abs split + if (!split_pos) + for(i=0,split_pos=0;isplit_count && !split_pos;i++) + if (dp->splits[i].marker==PM_ABS) + split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, dp->splits+i); + if (!split_pos) split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, &defpos); + if (!split_pos) split_pos = 1; DLOG("regular split pos: %zu\n",split_pos); if (!split_pos || split_pos>rlen_payload) split_pos=1; split_pos=pos_normalize(split_pos,reasm_offset,dis->len_payload); @@ -1241,7 +1248,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint case DESYNC_IPFRAG1: fooling_orig = (dp->desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (dp->desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; if (dis->ip6 && (dp->desync_mode2==DESYNC_NONE || !desync_valid_second_stage_tcp(dp->desync_mode2) || - (!split_pos && (dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_SPLIT2 || dp->desync_mode2==DESYNC_FAKEDDISORDER || dp->desync_mode2==DESYNC_DISORDER2)) || + (!split_pos && (dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_FAKEDDISORDER)) || (!multisplit_count && (dp->desync_mode2==DESYNC_MULTISPLIT || dp->desync_mode2==DESYNC_MULTIDISORDER)))) { if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, @@ -1352,10 +1359,13 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint seg = dis->data_payload+from; seg_len = to-from; seqovl = 0; - if (i>=0 && dp->desync_seqovl) + // do seqovl only to the second packet + // otherwise sequence overlap becomes problematic. overlap algorithm is not too obvious. + // real observations revealed that server can receive overlap junk instead of real data + if (i==0) { if (dp->desync_seqovl>=from) - DLOG("seqovl>=split_pos (%u>=%zu). cancelling seqovl for part %d.\n",dp->desync_seqovl,from,i+2); + DLOG("seqovl>=split_pos (%u>=%zu). cancelling seqovl for part %d.\n",seqovl,from,i+2); else { seqovl = dp->desync_seqovl; @@ -1389,30 +1399,32 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } break; case DESYNC_FAKEDDISORDER: - case DESYNC_DISORDER2: if (split_pos) { uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; size_t seg_len; + unsigned int seqovl; if (dp->desync_seqovl>=split_pos) { - DLOG("seqovl>=split_pos. desync is not possible.\n"); - return verdict; + DLOG("seqovl>=split_pos (%u>=%zu). cancelling seqovl.\n",dp->desync_seqovl,split_pos); + seqovl = 0; } + else + seqovl = dp->desync_seqovl; if (split_poslen_payload) { - if (dp->desync_seqovl) + if (seqovl) { - seg_len = dis->len_payload-split_pos+dp->desync_seqovl; + seg_len = dis->len_payload-split_pos+seqovl; if (seg_len>sizeof(fakeseg)) { DLOG("seqovl is too large\n"); return verdict; } - fill_pattern(fakeseg,dp->desync_seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); - memcpy(fakeseg+dp->desync_seqovl,dis->data_payload+split_pos,dis->len_payload-split_pos); + fill_pattern(fakeseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); + memcpy(fakeseg+seqovl,dis->data_payload+split_pos,dis->len_payload-split_pos); seg = fakeseg; } else @@ -1422,31 +1434,27 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq , split_pos - dp->desync_seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq , split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, ttl_orig,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, seg, seg_len, pkt1, &pkt1_len)) return verdict; - DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos, dp->desync_seqovl); + DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos, seqovl); hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return verdict; } - - if (desync_mode==DESYNC_FAKEDDISORDER) - { - seg_len = sizeof(fakeseg); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - ttl_fake,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - zeropkt, split_pos, fakeseg, &seg_len)) - return verdict; - DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len)) - return verdict; - } + seg_len = sizeof(fakeseg); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + ttl_fake,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), + dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, + zeropkt, split_pos, fakeseg, &seg_len)) + return verdict; + DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); + hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len)) + return verdict; pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, @@ -1459,37 +1467,30 @@ 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)) return verdict; - if (desync_mode==DESYNC_FAKEDDISORDER) - { - DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len)) - return verdict; - } + DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); + hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len)) + return verdict; return VERDICT_DROP; } break; case DESYNC_FAKEDSPLIT: - case DESYNC_SPLIT2: if (split_pos) { uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100],ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; size_t fakeseg_len,seg_len; - if (desync_mode==DESYNC_FAKEDSPLIT) - { - fakeseg_len = sizeof(fakeseg); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - ttl_fake,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - zeropkt, split_pos, fakeseg, &fakeseg_len)) - return verdict; - DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) - return verdict; - } + fakeseg_len = sizeof(fakeseg); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + ttl_fake,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), + dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, + zeropkt, split_pos, fakeseg, &fakeseg_len)) + return verdict; + DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); + hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) + return verdict; unsigned int seqovl = dp->desync_seqovl; #ifdef __linux__ @@ -1539,13 +1540,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } #endif - if (desync_mode==DESYNC_FAKEDSPLIT) - { - DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) - return verdict; - } + DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); + hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) + return verdict; + if (split_poslen_payload) { pkt1_len = sizeof(pkt1); @@ -1738,7 +1737,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint { const uint8_t *fake; size_t fake_size; - bool b; char host[256]; bool bHaveHost=false; @@ -1990,7 +1988,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint ttl_fake = (ctrack_replay && ctrack_replay->autottl) ? ctrack_replay->autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig)); - enum dpi_desync_mode desync_mode = dp->desync_mode; uint32_t fooling_orig = FOOL_NONE; if (params.debug) @@ -2001,15 +1998,14 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint DLOG("dpi desync src=%s dst=%s\n",s1,s2); } + bool bFake = false; pkt1_len = sizeof(pkt1); - b = false; - switch(desync_mode) + switch(dp->desync_mode) { case DESYNC_FAKE_KNOWN: if (l7proto==UNKNOWN) { DLOG("not applying fake because of unknown protocol\n"); - desync_mode = dp->desync_mode2; break; } case DESYNC_FAKE: @@ -2019,12 +2015,12 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return verdict; - b = true; + bFake = true; break; case DESYNC_HOPBYHOP: case DESYNC_DESTOPT: case DESYNC_IPFRAG1: - fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; + fooling_orig = (dp->desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (dp->desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; if (dis->ip6 && (dp->desync_mode2==DESYNC_NONE || !desync_valid_second_stage_udp(dp->desync_mode2))) { if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, @@ -2040,26 +2036,13 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint // this mode is final, no other options available return ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt); } - desync_mode = dp->desync_mode2; break; default: pkt1_len=0; break; } - if (b) - { - if (dp->desync_mode2==DESYNC_NONE || !desync_valid_second_stage_udp(dp->desync_mode2)) - { - DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", dis->len_pkt, dis->len_payload); - verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , dis->data_pkt, dis->len_pkt)) - return verdict; - return ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt); - } - desync_mode = dp->desync_mode2; - } - + enum dpi_desync_mode desync_mode = dp->desync_mode2==DESYNC_NONE ? dp->desync_mode : dp->desync_mode2; switch(desync_mode) { case DESYNC_UDPLEN: @@ -2067,7 +2050,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) { DLOG("could not construct packet with modified length. too large ?\n"); - return verdict; + break; } DLOG("resending original packet with increased by %d length\n", dp->udplen_increment); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) @@ -2084,7 +2067,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint if (szcopy>szbuf) { DLOG("packet is too long to tamper"); - return verdict; + break; } memcpy(pkt2+pkt2_len,dis->data_payload+1,szcopy); pkt2_len+=szcopy; @@ -2092,7 +2075,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len)) { DLOG("could not construct packet with modified length. too large ?\n"); - return verdict; + break; } DLOG("resending tampered DHT\n"); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) @@ -2102,7 +2085,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint else { DLOG("payload is not tamperable\n"); - return verdict; + break; } case DESYNC_IPFRAG2: { @@ -2150,6 +2133,16 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint break; } + if (bFake) + { + // if we are here original message was not sent in any form + // allowing system to pass the message to queue can result in unpredicted send order + DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", dis->len_pkt, dis->len_payload); + verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , dis->data_pkt, dis->len_pkt)) + return verdict; + return ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt); + } } return verdict; diff --git a/nfq/desync.h b/nfq/desync.h index 90be218..ad3aaf0 100644 --- a/nfq/desync.h +++ b/nfq/desync.h @@ -28,8 +28,6 @@ enum dpi_desync_mode { DESYNC_RSTACK, DESYNC_SYNACK, DESYNC_SYNDATA, - DESYNC_SPLIT2, - DESYNC_DISORDER2, DESYNC_FAKEDSPLIT, DESYNC_FAKEDDISORDER, DESYNC_MULTISPLIT, diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 7307231..6f41e08 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -752,7 +752,7 @@ static bool parse_tlspos(const char *s, struct proto_pos *sp) else if (!strcmp(s, "sniext")) { sp->marker = PM_SNI_EXT; - sp->pos=0; + sp->pos=1; } else if (!strcmp(s, "snisld")) { @@ -836,41 +836,6 @@ static bool parse_split_pos_list(char *opt, struct proto_pos *splits, int splits if (p) return false; // too much splits return true; } -static void split_compat(struct desync_profile *dp) -{ - // make it mostly compatible with old versions - int i; - dp->split_unknown.marker=PM_ABS; - dp->split_unknown.pos=2; - for (i=0;isplit_count;i++) - { - if (dp->splits[i].marker==PM_ABS) - { - dp->split_unknown.pos=dp->splits[i].pos; - break; - } - } - if (PROTO_POS_EMPTY(&dp->split_http)) - { - dp->split_http=dp->split_unknown; - for (i=0;isplit_count;i++) - if (IsHostMarker(dp->splits[i].marker) || dp->splits[i].marker==PM_HTTP_METHOD) - { - dp->split_http = dp->splits[i]; - break; - } - } - if (PROTO_POS_EMPTY(&dp->split_tls)) - { - dp->split_tls=dp->split_unknown; - for (i=0;isplit_count;i++) - if (IsHostMarker(dp->splits[i].marker) || dp->splits[i].marker==PM_SNI_EXT) - { - dp->split_tls = dp->splits[i]; - break; - } - } -} static void SplitDebug(void) { struct desync_profile_list *dpl; @@ -878,9 +843,6 @@ static void SplitDebug(void) LIST_FOREACH(dpl, ¶ms.desync_profiles, next) { dp = &dpl->dp; - DLOG("profile %d split_http %s %d\n",dp->n,posmarker_name(dp->split_http.marker),dp->split_http.pos); - DLOG("profile %d split_tls %s %d\n",dp->n,posmarker_name(dp->split_tls.marker),dp->split_tls.pos); - DLOG("profile %d split_unknown %s %d\n",dp->n,posmarker_name(dp->split_unknown.marker),dp->split_unknown.pos); for(int x=0;xsplit_count;x++) DLOG("profile %d multisplit %s %d\n",dp->n,posmarker_name(dp->splits[x].marker),dp->splits[x].pos); } @@ -1066,7 +1028,7 @@ static void exithelp(void) " --domcase\t\t\t\t\t; mix domain case : Host: TeSt.cOm\n" " --dpi-desync=[,][,]\t; try to desync dpi state. modes :\n" "\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n" - "\t\t\t\t\t\t; disorder2 split2 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper\n" + "\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper\n" #ifdef __linux__ " --dpi-desync-fwmark=\t\t; override fwmark for desync packet. default = 0x%08X (%u)\n" #elif defined(SO_USER_COOKIE) @@ -1079,9 +1041,10 @@ static void exithelp(void) " --dpi-desync-fooling=[,]\t\t; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2\n" " --dpi-desync-repeats=\t\t\t; send every desync packet N times\n" " --dpi-desync-skip-nosni=0|1\t\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n" - " --dpi-desync-split-pos=N|-N|marker+N|marker-N\t; comma separated list of split positions. markers: method,host,endhost,sld,endsld,midsld,sniext\n" + " --dpi-desync-split-pos=N|-N|marker+N|marker-N\t; comma separated list of split positions\n" + "\t\t\t\t\t\t; markers: method,host,endhost,sld,endsld,midsld,sniext\n" "\t\t\t\t\t\t; full list is only used by multisplit and multidisorder\n" - "\t\t\t\t\t\t; single split takes first l7-protocol-compatible parameter if present, first abs value otherwise\n" + "\t\t\t\t\t\t; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise\n" " --dpi-desync-split-seqovl=\t\t; use sequence overlap before first sent original split segment\n" " --dpi-desync-split-seqovl-pattern=|0xHEX ; pattern for the fake part of overlap\n" " --dpi-desync-ipfrag-pos-tcp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n" @@ -1589,19 +1552,33 @@ int main(int argc, char **argv) break; case 24: /* dpi-desync-split-http-req */ // obsolete arg - if (!parse_httpreqpos(optarg, &dp->split_http)) + DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS); + if (dp->split_count>=MAX_SPLITS) + { + DLOG_ERR("Too much splits. max splits: %u\n",MAX_SPLITS); + exit_clean(1); + } + if (!parse_httpreqpos(optarg, dp->splits + dp->split_count)) { DLOG_ERR("Invalid argument for dpi-desync-split-http-req\n"); exit_clean(1); } + dp->split_count++; break; case 25: /* dpi-desync-split-tls */ // obsolete arg - if (!parse_tlspos(optarg, &dp->split_tls)) + DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS); + if (dp->split_count>=MAX_SPLITS) + { + DLOG_ERR("Too much splits. max splits: %u\n",MAX_SPLITS); + exit_clean(1); + } + if (!parse_tlspos(optarg, dp->splits + dp->split_count)) { DLOG_ERR("Invalid argument for dpi-desync-split-tls\n"); exit_clean(1); } + dp->split_count++; break; case 26: /* dpi-desync-split-seqovl */ if (sscanf(optarg,"%u",&dp->desync_seqovl)<1) @@ -2048,13 +2025,6 @@ int main(int argc, char **argv) LIST_FOREACH(dpl, ¶ms.desync_profiles, next) { dp = &dpl->dp; - - if (!dp->split_count && (dp->desync_mode==DESYNC_MULTISPLIT || dp->desync_mode==DESYNC_MULTIDISORDER || dp->desync_mode2==DESYNC_MULTISPLIT || dp->desync_mode2==DESYNC_MULTIDISORDER)) - { - DLOG_ERR("multisplit requires explicit split pos\n"); - exit_clean(1); - } - // not specified - use desync_ttl value instead if (dp->desync_ttl6 == 0xFF) dp->desync_ttl6=dp->desync_ttl; if (!AUTOTTL_ENABLED(dp->desync_autottl6)) dp->desync_autottl6 = dp->desync_autottl; @@ -2062,7 +2032,6 @@ int main(int argc, char **argv) DLOG("[profile %d] autottl ipv4 %u:%u-%u\n",dp->n,dp->desync_autottl.delta,dp->desync_autottl.min,dp->desync_autottl.max); if (AUTOTTL_ENABLED(dp->desync_autottl6)) DLOG("[profile %d] autottl ipv6 %u:%u-%u\n",dp->n,dp->desync_autottl6.delta,dp->desync_autottl6.min,dp->desync_autottl6.max); - split_compat(dp); } if (!LoadAllHostLists()) diff --git a/nfq/params.h b/nfq/params.h index 8f5151d..ead35e1 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -60,8 +60,6 @@ struct desync_profile // multisplit struct proto_pos splits[MAX_SPLITS]; int split_count; - // single split pos cache - struct proto_pos split_http,split_tls,split_unknown; char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence unsigned int desync_start, desync_cutoff; diff --git a/nfq/protocol.c b/nfq/protocol.c index fd280f4..62f5f0e 100644 --- a/nfq/protocol.c +++ b/nfq/protocol.c @@ -511,8 +511,7 @@ size_t TLSPos(uint8_t posmarker, int16_t pos, const uint8_t *data, size_t sz) { if (posmarker==PM_SNI_EXT) { - offset = ext-data+1+pos; - return (offset>=0 && offset