From 4aef7a96a448585acfed314d13a6c4a135763489 Mon Sep 17 00:00:00 2001 From: bol-van Date: Sat, 5 Feb 2022 15:41:46 +0300 Subject: [PATCH] nfqws: ipfrag1 desync mode --- nfq/darkmagic.c | 52 +++++++++++++++++++++++++++++++++++++++++-------- nfq/darkmagic.h | 1 + nfq/desync.c | 22 ++++++++++++--------- nfq/desync.h | 3 ++- nfq/nfqws.c | 2 +- 5 files changed, 61 insertions(+), 19 deletions(-) diff --git a/nfq/darkmagic.c b/nfq/darkmagic.c index b00cf9a..25267e7 100644 --- a/nfq/darkmagic.c +++ b/nfq/darkmagic.c @@ -205,7 +205,11 @@ bool prepare_tcp_segment6( { uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor); uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len; - uint16_t ip_payload_len = transport_payload_len + 8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) + 16*!!(fooling & FOOL_HOPBYHOP2) + 8*!!(fooling & FOOL_DESTOPT); + uint16_t ip_payload_len = transport_payload_len + + 8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) + + 16*!!(fooling & FOOL_HOPBYHOP2) + + 8*!!(fooling & FOOL_DESTOPT) + + 8*!!(fooling & FOOL_IPFRAG1); uint16_t pktlen = sizeof(struct ip6_hdr) + ip_payload_len; if (pktlen>*buflen) return false; @@ -227,7 +231,7 @@ bool prepare_tcp_segment6( } hbh->ip6h_nxt = IPPROTO_TCP; nexttype = &hbh->ip6h_nxt; - proto = 0; // hop by hop options + proto = IPPROTO_HOPOPTS; } if (fooling & FOOL_DESTOPT) { @@ -236,9 +240,23 @@ bool prepare_tcp_segment6( memset(dest,0,8); dest->ip6d_nxt = IPPROTO_TCP; if (nexttype) - *nexttype = 60; // destination options + *nexttype = IPPROTO_DSTOPTS; else - proto = 60; + proto = IPPROTO_DSTOPTS; + nexttype = &dest->ip6d_nxt; + } + if (fooling & FOOL_IPFRAG1) + { + struct ip6_frag *frag = (struct ip6_frag*)tcp; + tcp = (struct tcphdr*)((uint8_t*)tcp+sizeof(struct ip6_frag)); + frag->ip6f_nxt = IPPROTO_TCP; + frag->ip6f_ident = htonl(1+random()%0xFFFFFFFF); + frag->ip6f_reserved = 0; + frag->ip6f_offlg = 0; + if (nexttype) + *nexttype = IPPROTO_FRAGMENT; + else + proto = IPPROTO_FRAGMENT; } uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen; @@ -309,7 +327,11 @@ bool prepare_udp_segment6( uint8_t *buf, size_t *buflen) { uint16_t transport_payload_len = sizeof(struct udphdr) + len; - uint16_t ip_payload_len = transport_payload_len + 8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) + 16*!!(fooling & FOOL_HOPBYHOP2) + 8*!!(fooling & FOOL_DESTOPT) ; + uint16_t ip_payload_len = transport_payload_len + + 8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) + + 16*!!(fooling & FOOL_HOPBYHOP2) + + 8*!!(fooling & FOOL_DESTOPT) + + 8*!!(fooling & FOOL_IPFRAG1); uint16_t pktlen = sizeof(struct ip6_hdr) + ip_payload_len; if (pktlen>*buflen) return false; @@ -331,7 +353,7 @@ bool prepare_udp_segment6( } hbh->ip6h_nxt = IPPROTO_UDP; nexttype = &hbh->ip6h_nxt; - proto = 0; // hop by hop options + proto = IPPROTO_HOPOPTS; } if (fooling & FOOL_DESTOPT) { @@ -340,9 +362,23 @@ bool prepare_udp_segment6( memset(dest,0,8); dest->ip6d_nxt = IPPROTO_UDP; if (nexttype) - *nexttype = 60; // destination options + *nexttype = IPPROTO_DSTOPTS; else - proto = 60; + proto = IPPROTO_DSTOPTS; + nexttype = &dest->ip6d_nxt; + } + if (fooling & FOOL_IPFRAG1) + { + struct ip6_frag *frag = (struct ip6_frag*)udp; + udp = (struct udphdr*)((uint8_t*)udp+sizeof(struct ip6_frag)); + frag->ip6f_nxt = IPPROTO_UDP; + frag->ip6f_ident = htonl(1+random()%0xFFFFFFFF); + frag->ip6f_reserved = 0; + frag->ip6f_offlg = 0; + if (nexttype) + *nexttype = IPPROTO_FRAGMENT; + else + proto = IPPROTO_FRAGMENT; } uint8_t *payload = (uint8_t*)(udp+1); diff --git a/nfq/darkmagic.h b/nfq/darkmagic.h index cf02849..34889eb 100644 --- a/nfq/darkmagic.h +++ b/nfq/darkmagic.h @@ -23,6 +23,7 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment); #define FOOL_HOPBYHOP 0x10 #define FOOL_HOPBYHOP2 0x20 #define FOOL_DESTOPT 0x40 +#define FOOL_IPFRAG1 0x80 #define SCALE_NONE ((uint8_t)-1) diff --git a/nfq/desync.c b/nfq/desync.c index 236768d..c080cc6 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -67,7 +67,7 @@ bool desync_valid_zero_stage(enum dpi_desync_mode mode) } bool desync_valid_first_stage(enum dpi_desync_mode mode) { - return mode==DESYNC_FAKE || mode==DESYNC_RST || mode==DESYNC_RSTACK || mode==DESYNC_HOPBYHOP || mode==DESYNC_DESTOPT; + return mode==DESYNC_FAKE || mode==DESYNC_RST || mode==DESYNC_RSTACK || mode==DESYNC_HOPBYHOP || mode==DESYNC_DESTOPT || mode==DESYNC_IPFRAG1; } bool desync_only_first_stage(enum dpi_desync_mode mode) { @@ -103,6 +103,8 @@ enum dpi_desync_mode desync_mode_from_string(const char *s) return DESYNC_HOPBYHOP; else if (!strcmp(s,"destopt")) return DESYNC_DESTOPT; + else if (!strcmp(s,"ipfrag1")) + return DESYNC_IPFRAG1; return DESYNC_INVALID; } @@ -389,7 +391,8 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s break; case DESYNC_HOPBYHOP: case DESYNC_DESTOPT: - fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : FOOL_DESTOPT; + case DESYNC_IPFRAG1: + fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; if (ip6hdr && params.desync_mode2==DESYNC_NONE) { if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, @@ -562,15 +565,15 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s size_t pkt_orig_len; size_t ipfrag_pos = (params.desync_ipfrag_pos_tcp && params.desync_ipfrag_pos_tcpip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()&0xFFFFFFFF); + uint32_t ident = ip ? ip->ip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()%0xFFFFFFFF); pkt1_len = sizeof(pkt1); pkt2_len = sizeof(pkt2); - if (ip6hdr && fooling_orig!=FOOL_NONE) + if (ip6hdr && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT)) { pkt_orig_len = sizeof(pkt3); - if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? 0 : 60, data_pkt, len_pkt, pkt3, &pkt_orig_len)) + if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, data_pkt, len_pkt, pkt3, &pkt_orig_len)) return res; pkt_orig = pkt3; } @@ -690,7 +693,8 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s break; case DESYNC_HOPBYHOP: case DESYNC_DESTOPT: - fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : FOOL_DESTOPT; + case DESYNC_IPFRAG1: + fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; if (ip6hdr && params.desync_mode2==DESYNC_NONE) { if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, @@ -750,15 +754,15 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s size_t len_transport = len_payload + sizeof(struct udphdr); size_t ipfrag_pos = (params.desync_ipfrag_pos_udp && params.desync_ipfrag_pos_udpip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()&0xFFFFFFFF); + uint32_t ident = ip ? ip->ip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()%0xFFFFFFFF); pkt1_len = sizeof(pkt1); pkt2_len = sizeof(pkt2); - if (ip6hdr && fooling_orig!=FOOL_NONE) + if (ip6hdr && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT)) { pkt_orig_len = sizeof(pkt3); - if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? 0 : 60, data_pkt, len_pkt, pkt3, &pkt_orig_len)) + if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, data_pkt, len_pkt, pkt3, &pkt_orig_len)) return res; pkt_orig = pkt3; } diff --git a/nfq/desync.h b/nfq/desync.h index 6be6160..b531af0 100644 --- a/nfq/desync.h +++ b/nfq/desync.h @@ -31,7 +31,8 @@ enum dpi_desync_mode { DESYNC_SPLIT2, DESYNC_IPFRAG2, DESYNC_HOPBYHOP, - DESYNC_DESTOPT + DESYNC_DESTOPT, + DESYNC_IPFRAG1 }; extern const char *fake_http_request_default; diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 4a45046..f055aba 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -505,7 +505,7 @@ static void exithelp() " --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n" " --hostnospace\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n" " --domcase\t\t\t\t; mix domain case : Host: TeSt.cOm\n" - " --dpi-desync=[,][,] ; try to desync dpi state. modes : synack fake rst rstack hopbyhop destopt disorder disorder2 split split2 ipfrag2\n" + " --dpi-desync=[,][,] ; try to desync dpi state. modes : synack fake rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2\n" #ifdef __linux__ " --dpi-desync-fwmark=\t; override fwmark for desync packet. default = 0x%08X (%u)\n" #elif defined(SO_USER_COOKIE)