nfqws: destopt desync mode

This commit is contained in:
bol-van
2022-02-05 13:36:03 +03:00
parent 3ee381aff6
commit 6151afe727
17 changed files with 62 additions and 35 deletions

View File

@@ -205,13 +205,13 @@ 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);
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 pktlen = sizeof(struct ip6_hdr) + ip_payload_len;
if (pktlen>*buflen) return false;
struct ip6_hdr *ip6 = (struct ip6_hdr*)buf;
struct tcphdr *tcp = (struct tcphdr*)(ip6+1);
uint8_t proto;
uint8_t proto = IPPROTO_TCP, *nexttype = NULL;
if (fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))
{
@@ -226,10 +226,20 @@ bool prepare_tcp_segment6(
memset(hbh,0,8);
}
hbh->ip6h_nxt = IPPROTO_TCP;
nexttype = &hbh->ip6h_nxt;
proto = 0; // hop by hop options
}
else
proto = IPPROTO_TCP;
if (fooling & FOOL_DESTOPT)
{
struct ip6_dest *dest = (struct ip6_dest*)tcp;
tcp = (struct tcphdr*)((uint8_t*)tcp+8);
memset(dest,0,8);
dest->ip6d_nxt = IPPROTO_TCP;
if (nexttype)
*nexttype = 60; // destination options
else
proto = 60;
}
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
@@ -299,13 +309,13 @@ 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);
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 pktlen = sizeof(struct ip6_hdr) + ip_payload_len;
if (pktlen>*buflen) return false;
struct ip6_hdr *ip6 = (struct ip6_hdr*)buf;
struct udphdr *udp = (struct udphdr*)(ip6+1);
uint8_t proto;
uint8_t proto = IPPROTO_UDP, *nexttype = NULL;
if (fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))
{
@@ -320,10 +330,21 @@ bool prepare_udp_segment6(
memset(hbh,0,8);
}
hbh->ip6h_nxt = IPPROTO_UDP;
nexttype = &hbh->ip6h_nxt;
proto = 0; // hop by hop options
}
else
proto = IPPROTO_UDP;
if (fooling & FOOL_DESTOPT)
{
struct ip6_dest *dest = (struct ip6_dest*)udp;
udp = (struct udphdr*)((uint8_t*)udp+8);
memset(dest,0,8);
dest->ip6d_nxt = IPPROTO_UDP;
if (nexttype)
*nexttype = 60; // destination options
else
proto = 60;
}
uint8_t *payload = (uint8_t*)(udp+1);
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl);
@@ -350,17 +371,17 @@ bool prepare_udp_segment(
false;
}
bool ip6_insert_hopbyhop(uint8_t *data_pkt, size_t len_pkt, uint8_t *buf, size_t *buflen)
bool ip6_insert_simple_hdr(uint8_t type, uint8_t *data_pkt, size_t len_pkt, uint8_t *buf, size_t *buflen)
{
if ((len_pkt+8)<=*buflen && len_pkt>=sizeof(struct ip6_hdr))
{
struct ip6_hdr *ip6 = (struct ip6_hdr *)buf;
struct ip6_hbh *hbh = (struct ip6_hbh*)(ip6+1);
struct ip6_ext *hbh = (struct ip6_ext*)(ip6+1);
*ip6 = *(struct ip6_hdr*)data_pkt;
memset(hbh,0,8);
memcpy((uint8_t*)hbh+8, data_pkt+sizeof(struct ip6_hdr), len_pkt-sizeof(struct ip6_hdr));
hbh->ip6h_nxt = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt = 0;
hbh->ip6e_nxt = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt = type;
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = net16_add(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen, 8);
*buflen = len_pkt + 8;
return true;

View File

@@ -22,6 +22,7 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
#define FOOL_BADSEQ 0x08
#define FOOL_HOPBYHOP 0x10
#define FOOL_HOPBYHOP2 0x20
#define FOOL_DESTOPT 0x40
#define SCALE_NONE ((uint8_t)-1)
@@ -86,7 +87,7 @@ bool prepare_udp_segment(
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen);
bool ip6_insert_hopbyhop(uint8_t *data_pkt, size_t len_pkt, uint8_t *buf, size_t *buflen);
bool ip6_insert_simple_hdr(uint8_t type, uint8_t *data_pkt, size_t len_pkt, uint8_t *buf, size_t *buflen);
// ipv4: ident==-1 - copy ip_id from original ipv4 packet
bool ip_frag4(

View File

@@ -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;
return mode==DESYNC_FAKE || mode==DESYNC_RST || mode==DESYNC_RSTACK || mode==DESYNC_HOPBYHOP || mode==DESYNC_DESTOPT;
}
bool desync_only_first_stage(enum dpi_desync_mode mode)
{
@@ -101,6 +101,8 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
return DESYNC_IPFRAG2;
else if (!strcmp(s,"hopbyhop"))
return DESYNC_HOPBYHOP;
else if (!strcmp(s,"destopt"))
return DESYNC_DESTOPT;
return DESYNC_INVALID;
}
@@ -386,21 +388,22 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
b = true;
break;
case DESYNC_HOPBYHOP:
case DESYNC_DESTOPT:
fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : FOOL_DESTOPT;
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,
ttl_orig,FOOL_HOPBYHOP,0,0,
ttl_orig,fooling_orig,0,0,
data_payload, len_payload, pkt1, &pkt1_len))
{
return res;
}
DLOG("resending original packet with hop-by-hop options\n");
DLOG("resending original packet with extension header\n");
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
return res;
// this mode is final, no other options available
return drop;
}
fooling_orig = FOOL_HOPBYHOP;
desync_mode = params.desync_mode2;
}
@@ -564,10 +567,10 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
pkt1_len = sizeof(pkt1);
pkt2_len = sizeof(pkt2);
if (ip6hdr && fooling_orig==FOOL_HOPBYHOP)
if (ip6hdr && fooling_orig!=FOOL_NONE)
{
pkt_orig_len = sizeof(pkt3);
if (!ip6_insert_hopbyhop(data_pkt, len_pkt, pkt3, &pkt_orig_len))
if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? 0 : 60, data_pkt, len_pkt, pkt3, &pkt_orig_len))
return res;
pkt_orig = pkt3;
}
@@ -686,21 +689,22 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
b = true;
break;
case DESYNC_HOPBYHOP:
case DESYNC_DESTOPT:
fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : FOOL_DESTOPT;
if (ip6hdr && params.desync_mode2==DESYNC_NONE)
{
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
ttl_orig,FOOL_HOPBYHOP,
ttl_orig,fooling_orig,
data_payload, len_payload, pkt1, &pkt1_len))
{
return res;
}
DLOG("resending original packet with hop-by-hop options\n");
DLOG("resending original packet with extension header\n");
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
return res;
// this mode is final, no other options available
return drop;
}
fooling_orig = FOOL_HOPBYHOP;
desync_mode = params.desync_mode2;
}
@@ -751,10 +755,10 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
pkt1_len = sizeof(pkt1);
pkt2_len = sizeof(pkt2);
if (ip6hdr && fooling_orig==FOOL_HOPBYHOP)
if (ip6hdr && fooling_orig!=FOOL_NONE)
{
pkt_orig_len = sizeof(pkt3);
if (!ip6_insert_hopbyhop(data_pkt, len_pkt, pkt3, &pkt_orig_len))
if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? 0 : 60, data_pkt, len_pkt, pkt3, &pkt_orig_len))
return res;
pkt_orig = pkt3;
}

View File

@@ -30,7 +30,8 @@ enum dpi_desync_mode {
DESYNC_SPLIT,
DESYNC_SPLIT2,
DESYNC_IPFRAG2,
DESYNC_HOPBYHOP
DESYNC_HOPBYHOP,
DESYNC_DESTOPT
};
extern const char *fake_http_request_default;

View File

@@ -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=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake rst rstack hopbyhop disorder disorder2 split split2 ipfrag2\n"
" --dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake rst rstack hopbyhop destopt disorder disorder2 split split2 ipfrag2\n"
#ifdef __linux__
" --dpi-desync-fwmark=<int|0xHEX>\t; override fwmark for desync packet. default = 0x%08X (%u)\n"
#elif defined(SO_USER_COOKIE)
@@ -870,7 +870,7 @@ int main(int argc, char **argv)
params.desync_fooling_mode |= FOOL_HOPBYHOP2;
else if (strcmp(p,"none"))
{
fprintf(stderr, "dpi-desync-fooling allowed values : none,md5sig,ts,badseq,badsum\n");
fprintf(stderr, "dpi-desync-fooling allowed values : none,md5sig,ts,badseq,badsum,hopbyhop,hopbyhop2\n");
exit_clean(1);
}
p = e;