diff --git a/binaries/aarch64/nfqws b/binaries/aarch64/nfqws index b4aa038..24c65a1 100755 Binary files a/binaries/aarch64/nfqws and b/binaries/aarch64/nfqws differ diff --git a/binaries/arm/nfqws b/binaries/arm/nfqws index 7d9fb2d..1b15fdc 100755 Binary files a/binaries/arm/nfqws and b/binaries/arm/nfqws differ diff --git a/binaries/mips32r1-lsb/nfqws b/binaries/mips32r1-lsb/nfqws index 4f32320..56a400e 100755 Binary files a/binaries/mips32r1-lsb/nfqws and b/binaries/mips32r1-lsb/nfqws differ diff --git a/binaries/mips32r1-msb/nfqws b/binaries/mips32r1-msb/nfqws index 96d2f92..b00e770 100755 Binary files a/binaries/mips32r1-msb/nfqws and b/binaries/mips32r1-msb/nfqws differ diff --git a/binaries/mips64r2-msb/nfqws b/binaries/mips64r2-msb/nfqws index dfa0304..ae000f0 100755 Binary files a/binaries/mips64r2-msb/nfqws and b/binaries/mips64r2-msb/nfqws differ diff --git a/binaries/ppc/nfqws b/binaries/ppc/nfqws index 22c843d..1ec9638 100755 Binary files a/binaries/ppc/nfqws and b/binaries/ppc/nfqws differ diff --git a/binaries/x86/nfqws b/binaries/x86/nfqws index d843aac..b8a10d8 100755 Binary files a/binaries/x86/nfqws and b/binaries/x86/nfqws differ diff --git a/binaries/x86_64/nfqws b/binaries/x86_64/nfqws index 100f13a..78bf3aa 100755 Binary files a/binaries/x86_64/nfqws and b/binaries/x86_64/nfqws differ diff --git a/nfq/darkmagic.c b/nfq/darkmagic.c index 05df8ff..500ee5d 100644 --- a/nfq/darkmagic.c +++ b/nfq/darkmagic.c @@ -54,7 +54,14 @@ uint8_t tcp_find_scale_factor(const struct tcphdr *tcp) } // n prefix (nsport, nwsize) means network byte order -static void fill_tcphdr(struct tcphdr *tcp, uint8_t fooling, uint8_t tcp_flags, uint32_t nseq, uint32_t nack_seq, uint16_t nsport, uint16_t ndport, uint16_t nwsize, uint8_t scale_factor, uint32_t *timestamps) +static void fill_tcphdr( + struct tcphdr *tcp, uint8_t fooling, uint8_t tcp_flags, + uint32_t nseq, uint32_t nack_seq, + uint16_t nsport, uint16_t ndport, + uint16_t nwsize, uint8_t scale_factor, + uint32_t *timestamps, + uint32_t badseq_increment, + uint32_t badseq_ack_increment) { char *tcpopt = (char*)(tcp+1); uint8_t t=0; @@ -64,13 +71,13 @@ static void fill_tcphdr(struct tcphdr *tcp, uint8_t fooling, uint8_t tcp_flags, tcp->th_dport = ndport; if (fooling & TCP_FOOL_BADSEQ) { - tcp->th_seq = net32_add(nseq,0x80000000); - tcp->th_ack = net32_add(nack_seq,0x80000000); + tcp->th_seq = net32_add(nseq,badseq_increment); + tcp->th_ack = net32_add(nack_seq,badseq_ack_increment); } else { - tcp->th_seq = nseq; - tcp->th_ack = nack_seq; + tcp->th_seq = nseq; + tcp->th_ack = nack_seq; } tcp->th_off = 5; *((uint8_t*)tcp+13)= tcp_flags; @@ -285,7 +292,7 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const void *data,size_t v = ((struct ip6_hdr *)data)->ip6_ctlun.ip6_un1.ip6_un1_hlim; if (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &v, sizeof(v)) == -1) perror("rawsend: setsockopt(IPV6_HOPLIMIT)"); - // the only way to control source address is bind. make it equal to ip6_hdr +[5~ // the only way to control source address is bind. make it equal to ip6_hdr if (bind(sock, (struct sockaddr*)&sa_src, salen) < 0) perror("rawsend bind: "); //printf("BSD v6 RAWSEND "); print_sockaddr((struct sockaddr*)&sa_src); printf(" -> "); print_sockaddr((struct sockaddr*)&dst2); printf("\n"); @@ -342,6 +349,8 @@ bool prepare_tcp_segment4( uint32_t *timestamps, uint8_t ttl, uint8_t fooling, + uint32_t badseq_increment, + uint32_t badseq_ack_increment, const void *data, uint16_t len, uint8_t *buf, size_t *buflen) { @@ -366,7 +375,7 @@ bool prepare_tcp_segment4( ip->ip_src = src->sin_addr; ip->ip_dst = dst->sin_addr; - fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps); + fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment); memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len); tcp4_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,&ip->ip_src,&ip->ip_dst); @@ -386,6 +395,8 @@ bool prepare_tcp_segment6( uint32_t *timestamps, uint8_t ttl, uint8_t fooling, + uint32_t badseq_increment, + uint32_t badseq_ack_increment, const void *data, uint16_t len, uint8_t *buf, size_t *buflen) { @@ -408,7 +419,7 @@ bool prepare_tcp_segment6( ip6->ip6_src = src->sin6_addr; ip6->ip6_dst = dst->sin6_addr; - fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps); + fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment); memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len); tcp6_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,&ip6->ip6_src,&ip6->ip6_dst); @@ -427,13 +438,15 @@ bool prepare_tcp_segment( uint32_t *timestamps, uint8_t ttl, uint8_t fooling, + uint32_t badseq_increment, + uint32_t badseq_ack_increment, const void *data, uint16_t len, uint8_t *buf, size_t *buflen) { return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ? - prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,fooling,data,len,buf,buflen) : + prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) : (src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ? - prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,fooling,data,len,buf,buflen) : + prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) : false; } diff --git a/nfq/darkmagic.h b/nfq/darkmagic.h index 6430e8f..dfe194a 100644 --- a/nfq/darkmagic.h +++ b/nfq/darkmagic.h @@ -31,6 +31,8 @@ bool prepare_tcp_segment4( uint32_t *timestamps, uint8_t ttl, uint8_t fooling, + uint32_t badseq_increment, + uint32_t badseq_ack_increment, const void *data, uint16_t len, uint8_t *buf, size_t *buflen); bool prepare_tcp_segment6( @@ -42,6 +44,8 @@ bool prepare_tcp_segment6( uint32_t *timestamps, uint8_t ttl, uint8_t fooling, + uint32_t badseq_increment, + uint32_t badseq_ack_increment, const void *data, uint16_t len, uint8_t *buf, size_t *buflen); bool prepare_tcp_segment( @@ -53,6 +57,8 @@ bool prepare_tcp_segment( uint32_t *timestamps, uint8_t ttl, uint8_t fooling, + uint32_t badseq_increment, + uint32_t badseq_ack_increment, const void *data, uint16_t len, uint8_t *buf, size_t *buflen); diff --git a/nfq/desync.c b/nfq/desync.c index 8f1a349..ffd499d 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -176,7 +176,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc { newlen = sizeof(newdata); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN|TH_ACK, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_fake,params.desync_tcp_fooling_mode, + ttl_fake,params.desync_tcp_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment, NULL, 0, newdata, &newlen)) { return res; @@ -309,7 +309,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc { case DESYNC_FAKE: if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_fake,params.desync_tcp_fooling_mode, + ttl_fake,params.desync_tcp_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment, fake, fake_size, newdata, &newlen)) { return res; @@ -321,7 +321,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc case DESYNC_RST: case DESYNC_RSTACK: if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (desync_mode==DESYNC_RSTACK ? TH_ACK:0), tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_fake,params.desync_tcp_fooling_mode, + ttl_fake,params.desync_tcp_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment, NULL, 0, newdata, &newlen)) { return res; @@ -373,7 +373,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (split_posth_seq,split_pos), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_orig,TCP_FOOL_NONE, + ttl_orig,TCP_FOOL_NONE,params.desync_badseq_increment,params.desync_badseq_ack_increment, data_payload+split_pos, len_payload-split_pos, newdata, &newlen)) return res; DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,len_payload-1, len_payload-split_pos) @@ -387,7 +387,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc { fakeseg_len = sizeof(fakeseg); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_fake,params.desync_tcp_fooling_mode, + ttl_fake,params.desync_tcp_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment, zeropkt, split_pos, fakeseg, &fakeseg_len)) return res; DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos) @@ -399,7 +399,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc newlen = sizeof(newdata); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_orig,TCP_FOOL_NONE, + ttl_orig,TCP_FOOL_NONE,params.desync_badseq_increment,params.desync_badseq_ack_increment, data_payload, split_pos, newdata, &newlen)) return res; DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos) @@ -429,7 +429,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc { fakeseg_len = sizeof(fakeseg); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_fake,params.desync_tcp_fooling_mode, + ttl_fake,params.desync_tcp_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment, zeropkt, split_pos, fakeseg, &fakeseg_len)) return res; DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos) @@ -440,7 +440,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc newlen = sizeof(newdata); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_orig,TCP_FOOL_NONE, + ttl_orig,TCP_FOOL_NONE,params.desync_badseq_increment,params.desync_badseq_ack_increment, data_payload, split_pos, newdata, &newlen)) return res; DLOG("sending 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos) @@ -460,7 +460,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc { newlen = sizeof(newdata); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->th_seq,split_pos), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, - ttl_orig,TCP_FOOL_NONE, + ttl_orig,TCP_FOOL_NONE,params.desync_badseq_increment,params.desync_badseq_ack_increment, data_payload+split_pos, len_payload-split_pos, newdata, &newlen)) return res; DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ",split_pos,len_payload-1, len_payload-split_pos) diff --git a/nfq/nfqws.c b/nfq/nfqws.c index e07739e..49a2046 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -494,6 +494,8 @@ static void exithelp() " --dpi-desync-repeats=\t\t; send every desync packet N times\n" " --dpi-desync-skip-nosni=0|1\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n" " --dpi-desync-split-pos=<1..%u>\t; TCP packet split position\n" + " --dpi-desync-badseq-increment= ; badseq fooling seq signed increment. default %d\n" + " --dpi-desync-badack-increment= ; badseq fooling ackseq signed increment. default %d\n" " --dpi-desync-any-protocol=0|1\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n" " --dpi-desync-fake-http=\t; file containing fake http request\n" " --dpi-desync-fake-tls=\t; file containing fake TLS ClientHello (for https)\n" @@ -503,7 +505,8 @@ static void exithelp() #if defined(__linux__) || defined(SO_USER_COOKIE) DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT, #endif - DPI_DESYNC_MAX_FAKE_LEN + DPI_DESYNC_MAX_FAKE_LEN, + BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT ); exit(1); } @@ -554,6 +557,8 @@ int main(int argc, char **argv) params.ctrack_t_est = CTRACK_T_EST; params.ctrack_t_fin = CTRACK_T_FIN; params.desync_ttl6 = 0xFF; // unused + params.desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT; + params.desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT; if (can_drop_root()) // are we root ? { @@ -597,11 +602,13 @@ int main(int argc, char **argv) {"dpi-desync-repeats",required_argument,0,0}, // optidx=20 {"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=21 {"dpi-desync-split-pos",required_argument,0,0},// optidx=22 - {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=23 - {"dpi-desync-fake-http",required_argument,0,0},// optidx=24 - {"dpi-desync-fake-tls",required_argument,0,0},// optidx=25 - {"dpi-desync-cutoff",required_argument,0,0},// optidx=26 - {"hostlist",required_argument,0,0}, // optidx=27 + {"dpi-desync-badseq-increment",required_argument,0,0},// optidx=23 + {"dpi-desync-badack-increment",required_argument,0,0},// optidx=24 + {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=25 + {"dpi-desync-fake-http",required_argument,0,0},// optidx=26 + {"dpi-desync-fake-tls",required_argument,0,0},// optidx=27 + {"dpi-desync-cutoff",required_argument,0,0},// optidx=28 + {"hostlist",required_argument,0,0}, // optidx=29 {NULL,0,NULL,0} }; if (argc < 2) exithelp(); @@ -816,10 +823,30 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 23: /* dpi-desync-any-protocol */ + case 23: /* dpi-desync-badseq-increments */ + if ((optarg[0]=='0' && optarg[1]=='x' || optarg[0]=='-' && optarg[1]=='0' && optarg[2]=='x') && sscanf(optarg+2+(optarg[0]=='-'), "%X", (int32_t*)¶ms.desync_badseq_increment)) + { + if (optarg[0]=='-') params.desync_badseq_increment = -params.desync_badseq_increment; + } else if (!sscanf(optarg, "%d", (int32_t*)¶ms.desync_badseq_increment)) + { + fprintf(stderr, "dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n"); + exit_clean(1); + } + break; + case 24: /* dpi-desync-badack-increment */ + if ((optarg[0]=='0' && optarg[1]=='x' || optarg[0]=='-' && optarg[1]=='0' && optarg[2]=='x') && sscanf(optarg+2+(optarg[0]=='-'), "%X", (int32_t*)¶ms.desync_badseq_ack_increment)) + { + if (optarg[0]=='-') params.desync_badseq_ack_increment = -params.desync_badseq_ack_increment; + } else if (!sscanf(optarg, "%d", (int32_t*)¶ms.desync_badseq_ack_increment)) + { + fprintf(stderr, "dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n"); + exit_clean(1); + } + break; + case 25: /* dpi-desync-any-protocol */ params.desync_any_proto = !optarg || atoi(optarg); break; - case 24: /* dpi-desync-fake-http */ + case 26: /* dpi-desync-fake-http */ params.fake_http_size = sizeof(params.fake_http); if (!load_file_nonempty(optarg,params.fake_http,¶ms.fake_http_size)) { @@ -827,7 +854,7 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 25: /* dpi-desync-fake-tls */ + case 27: /* dpi-desync-fake-tls */ params.fake_tls_size = sizeof(params.fake_tls); if (!load_file_nonempty(optarg,params.fake_tls,¶ms.fake_tls_size)) { @@ -835,14 +862,14 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 26: /* desync-cutoff */ + case 28: /* desync-cutoff */ if (!sscanf(optarg, "%u", ¶ms.desync_cutoff)) { fprintf(stderr, "invalid desync-cutoff value\n"); exit_clean(1); } break; - case 27: /* hostlist */ + case 29: /* hostlist */ if (!LoadHostList(¶ms.hostlist, optarg)) exit_clean(1); strncpy(params.hostfile,optarg,sizeof(params.hostfile)); diff --git a/nfq/params.h b/nfq/params.h index 787dc6f..57eaba0 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -17,6 +17,9 @@ #define Q_MAXLEN 1024 // in packets +#define BADSEQ_INCREMENT_DEFAULT -10000 +#define BADSEQ_ACK_INCREMENT_DEFAULT -65000 + struct params_s { bool debug; @@ -37,6 +40,7 @@ struct params_s uint8_t desync_ttl, desync_ttl6; uint8_t desync_tcp_fooling_mode; uint32_t desync_fwmark; // unused in BSD + uint32_t desync_badseq_increment, desync_badseq_ack_increment; char hostfile[256]; strpool *hostlist; uint8_t fake_http[1460],fake_tls[1460];