diff --git a/binaries/aarch64/nfqws b/binaries/aarch64/nfqws index 4da8068..2690077 100755 Binary files a/binaries/aarch64/nfqws and b/binaries/aarch64/nfqws differ diff --git a/binaries/armhf/nfqws b/binaries/armhf/nfqws index 6fcc17e..f772cba 100755 Binary files a/binaries/armhf/nfqws and b/binaries/armhf/nfqws differ diff --git a/binaries/mips32r1-lsb/nfqws b/binaries/mips32r1-lsb/nfqws index b00f7c1..287c59e 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 52e4d3c..1248659 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 a21833b..0355d75 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 d84c5ba..6cc939b 100755 Binary files a/binaries/ppc/nfqws and b/binaries/ppc/nfqws differ diff --git a/binaries/x86/nfqws b/binaries/x86/nfqws index 419b002..60c3261 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 0b9773b..87a0b3b 100755 Binary files a/binaries/x86_64/nfqws and b/binaries/x86_64/nfqws differ diff --git a/docs/readme.eng.txt b/docs/readme.eng.txt index d6bc2f9..a8198c8 100644 --- a/docs/readme.eng.txt +++ b/docs/readme.eng.txt @@ -132,6 +132,7 @@ It takes the following parameters: --dpi-desync-ttl= ; set ttl for desync packet --dpi-desync-fooling=none|md5sig|ts|badseq|badsum ; can take multiple comma separated values --dpi-desync-retrans=0|1 ; (fake,rst,rstack only) 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission + --dpi-desync-repeats= ; send every desync packet N times --dpi-desync-skip-nosni=0|1 ; 1(default)=do not apply desync to requests without hostname in the SNI --dpi-desync-split-pos=<1..1500> ; (for disorder only) split TCP packet at specified position --dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet diff --git a/docs/readme.txt b/docs/readme.txt index c69ebf0..fb15f06 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -173,6 +173,7 @@ nfqws --dpi-desync-ttl= ; установить ttl для десинхронизирующих пакетов --dpi-desync-fooling=none|md5sig|ts|badseq|badsum ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера --dpi-desync-retrans=0|1 ; (только для fake,rst,rstack) 0(default)=отправлять оригинал следом за фейком 1=дропать оригинал, заставляя ОС выполнять ретрансмиссию через 0.2 сек + --dpi-desync-repeats= ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты) --dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI --dpi-desync-split-pos=<1..1500> ; (только для disorder) разбивать пакет на указанной позиции --dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных diff --git a/nfq/desync.c b/nfq/desync.c index 96b701b..c15c06f 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -57,6 +57,16 @@ void desync_init() } +// auto creates internal socket and uses it for subsequent calls +static bool rawsend_rep(struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len) +{ + for (int i=0;iseq,split_pos), tcphdr->ack_seq, tcphdr->window, timestamps, ttl_orig,TCP_FOOL_NONE, data_payload+split_pos, len_payload-split_pos, newdata, &newlen) || - !rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) + !rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) { return res; } @@ -196,7 +206,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window, timestamps, ttl_fake,params.desync_tcp_fooling_mode, zeropkt, split_pos, fakeseg, &fakeseg_len) || - !rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) + !rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) { return res; } @@ -208,7 +218,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window, timestamps, ttl_orig,TCP_FOOL_NONE, data_payload, split_pos, newdata, &newlen) || - !rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) + !rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) { return res; } @@ -216,7 +226,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (params.desync_mode==DESYNC_DISORDER) { DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos) - if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) + if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) return res; } @@ -237,7 +247,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window, timestamps, ttl_fake,params.desync_tcp_fooling_mode, zeropkt, split_pos, fakeseg, &fakeseg_len) || - !rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) + !rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) { return res; } @@ -248,7 +258,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window, timestamps, ttl_orig,TCP_FOOL_NONE, data_payload, split_pos, newdata, &newlen) || - !rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) + !rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) { return res; } @@ -256,7 +266,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (params.desync_mode==DESYNC_SPLIT) { DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos) - if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) + if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) return res; } @@ -267,7 +277,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->seq,split_pos), tcphdr->ack_seq, tcphdr->window, timestamps, ttl_orig,TCP_FOOL_NONE, data_payload+split_pos, len_payload-split_pos, newdata, &newlen) || - !rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) + !rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) { return res; } @@ -299,7 +309,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc return res; } - if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) + if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) return res; if (params.desync_retrans) @@ -309,7 +319,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", len_pkt, len_payload) // if original packet was tampered earlier it needs checksum fixed if (res==modify) tcp_fix_checksum(tcphdr,len_tcp,iphdr,ip6hdr); - if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, data_pkt, len_pkt)) + if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, data_pkt, len_pkt)) return res; } return drop; diff --git a/nfq/nfqws.c b/nfq/nfqws.c index c62f027..2d9209e 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -257,6 +257,7 @@ static void exithelp() " --dpi-desync-ttl=\t\t\t; set ttl for desync packet\n" " --dpi-desync-fooling=[,]\t; can use multiple comma separated values. modes : none md5sig ts badseq badsum\n" " --dpi-desync-retrans=0|1\t\t; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission\n" + " --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; (for disorder only) split TCP packet at specified position\n" " --dpi-desync-any-protocol=0|1\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n" @@ -310,6 +311,7 @@ int main(int argc, char **argv) params.desync_fwmark = DPI_DESYNC_FWMARK_DEFAULT; params.desync_skip_nosni = true; params.desync_split_pos = 3; + params.desync_repeats = 1; const struct option long_options[] = { {"debug",optional_argument,0,0}, // optidx=0 @@ -327,10 +329,11 @@ int main(int argc, char **argv) {"dpi-desync-ttl",required_argument,0,0}, // optidx=12 {"dpi-desync-fooling",required_argument,0,0}, // optidx=13 {"dpi-desync-retrans",optional_argument,0,0}, // optidx=14 - {"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=15 - {"dpi-desync-split-pos",required_argument,0,0},// optidx=16 - {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=17 - {"hostlist",required_argument,0,0}, // optidx=18 + {"dpi-desync-repeats",required_argument,0,0}, // optidx=15 + {"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=16 + {"dpi-desync-split-pos",required_argument,0,0},// optidx=17 + {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=18 + {"hostlist",required_argument,0,0}, // optidx=19 {NULL,0,NULL,0} }; if (argc < 2) exithelp(); @@ -460,10 +463,18 @@ int main(int argc, char **argv) case 14: /* dpi-desync-retrans */ params.desync_retrans = !optarg || atoi(optarg); break; - case 15: /* dpi-desync-skip-nosni */ + case 15: /* dpi-desync-repeats */ + params.desync_repeats = atoi(optarg); + if (params.desync_repeats<=0 || params.desync_repeats>20) + { + fprintf(stderr, "dpi-desync-repeats must be within 1..20\n"); + exit_clean(1); + } + break; + case 16: /* dpi-desync-skip-nosni */ params.desync_skip_nosni = !optarg || atoi(optarg); break; - case 16: /* dpi-desync-split-pos */ + case 17: /* dpi-desync-split-pos */ params.desync_split_pos = atoi(optarg); if (params.desync_split_pos<1 || params.desync_split_pos>DPI_DESYNC_MAX_FAKE_LEN) { @@ -471,10 +482,10 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 17: /* dpi-desync-any-protocol */ + case 18: /* dpi-desync-any-protocol */ params.desync_any_proto = !optarg || atoi(optarg); break; - case 18: /* hostlist */ + case 19: /* 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 63be26a..b13ad6e 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -19,7 +19,7 @@ struct params_s char hostspell[4]; enum dpi_desync_mode desync_mode; bool desync_retrans,desync_skip_nosni,desync_any_proto; - int desync_split_pos; + int desync_repeats,desync_split_pos; uint8_t desync_ttl; uint8_t desync_tcp_fooling_mode; uint32_t desync_fwmark; diff --git a/nfq/strpool.c b/nfq/strpool.c index 41e62a9..6649763 100644 --- a/nfq/strpool.c +++ b/nfq/strpool.c @@ -6,71 +6,71 @@ #undef uthash_nonfatal_oom #define uthash_nonfatal_oom(elt) ut_oom_recover(elt) -static bool oom=false; +static bool oom = false; static void ut_oom_recover(strpool *elem) { - oom=true; + oom = true; } // for zero terminated strings -bool StrPoolAddStr(strpool **pp,const char *s) +bool StrPoolAddStr(strpool **pp, const char *s) { - strpool *elem; - if (!(elem = (strpool*)malloc(sizeof(strpool)))) - return false; - if (!(elem->str = strdup(s))) - { - free(elem); - return false; - } - oom = false; - HASH_ADD_KEYPTR( hh, *pp, elem->str, strlen(elem->str), elem ); - if (oom) - { - free(elem->str); - free(elem); - return false; - } - return true; + strpool *elem; + if (!(elem = (strpool*)malloc(sizeof(strpool)))) + return false; + if (!(elem->str = strdup(s))) + { + free(elem); + return false; + } + oom = false; + HASH_ADD_KEYPTR(hh, *pp, elem->str, strlen(elem->str), elem); + if (oom) + { + free(elem->str); + free(elem); + return false; + } + return true; } // for not zero terminated strings -bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen) +bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen) { - strpool *elem; - if (!(elem = (strpool*)malloc(sizeof(strpool)))) - return false; - if (!(elem->str = malloc(slen+1))) - { - free(elem); - return false; - } - memcpy(elem->str,s,slen); - elem->str[slen]=0; - oom = false; - HASH_ADD_KEYPTR( hh, *pp, elem->str, strlen(elem->str), elem ); - if (oom) - { - free(elem->str); - free(elem); - return false; - } - return true; + strpool *elem; + if (!(elem = (strpool*)malloc(sizeof(strpool)))) + return false; + if (!(elem->str = malloc(slen + 1))) + { + free(elem); + return false; + } + memcpy(elem->str, s, slen); + elem->str[slen] = 0; + oom = false; + HASH_ADD_KEYPTR(hh, *pp, elem->str, strlen(elem->str), elem); + if (oom) + { + free(elem->str); + free(elem); + return false; + } + return true; } -bool StrPoolCheckStr(strpool *p,const char *s) +bool StrPoolCheckStr(strpool *p, const char *s) { - strpool *elem; - HASH_FIND_STR( p, s, elem); - return elem!=NULL; + strpool *elem; + HASH_FIND_STR(p, s, elem); + return elem != NULL; } void StrPoolDestroy(strpool **p) { - strpool *elem,*tmp; - HASH_ITER(hh, *p, elem, tmp) { - free(elem->str); - HASH_DEL(*p, elem); - free(elem); - } - *p = NULL; + strpool *elem, *tmp; + HASH_ITER(hh, *p, elem, tmp) { + free(elem->str); + HASH_DEL(*p, elem); + free(elem); + } + *p = NULL; }