nfqws: hop-by-hop ipv6 fooling and desync

This commit is contained in:
bol-van
2022-02-01 20:35:52 +03:00
parent 2c1871cc44
commit 427f16776c
9 changed files with 144 additions and 24 deletions

View File

@@ -200,19 +200,40 @@ bool prepare_tcp_segment6(
uint8_t *buf, size_t *buflen)
{
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
uint16_t ip_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);
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;
if (fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))
{
struct ip6_hbh *hbh = (struct ip6_hbh*)tcp;
tcp = (struct tcphdr*)((uint8_t*)tcp+8);
memset(hbh,0,8);
// extra HOPBYHOP header. standard violation
if (fooling & FOOL_HOPBYHOP2)
{
hbh = (struct ip6_hbh*)tcp;
tcp = (struct tcphdr*)((uint8_t*)tcp+8);
memset(hbh,0,8);
}
hbh->ip6h_nxt = IPPROTO_TCP;
proto = 0; // hop by hop options
}
else
proto = IPPROTO_TCP;
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, IPPROTO_TCP, ttl);
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl);
fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment);
memcpy(payload,data,len);
tcp6_fix_checksum(tcp,ip_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
*buflen = pktlen;
@@ -273,19 +294,39 @@ bool prepare_udp_segment6(
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen)
{
uint16_t ip_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);
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;
if (fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))
{
struct ip6_hbh *hbh = (struct ip6_hbh*)udp;
udp = (struct udphdr*)((uint8_t*)udp+8);
memset(hbh,0,8);
// extra HOPBYHOP header. standard violation
if (fooling & FOOL_HOPBYHOP2)
{
hbh = (struct ip6_hbh*)udp;
udp = (struct udphdr*)((uint8_t*)udp+8);
memset(hbh,0,8);
}
hbh->ip6h_nxt = IPPROTO_UDP;
proto = 0; // hop by hop options
}
else
proto = IPPROTO_UDP;
uint8_t *payload = (uint8_t*)(udp+1);
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, IPPROTO_UDP, ttl);
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl);
fill_udphdr(udp, src->sin6_port, dst->sin6_port, len);
memcpy(payload,data,len);
udp6_fix_checksum(udp,ip_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
*buflen = pktlen;

View File

@@ -14,11 +14,13 @@
// returns netorder value
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
#define FOOL_NONE 0
#define FOOL_MD5SIG 1
#define FOOL_BADSUM 2
#define FOOL_TS 4
#define FOOL_BADSEQ 8
#define FOOL_NONE 0x00
#define FOOL_MD5SIG 0x01
#define FOOL_BADSUM 0x02
#define FOOL_TS 0x04
#define FOOL_BADSEQ 0x08
#define FOOL_HOPBYHOP 0x10
#define FOOL_HOPBYHOP2 0x20
#define SCALE_NONE ((uint8_t)-1)

View File

@@ -67,7 +67,11 @@ 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;
return mode==DESYNC_FAKE || mode==DESYNC_RST || mode==DESYNC_RSTACK || mode==DESYNC_HOPBYHOP;
}
bool desync_only_first_stage(enum dpi_desync_mode mode)
{
return mode==DESYNC_HOPBYHOP;
}
bool desync_valid_second_stage(enum dpi_desync_mode mode)
{
@@ -95,6 +99,8 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
return DESYNC_SPLIT2;
else if (!strcmp(s,"ipfrag2"))
return DESYNC_IPFRAG2;
else if (!strcmp(s,"hopbyhop"))
return DESYNC_HOPBYHOP;
return DESYNC_INVALID;
}
@@ -378,6 +384,21 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
DLOG("sending fake RST/RSTACK\n");
b = true;
break;
case DESYNC_HOPBYHOP:
if (ip6hdr)
{
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,
data_payload, len_payload, pkt1, &pkt1_len))
{
return res;
}
DLOG("resending original packet with hop-by-hop options\n");
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
return res;
}
// this mode is final, no other options available
return drop;
}
if (b)
@@ -640,6 +661,21 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n")
b = true;
break;
case DESYNC_HOPBYHOP:
if (ip6hdr)
{
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
ttl_orig,FOOL_HOPBYHOP,
data_payload, len_payload, pkt1, &pkt1_len))
{
return res;
}
DLOG("resending original packet with hop-by-hop options\n");
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
return res;
}
// this mode is final, no other options available
return drop;
}
if (b)

View File

@@ -29,7 +29,8 @@ enum dpi_desync_mode {
DESYNC_DISORDER2,
DESYNC_SPLIT,
DESYNC_SPLIT2,
DESYNC_IPFRAG2
DESYNC_IPFRAG2,
DESYNC_HOPBYHOP
};
extern const char *fake_http_request_default;
@@ -38,6 +39,7 @@ extern const uint8_t fake_tls_clienthello_default[517];
enum dpi_desync_mode desync_mode_from_string(const char *s);
bool desync_valid_zero_stage(enum dpi_desync_mode mode);
bool desync_valid_first_stage(enum dpi_desync_mode mode);
bool desync_only_first_stage(enum dpi_desync_mode mode);
bool desync_valid_second_stage(enum dpi_desync_mode mode);
void desync_init();

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 disorder disorder2 split split2 ipfrag2\n"
" --dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake rst rstack hopbyhop 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)
@@ -513,7 +513,7 @@ static void exithelp()
#endif
" --dpi-desync-ttl=<int>\t\t\t; set ttl for desync packet\n"
" --dpi-desync-ttl6=<int>\t\t; set ipv6 hop limit for desync packet. by default ttl value is used.\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 hopbyhop hopbyhop2\n"
#ifdef __linux__
" --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"
#endif
@@ -810,7 +810,7 @@ int main(int argc, char **argv)
fprintf(stderr, "invalid desync combo : %s+%s+%s\n",mode,mode2,mode3);
exit_clean(1);
}
if (params.desync_mode2 && !(desync_valid_first_stage(params.desync_mode) && desync_valid_second_stage(params.desync_mode2)))
if (params.desync_mode2 && (desync_only_first_stage(params.desync_mode) || !(desync_valid_first_stage(params.desync_mode) && desync_valid_second_stage(params.desync_mode2))))
{
fprintf(stderr, "invalid desync combo : %s+%s\n", mode,mode2);
exit_clean(1);
@@ -864,6 +864,10 @@ int main(int argc, char **argv)
}
else if (!strcmp(p,"badseq"))
params.desync_fooling_mode |= FOOL_BADSEQ;
else if (!strcmp(p,"hopbyhop"))
params.desync_fooling_mode |= FOOL_HOPBYHOP;
else if (!strcmp(p,"hopbyhop2"))
params.desync_fooling_mode |= FOOL_HOPBYHOP2;
else if (strcmp(p,"none"))
{
fprintf(stderr, "dpi-desync-fooling allowed values : none,md5sig,ts,badseq,badsum\n");