nfqws: dpi-desync-repeats

This commit is contained in:
bol-van 2020-03-18 15:38:15 +03:00
parent 35ec175b54
commit b7a9442723
14 changed files with 93 additions and 70 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -132,6 +132,7 @@ It takes the following parameters:
--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-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-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

View File

@ -173,6 +173,7 @@ nfqws
--dpi-desync-ttl=<int> ; установить 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=<N> ; посылать каждый генерируемый в 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=по всем непустым пакетам данных

View File

@ -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
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,
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;

View File

@ -257,6 +257,7 @@ static void exithelp()
" --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-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-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(&params.hostlist, optarg))
exit_clean(1);
strncpy(params.hostfile,optarg,sizeof(params.hostfile));

View File

@ -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;

View File

@ -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;
}