mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
nfqws: ipv6 fragment at transport header
This commit is contained in:
@@ -346,42 +346,50 @@ bool ip_frag6(
|
||||
uint8_t *pkt1, size_t *pkt1_size,
|
||||
uint8_t *pkt2, size_t *pkt2_size)
|
||||
{
|
||||
uint16_t payload_len;
|
||||
size_t payload_len, unfragmentable;
|
||||
uint8_t *last_header_type;
|
||||
uint8_t proto;
|
||||
struct ip6_frag *frag;
|
||||
const uint8_t *payload;
|
||||
|
||||
if (frag_pos & 7 || pkt_size < sizeof(struct ip6_hdr)) return false;
|
||||
payload_len = htons(((struct ip6_hdr*)pkt)->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
if ((sizeof(struct ip6_hdr)+payload_len)>pkt_size || frag_pos>=payload_len ||
|
||||
*pkt1_size<(sizeof(struct ip6_hdr)+sizeof(struct ip6_frag)+frag_pos) ||
|
||||
*pkt2_size<(sizeof(struct ip6_hdr)+sizeof(struct ip6_frag)+payload_len-frag_pos))
|
||||
payload_len = sizeof(struct ip6_hdr) + htons(((struct ip6_hdr*)pkt)->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
if (pkt_size < payload_len) return false;
|
||||
|
||||
payload = pkt;
|
||||
proto_skip_ipv6((uint8_t**)&payload, &payload_len, &proto, &last_header_type);
|
||||
unfragmentable = payload - pkt;
|
||||
|
||||
//printf("pkt_size=%zu FRAG_POS=%zu payload_len=%zu unfragmentable=%zu dh=%zu\n",pkt_size,frag_pos,payload_len,unfragmentable,last_header_type - pkt);
|
||||
|
||||
if (frag_pos>=payload_len ||
|
||||
*pkt1_size<(unfragmentable + sizeof(struct ip6_frag) + frag_pos) ||
|
||||
*pkt2_size<(unfragmentable + sizeof(struct ip6_frag) + payload_len - frag_pos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
proto = ((struct ip6_hdr*)pkt)->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||
|
||||
memcpy(pkt1, pkt, sizeof(struct ip6_hdr));
|
||||
((struct ip6_hdr*)pkt1)->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct ip6_frag)+frag_pos);
|
||||
((struct ip6_hdr*)pkt1)->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_FRAGMENT;
|
||||
frag = (struct ip6_frag*)(((struct ip6_hdr*)pkt1)+1);
|
||||
memcpy(pkt1, pkt, unfragmentable);
|
||||
((struct ip6_hdr*)pkt1)->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(unfragmentable - sizeof(struct ip6_hdr) + sizeof(struct ip6_frag) + frag_pos);
|
||||
pkt1[last_header_type - pkt] = IPPROTO_FRAGMENT;
|
||||
frag = (struct ip6_frag*)(pkt1 + unfragmentable);
|
||||
frag->ip6f_nxt = proto;
|
||||
frag->ip6f_reserved = 0;
|
||||
frag->ip6f_offlg = IP6F_MORE_FRAG;
|
||||
frag->ip6f_ident = ident;
|
||||
memcpy(frag+1, pkt+sizeof(struct ip6_hdr), frag_pos);
|
||||
*pkt1_size = sizeof(struct ip6_hdr)+sizeof(struct ip6_frag)+frag_pos;
|
||||
memcpy(frag+1, pkt + unfragmentable, frag_pos);
|
||||
*pkt1_size = unfragmentable + sizeof(struct ip6_frag) + frag_pos;
|
||||
|
||||
memcpy(pkt2, pkt, sizeof(struct ip6_hdr));
|
||||
((struct ip6_hdr*)pkt2)->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct ip6_frag)+payload_len-frag_pos);
|
||||
((struct ip6_hdr*)pkt2)->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_FRAGMENT;
|
||||
frag = (struct ip6_frag*)(((struct ip6_hdr*)pkt2)+1);
|
||||
((struct ip6_hdr*)pkt2)->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(unfragmentable - sizeof(struct ip6_hdr) + sizeof(struct ip6_frag) + payload_len - frag_pos);
|
||||
pkt2[last_header_type - pkt] = IPPROTO_FRAGMENT;
|
||||
frag = (struct ip6_frag*)(pkt2 + unfragmentable);
|
||||
frag->ip6f_nxt = proto;
|
||||
frag->ip6f_reserved = 0;
|
||||
frag->ip6f_offlg = htons(frag_pos);
|
||||
frag->ip6f_ident = ident;
|
||||
memcpy(frag+1, pkt+sizeof(struct ip6_hdr)+frag_pos, payload_len-frag_pos);
|
||||
*pkt2_size = sizeof(struct ip6_hdr)+sizeof(struct ip6_frag)+payload_len-frag_pos;
|
||||
memcpy(frag+1, pkt + unfragmentable + frag_pos, payload_len - frag_pos);
|
||||
*pkt2_size = unfragmentable + sizeof(struct ip6_frag) + payload_len - frag_pos;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -619,7 +627,7 @@ bool proto_check_ipv6(const uint8_t *data, size_t len)
|
||||
}
|
||||
// move to transport protocol
|
||||
// proto_type = 0 => error
|
||||
void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type)
|
||||
void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t **last_header_type)
|
||||
{
|
||||
size_t hdrlen;
|
||||
uint8_t HeaderType;
|
||||
@@ -627,6 +635,7 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type)
|
||||
if (proto_type) *proto_type = 0; // put error in advance
|
||||
|
||||
HeaderType = (*data)[6]; // NextHeader field
|
||||
if (last_header_type) *last_header_type = (*data)+6;
|
||||
*data += 40; *len -= 40; // skip ipv6 base header
|
||||
while (*len > 0) // need at least one byte for NextHeader field
|
||||
{
|
||||
@@ -654,6 +663,7 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type)
|
||||
}
|
||||
if (*len < hdrlen) return; // error
|
||||
HeaderType = **data;
|
||||
if (last_header_type) *last_header_type = *data;
|
||||
// advance to the next header location
|
||||
*len -= hdrlen;
|
||||
*data += hdrlen;
|
||||
|
@@ -125,7 +125,7 @@ void print_udphdr(const struct udphdr *udphdr);
|
||||
bool proto_check_ipv4(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv4(uint8_t **data, size_t *len);
|
||||
bool proto_check_ipv6(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type);
|
||||
void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t **last_header_type);
|
||||
bool proto_check_tcp(const uint8_t *data, size_t len);
|
||||
void proto_skip_tcp(uint8_t **data, size_t *len);
|
||||
bool proto_check_udp(const uint8_t *data, size_t len);
|
||||
|
@@ -115,7 +115,7 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt
|
||||
else if (proto_check_ipv6(data, len))
|
||||
{
|
||||
ip6hdr = (struct ip6_hdr *) data;
|
||||
proto_skip_ipv6(&data, &len, &proto);
|
||||
proto_skip_ipv6(&data, &len, &proto, NULL);
|
||||
if (params.debug)
|
||||
{
|
||||
printf("IP6: ");
|
||||
@@ -520,8 +520,8 @@ static void exithelp()
|
||||
" --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; data payload split position\n"
|
||||
" --dpi-desync-ipfrag-pos-tcp=<8..%u>\t; ip frag position starting from the second header (usually transport header). multiple of 8, default %u.\n"
|
||||
" --dpi-desync-ipfrag-pos-udp=<8..%u>\t; ip frag position starting from the second header (usually transport header). multiple of 8, default %u.\n"
|
||||
" --dpi-desync-ipfrag-pos-tcp=<8..%u>\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
||||
" --dpi-desync-ipfrag-pos-udp=<8..%u>\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
||||
" --dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default %d\n"
|
||||
" --dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default %d\n"
|
||||
" --dpi-desync-any-protocol=0|1\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n"
|
||||
|
Reference in New Issue
Block a user