Browse Source

nfqws: dpi-desync-repeats

pull/53/head
bol-van 6 years ago
parent
commit
b7a9442723
  1. BIN
      binaries/aarch64/nfqws
  2. BIN
      binaries/armhf/nfqws
  3. BIN
      binaries/mips32r1-lsb/nfqws
  4. BIN
      binaries/mips32r1-msb/nfqws
  5. BIN
      binaries/mips64r2-msb/nfqws
  6. BIN
      binaries/ppc/nfqws
  7. BIN
      binaries/x86/nfqws
  8. BIN
      binaries/x86_64/nfqws
  9. 1
      docs/readme.eng.txt
  10. 1
      docs/readme.txt
  11. 30
      nfq/desync.c
  12. 27
      nfq/nfqws.c
  13. 2
      nfq/params.h
  14. 102
      nfq/strpool.c

BIN
binaries/aarch64/nfqws

Binary file not shown.

BIN
binaries/armhf/nfqws

Binary file not shown.

BIN
binaries/mips32r1-lsb/nfqws

Binary file not shown.

BIN
binaries/mips32r1-msb/nfqws

Binary file not shown.

BIN
binaries/mips64r2-msb/nfqws

Binary file not shown.

BIN
binaries/ppc/nfqws

Binary file not shown.

BIN
binaries/x86/nfqws

Binary file not shown.

BIN
binaries/x86_64/nfqws

Binary file not shown.

1
docs/readme.eng.txt

@ -132,6 +132,7 @@ It takes the following parameters:
--dpi-desync-ttl=<int> ; set ttl for desync packet --dpi-desync-ttl=<int> ; set ttl for desync packet
--dpi-desync-fooling=none|md5sig|ts|badseq|badsum ; can take multiple comma separated values --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-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=<N> ; 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-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-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 --dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet

1
docs/readme.txt

@ -173,6 +173,7 @@ nfqws
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов --dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
--dpi-desync-fooling=none|md5sig|ts|badseq|badsum ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера --dpi-desync-fooling=none|md5sig|ts|badseq|badsum ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера
--dpi-desync-retrans=0|1 ; (только для fake,rst,rstack) 0(default)=отправлять оригинал следом за фейком 1=дропать оригинал, заставляя ОС выполнять ретрансмиссию через 0.2 сек --dpi-desync-retrans=0|1 ; (только для fake,rst,rstack) 0(default)=отправлять оригинал следом за фейком 1=дропать оригинал, заставляя ОС выполнять ретрансмиссию через 0.2 сек
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI --dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
--dpi-desync-split-pos=<1..1500> ; (только для disorder) разбивать пакет на указанной позиции --dpi-desync-split-pos=<1..1500> ; (только для disorder) разбивать пакет на указанной позиции
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных --dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных

30
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;i<params.desync_repeats;i++)
if (!rawsend(dst,fwmark,data,len))
return false;
return true;
}
// result : true - drop original packet, false = dont drop // result : true - drop original packet, false = dont drop
packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struct iphdr *iphdr, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, size_t len_tcp, uint8_t *data_payload, size_t len_payload) packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struct iphdr *iphdr, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, size_t len_tcp, uint8_t *data_payload, size_t len_payload)
{ {
@ -182,7 +192,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, 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, ttl_orig,TCP_FOOL_NONE,
data_payload+split_pos, len_payload-split_pos, newdata, &newlen) || 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; 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, 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, ttl_fake,params.desync_tcp_fooling_mode,
zeropkt, split_pos, fakeseg, &fakeseg_len) || 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; 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, 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, ttl_orig,TCP_FOOL_NONE,
data_payload, split_pos, newdata, &newlen) || 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; 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) 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) 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; 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, 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, ttl_fake,params.desync_tcp_fooling_mode,
zeropkt, split_pos, fakeseg, &fakeseg_len) || 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; 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, 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, ttl_orig,TCP_FOOL_NONE,
data_payload, split_pos, newdata, &newlen) || 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; 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) if (params.desync_mode==DESYNC_SPLIT)
{ {
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos) 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; 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, 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, ttl_orig,TCP_FOOL_NONE,
data_payload+split_pos, len_payload-split_pos, newdata, &newlen) || 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; return res;
} }
@ -299,7 +309,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
return res; 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; return res;
if (params.desync_retrans) 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) 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 original packet was tampered earlier it needs checksum fixed
if (res==modify) tcp_fix_checksum(tcphdr,len_tcp,iphdr,ip6hdr); 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 res;
} }
return drop; return drop;

27
nfq/nfqws.c

@ -257,6 +257,7 @@ static void exithelp()
" --dpi-desync-ttl=<int>\t\t\t; set ttl for desync packet\n" " --dpi-desync-ttl=<int>\t\t\t; set ttl for desync packet\n"
" --dpi-desync-fooling=<mode>[,<mode>]\t; can use multiple comma separated values. modes : none md5sig ts badseq badsum\n" " --dpi-desync-fooling=<mode>[,<mode>]\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-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=<N>\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-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-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" " --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_fwmark = DPI_DESYNC_FWMARK_DEFAULT;
params.desync_skip_nosni = true; params.desync_skip_nosni = true;
params.desync_split_pos = 3; params.desync_split_pos = 3;
params.desync_repeats = 1;
const struct option long_options[] = { const struct option long_options[] = {
{"debug",optional_argument,0,0}, // optidx=0 {"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-ttl",required_argument,0,0}, // optidx=12
{"dpi-desync-fooling",required_argument,0,0}, // optidx=13 {"dpi-desync-fooling",required_argument,0,0}, // optidx=13
{"dpi-desync-retrans",optional_argument,0,0}, // optidx=14 {"dpi-desync-retrans",optional_argument,0,0}, // optidx=14
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=15 {"dpi-desync-repeats",required_argument,0,0}, // optidx=15
{"dpi-desync-split-pos",required_argument,0,0},// optidx=16 {"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=16
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=17 {"dpi-desync-split-pos",required_argument,0,0},// optidx=17
{"hostlist",required_argument,0,0}, // optidx=18 {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=18
{"hostlist",required_argument,0,0}, // optidx=19
{NULL,0,NULL,0} {NULL,0,NULL,0}
}; };
if (argc < 2) exithelp(); if (argc < 2) exithelp();
@ -460,10 +463,18 @@ int main(int argc, char **argv)
case 14: /* dpi-desync-retrans */ case 14: /* dpi-desync-retrans */
params.desync_retrans = !optarg || atoi(optarg); params.desync_retrans = !optarg || atoi(optarg);
break; 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); params.desync_skip_nosni = !optarg || atoi(optarg);
break; break;
case 16: /* dpi-desync-split-pos */ case 17: /* dpi-desync-split-pos */
params.desync_split_pos = atoi(optarg); params.desync_split_pos = atoi(optarg);
if (params.desync_split_pos<1 || params.desync_split_pos>DPI_DESYNC_MAX_FAKE_LEN) 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); exit_clean(1);
} }
break; break;
case 17: /* dpi-desync-any-protocol */ case 18: /* dpi-desync-any-protocol */
params.desync_any_proto = !optarg || atoi(optarg); params.desync_any_proto = !optarg || atoi(optarg);
break; break;
case 18: /* hostlist */ case 19: /* hostlist */
if (!LoadHostList(&params.hostlist, optarg)) if (!LoadHostList(&params.hostlist, optarg))
exit_clean(1); exit_clean(1);
strncpy(params.hostfile,optarg,sizeof(params.hostfile)); strncpy(params.hostfile,optarg,sizeof(params.hostfile));

2
nfq/params.h

@ -19,7 +19,7 @@ struct params_s
char hostspell[4]; char hostspell[4];
enum dpi_desync_mode desync_mode; enum dpi_desync_mode desync_mode;
bool desync_retrans,desync_skip_nosni,desync_any_proto; 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_ttl;
uint8_t desync_tcp_fooling_mode; uint8_t desync_tcp_fooling_mode;
uint32_t desync_fwmark; uint32_t desync_fwmark;

102
nfq/strpool.c

@ -6,71 +6,71 @@
#undef uthash_nonfatal_oom #undef uthash_nonfatal_oom
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt) #define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
static bool oom=false; static bool oom = false;
static void ut_oom_recover(strpool *elem) static void ut_oom_recover(strpool *elem)
{ {
oom=true; oom = true;
} }
// for zero terminated strings // for zero terminated strings
bool StrPoolAddStr(strpool **pp,const char *s) bool StrPoolAddStr(strpool **pp, const char *s)
{ {
strpool *elem; strpool *elem;
if (!(elem = (strpool*)malloc(sizeof(strpool)))) if (!(elem = (strpool*)malloc(sizeof(strpool))))
return false; return false;
if (!(elem->str = strdup(s))) if (!(elem->str = strdup(s)))
{ {
free(elem); free(elem);
return false; return false;
} }
oom = false; oom = false;
HASH_ADD_KEYPTR( hh, *pp, elem->str, strlen(elem->str), elem ); HASH_ADD_KEYPTR(hh, *pp, elem->str, strlen(elem->str), elem);
if (oom) if (oom)
{ {
free(elem->str); free(elem->str);
free(elem); free(elem);
return false; return false;
} }
return true; return true;
} }
// for not zero terminated strings // 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; strpool *elem;
if (!(elem = (strpool*)malloc(sizeof(strpool)))) if (!(elem = (strpool*)malloc(sizeof(strpool))))
return false; return false;
if (!(elem->str = malloc(slen+1))) if (!(elem->str = malloc(slen + 1)))
{ {
free(elem); free(elem);
return false; return false;
} }
memcpy(elem->str,s,slen); memcpy(elem->str, s, slen);
elem->str[slen]=0; elem->str[slen] = 0;
oom = false; oom = false;
HASH_ADD_KEYPTR( hh, *pp, elem->str, strlen(elem->str), elem ); HASH_ADD_KEYPTR(hh, *pp, elem->str, strlen(elem->str), elem);
if (oom) if (oom)
{ {
free(elem->str); free(elem->str);
free(elem); free(elem);
return false; return false;
} }
return true; return true;
} }
bool StrPoolCheckStr(strpool *p,const char *s) bool StrPoolCheckStr(strpool *p, const char *s)
{ {
strpool *elem; strpool *elem;
HASH_FIND_STR( p, s, elem); HASH_FIND_STR(p, s, elem);
return elem!=NULL; return elem != NULL;
} }
void StrPoolDestroy(strpool **p) void StrPoolDestroy(strpool **p)
{ {
strpool *elem,*tmp; strpool *elem, *tmp;
HASH_ITER(hh, *p, elem, tmp) { HASH_ITER(hh, *p, elem, tmp) {
free(elem->str); free(elem->str);
HASH_DEL(*p, elem); HASH_DEL(*p, elem);
free(elem); free(elem);
} }
*p = NULL; *p = NULL;
} }

Loading…
Cancel
Save