nfqws: ipfrag1 desync mode

This commit is contained in:
bol-van 2022-02-05 15:41:46 +03:00
parent 190b4e367f
commit 4aef7a96a4
5 changed files with 61 additions and 19 deletions

View File

@ -205,7 +205,11 @@ bool prepare_tcp_segment6(
{ {
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor); uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len; 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) + 8*!!(fooling & FOOL_DESTOPT); uint16_t ip_payload_len = transport_payload_len +
8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) +
16*!!(fooling & FOOL_HOPBYHOP2) +
8*!!(fooling & FOOL_DESTOPT) +
8*!!(fooling & FOOL_IPFRAG1);
uint16_t pktlen = sizeof(struct ip6_hdr) + ip_payload_len; uint16_t pktlen = sizeof(struct ip6_hdr) + ip_payload_len;
if (pktlen>*buflen) return false; if (pktlen>*buflen) return false;
@ -227,7 +231,7 @@ bool prepare_tcp_segment6(
} }
hbh->ip6h_nxt = IPPROTO_TCP; hbh->ip6h_nxt = IPPROTO_TCP;
nexttype = &hbh->ip6h_nxt; nexttype = &hbh->ip6h_nxt;
proto = 0; // hop by hop options proto = IPPROTO_HOPOPTS;
} }
if (fooling & FOOL_DESTOPT) if (fooling & FOOL_DESTOPT)
{ {
@ -236,9 +240,23 @@ bool prepare_tcp_segment6(
memset(dest,0,8); memset(dest,0,8);
dest->ip6d_nxt = IPPROTO_TCP; dest->ip6d_nxt = IPPROTO_TCP;
if (nexttype) if (nexttype)
*nexttype = 60; // destination options *nexttype = IPPROTO_DSTOPTS;
else else
proto = 60; proto = IPPROTO_DSTOPTS;
nexttype = &dest->ip6d_nxt;
}
if (fooling & FOOL_IPFRAG1)
{
struct ip6_frag *frag = (struct ip6_frag*)tcp;
tcp = (struct tcphdr*)((uint8_t*)tcp+sizeof(struct ip6_frag));
frag->ip6f_nxt = IPPROTO_TCP;
frag->ip6f_ident = htonl(1+random()%0xFFFFFFFF);
frag->ip6f_reserved = 0;
frag->ip6f_offlg = 0;
if (nexttype)
*nexttype = IPPROTO_FRAGMENT;
else
proto = IPPROTO_FRAGMENT;
} }
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen; uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
@ -309,7 +327,11 @@ bool prepare_udp_segment6(
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
uint16_t transport_payload_len = sizeof(struct udphdr) + len; 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) + 8*!!(fooling & FOOL_DESTOPT) ; uint16_t ip_payload_len = transport_payload_len +
8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) +
16*!!(fooling & FOOL_HOPBYHOP2) +
8*!!(fooling & FOOL_DESTOPT) +
8*!!(fooling & FOOL_IPFRAG1);
uint16_t pktlen = sizeof(struct ip6_hdr) + ip_payload_len; uint16_t pktlen = sizeof(struct ip6_hdr) + ip_payload_len;
if (pktlen>*buflen) return false; if (pktlen>*buflen) return false;
@ -331,7 +353,7 @@ bool prepare_udp_segment6(
} }
hbh->ip6h_nxt = IPPROTO_UDP; hbh->ip6h_nxt = IPPROTO_UDP;
nexttype = &hbh->ip6h_nxt; nexttype = &hbh->ip6h_nxt;
proto = 0; // hop by hop options proto = IPPROTO_HOPOPTS;
} }
if (fooling & FOOL_DESTOPT) if (fooling & FOOL_DESTOPT)
{ {
@ -340,9 +362,23 @@ bool prepare_udp_segment6(
memset(dest,0,8); memset(dest,0,8);
dest->ip6d_nxt = IPPROTO_UDP; dest->ip6d_nxt = IPPROTO_UDP;
if (nexttype) if (nexttype)
*nexttype = 60; // destination options *nexttype = IPPROTO_DSTOPTS;
else else
proto = 60; proto = IPPROTO_DSTOPTS;
nexttype = &dest->ip6d_nxt;
}
if (fooling & FOOL_IPFRAG1)
{
struct ip6_frag *frag = (struct ip6_frag*)udp;
udp = (struct udphdr*)((uint8_t*)udp+sizeof(struct ip6_frag));
frag->ip6f_nxt = IPPROTO_UDP;
frag->ip6f_ident = htonl(1+random()%0xFFFFFFFF);
frag->ip6f_reserved = 0;
frag->ip6f_offlg = 0;
if (nexttype)
*nexttype = IPPROTO_FRAGMENT;
else
proto = IPPROTO_FRAGMENT;
} }
uint8_t *payload = (uint8_t*)(udp+1); uint8_t *payload = (uint8_t*)(udp+1);

View File

@ -23,6 +23,7 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
#define FOOL_HOPBYHOP 0x10 #define FOOL_HOPBYHOP 0x10
#define FOOL_HOPBYHOP2 0x20 #define FOOL_HOPBYHOP2 0x20
#define FOOL_DESTOPT 0x40 #define FOOL_DESTOPT 0x40
#define FOOL_IPFRAG1 0x80
#define SCALE_NONE ((uint8_t)-1) #define SCALE_NONE ((uint8_t)-1)

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) bool desync_valid_first_stage(enum dpi_desync_mode mode)
{ {
return mode==DESYNC_FAKE || mode==DESYNC_RST || mode==DESYNC_RSTACK || mode==DESYNC_HOPBYHOP || mode==DESYNC_DESTOPT; return mode==DESYNC_FAKE || mode==DESYNC_RST || mode==DESYNC_RSTACK || mode==DESYNC_HOPBYHOP || mode==DESYNC_DESTOPT || mode==DESYNC_IPFRAG1;
} }
bool desync_only_first_stage(enum dpi_desync_mode mode) bool desync_only_first_stage(enum dpi_desync_mode mode)
{ {
@ -103,6 +103,8 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
return DESYNC_HOPBYHOP; return DESYNC_HOPBYHOP;
else if (!strcmp(s,"destopt")) else if (!strcmp(s,"destopt"))
return DESYNC_DESTOPT; return DESYNC_DESTOPT;
else if (!strcmp(s,"ipfrag1"))
return DESYNC_IPFRAG1;
return DESYNC_INVALID; return DESYNC_INVALID;
} }
@ -389,7 +391,8 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
break; break;
case DESYNC_HOPBYHOP: case DESYNC_HOPBYHOP:
case DESYNC_DESTOPT: case DESYNC_DESTOPT:
fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : FOOL_DESTOPT; case DESYNC_IPFRAG1:
fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1;
if (ip6hdr && params.desync_mode2==DESYNC_NONE) 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, if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
@ -562,15 +565,15 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
size_t pkt_orig_len; size_t pkt_orig_len;
size_t ipfrag_pos = (params.desync_ipfrag_pos_tcp && params.desync_ipfrag_pos_tcp<len_tcp) ? params.desync_ipfrag_pos_tcp : 24; size_t ipfrag_pos = (params.desync_ipfrag_pos_tcp && params.desync_ipfrag_pos_tcp<len_tcp) ? params.desync_ipfrag_pos_tcp : 24;
uint32_t ident = ip ? ip->ip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()&0xFFFFFFFF); uint32_t ident = ip ? ip->ip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()%0xFFFFFFFF);
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
pkt2_len = sizeof(pkt2); pkt2_len = sizeof(pkt2);
if (ip6hdr && fooling_orig!=FOOL_NONE) if (ip6hdr && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT))
{ {
pkt_orig_len = sizeof(pkt3); pkt_orig_len = sizeof(pkt3);
if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? 0 : 60, data_pkt, len_pkt, pkt3, &pkt_orig_len)) if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, data_pkt, len_pkt, pkt3, &pkt_orig_len))
return res; return res;
pkt_orig = pkt3; pkt_orig = pkt3;
} }
@ -690,7 +693,8 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
break; break;
case DESYNC_HOPBYHOP: case DESYNC_HOPBYHOP:
case DESYNC_DESTOPT: case DESYNC_DESTOPT:
fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : FOOL_DESTOPT; case DESYNC_IPFRAG1:
fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1;
if (ip6hdr && params.desync_mode2==DESYNC_NONE) if (ip6hdr && params.desync_mode2==DESYNC_NONE)
{ {
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
@ -750,15 +754,15 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
size_t len_transport = len_payload + sizeof(struct udphdr); size_t len_transport = len_payload + sizeof(struct udphdr);
size_t ipfrag_pos = (params.desync_ipfrag_pos_udp && params.desync_ipfrag_pos_udp<len_transport) ? params.desync_ipfrag_pos_udp : sizeof(struct udphdr); size_t ipfrag_pos = (params.desync_ipfrag_pos_udp && params.desync_ipfrag_pos_udp<len_transport) ? params.desync_ipfrag_pos_udp : sizeof(struct udphdr);
// freebsd do not set ip.id // freebsd do not set ip.id
uint32_t ident = ip ? ip->ip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()&0xFFFFFFFF); uint32_t ident = ip ? ip->ip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()%0xFFFFFFFF);
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
pkt2_len = sizeof(pkt2); pkt2_len = sizeof(pkt2);
if (ip6hdr && fooling_orig!=FOOL_NONE) if (ip6hdr && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT))
{ {
pkt_orig_len = sizeof(pkt3); pkt_orig_len = sizeof(pkt3);
if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? 0 : 60, data_pkt, len_pkt, pkt3, &pkt_orig_len)) if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, data_pkt, len_pkt, pkt3, &pkt_orig_len))
return res; return res;
pkt_orig = pkt3; pkt_orig = pkt3;
} }

View File

@ -31,7 +31,8 @@ enum dpi_desync_mode {
DESYNC_SPLIT2, DESYNC_SPLIT2,
DESYNC_IPFRAG2, DESYNC_IPFRAG2,
DESYNC_HOPBYHOP, DESYNC_HOPBYHOP,
DESYNC_DESTOPT DESYNC_DESTOPT,
DESYNC_IPFRAG1
}; };
extern const char *fake_http_request_default; 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" " --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" " --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" " --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 destopt disorder disorder2 split split2 ipfrag2\n" " --dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2\n"
#ifdef __linux__ #ifdef __linux__
" --dpi-desync-fwmark=<int|0xHEX>\t; override fwmark for desync packet. default = 0x%08X (%u)\n" " --dpi-desync-fwmark=<int|0xHEX>\t; override fwmark for desync packet. default = 0x%08X (%u)\n"
#elif defined(SO_USER_COOKIE) #elif defined(SO_USER_COOKIE)