nfqws: preserve tos and flow_label in ip4/ipv6 headers

This commit is contained in:
bol-van 2024-09-22 09:43:22 +03:00
parent cb6eed4f3c
commit 2e09dce5f0
12 changed files with 54 additions and 27 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.

Binary file not shown.

View File

@ -158,9 +158,9 @@ static void fill_udphdr(struct udphdr *udp, uint16_t nsport, uint16_t ndport, ui
udp->uh_sum = 0;
}
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl)
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl, uint8_t tos)
{
ip->ip_tos = 0;
ip->ip_tos = tos;
ip->ip_sum = 0;
ip->ip_off = 0;
ip->ip_v = 4;
@ -172,9 +172,9 @@ static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in
ip->ip_src = *src;
ip->ip_dst = *dst;
}
static void fill_ip6hdr(struct ip6_hdr *ip6, const struct in6_addr *src, const struct in6_addr *dst, uint16_t payloadlen, uint8_t proto, uint8_t ttl)
static void fill_ip6hdr(struct ip6_hdr *ip6, const struct in6_addr *src, const struct in6_addr *dst, uint16_t payloadlen, uint8_t proto, uint8_t ttl, uint32_t flow_label)
{
ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000);
ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(ntohl(flow_label) & 0x0FFFFFFF | 0x60000000);
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(payloadlen);
ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt = proto;
ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
@ -190,6 +190,7 @@ bool prepare_tcp_segment4(
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t tos,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@ -205,7 +206,7 @@ bool prepare_tcp_segment4(
struct tcphdr *tcp = (struct tcphdr*)(ip+1);
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl, tos);
fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len);
@ -224,6 +225,7 @@ bool prepare_tcp_segment6(
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint32_t flow_label,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@ -288,7 +290,7 @@ bool prepare_tcp_segment6(
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl);
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl, flow_label);
fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len);
@ -307,6 +309,7 @@ bool prepare_tcp_segment(
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t tos, uint32_t flow_label,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@ -314,9 +317,9 @@ bool prepare_tcp_segment(
uint8_t *buf, size_t *buflen)
{
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
false;
}
@ -325,6 +328,7 @@ bool prepare_tcp_segment(
bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t ttl,
uint8_t tos,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@ -348,7 +352,7 @@ bool prepare_udp_segment4(
uint8_t *payload = (uint8_t*)(udp+1);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl, tos);
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
memcpy(payload,data,len);
@ -365,6 +369,7 @@ bool prepare_udp_segment4(
bool prepare_udp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t ttl,
uint32_t flow_label,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@ -436,7 +441,7 @@ bool prepare_udp_segment6(
uint8_t *payload = (uint8_t*)(udp+1);
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl);
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl, flow_label);
fill_udphdr(udp, src->sin6_port, dst->sin6_port, datalen);
memcpy(payload,data,len);
@ -453,6 +458,7 @@ bool prepare_udp_segment6(
bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
uint8_t ttl,
uint8_t tos, uint32_t flow_label,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@ -460,9 +466,9 @@ bool prepare_udp_segment(
uint8_t *buf, size_t *buflen)
{
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,tos,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
false;
}

View File

@ -59,6 +59,9 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
#define VERDICT_MASK 3
#define VERDICT_NOCSUM 4
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
#define IP6_FLOW(ip6_header) (ip6_header ? ip6_header->ip6_ctlun.ip6_un1.ip6_un1_flow : 0)
// seq and wsize have network byte order
bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
@ -68,6 +71,7 @@ bool prepare_tcp_segment4(
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t tos,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@ -81,6 +85,7 @@ bool prepare_tcp_segment6(
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint32_t flow_label,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@ -94,6 +99,7 @@ bool prepare_tcp_segment(
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t tos, uint32_t flow_label,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@ -104,6 +110,7 @@ bool prepare_tcp_segment(
bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t ttl,
uint8_t tos,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@ -112,6 +119,7 @@ bool prepare_udp_segment4(
bool prepare_udp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t ttl,
uint32_t flow_label,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@ -120,6 +128,7 @@ bool prepare_udp_segment6(
bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
uint8_t ttl,
uint8_t tos, uint32_t flow_label,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,

View File

@ -755,7 +755,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_SYNACK:
pkt1_len = sizeof(pkt1);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN|TH_ACK, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
ttl_fake,dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_fake,IP4_TOS(ip),IP6_FLOW(ip6hdr),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
NULL, 0, pkt1, &pkt1_len))
{
return verdict;
@ -778,7 +779,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
pkt1_len = sizeof(pkt1);
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,0,0,0, dp->fake_syndata,dp->fake_syndata_size, pkt1,&pkt1_len))
ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr),
0,0,0, dp->fake_syndata,dp->fake_syndata_size, pkt1,&pkt1_len))
{
return verdict;
}
@ -1093,7 +1095,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_FAKE:
if (reasm_offset) break;
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_fake,dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_fake,IP4_TOS(ip),IP6_FLOW(ip6hdr),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
fake, fake_size, pkt1, &pkt1_len))
{
return verdict;
@ -1106,7 +1109,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_RSTACK:
if (reasm_offset) break;
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (desync_mode==DESYNC_RSTACK ? TH_ACK:0), tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
ttl_fake,dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_fake,IP4_TOS(ip),IP6_FLOW(ip6hdr),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
NULL, 0, pkt1, &pkt1_len))
{
return verdict;
@ -1123,7 +1127,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
(!split_pos && (desync_mode==DESYNC_SPLIT || desync_mode==DESYNC_SPLIT2 || desync_mode==DESYNC_DISORDER || desync_mode==DESYNC_DISORDER2))))
{
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,fooling_orig,0,0,
ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr),
fooling_orig,0,0,
data_payload, len_payload, pkt1, &pkt1_len))
{
return verdict;
@ -1191,7 +1196,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(net32_add(tcphdr->th_seq,split_pos),-dp->desync_seqovl), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
ttl_orig,fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
seg, seg_len, pkt1, &pkt1_len))
return verdict;
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ",split_pos,len_payload-1, len_payload-split_pos, dp->desync_seqovl);
@ -1205,7 +1211,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
{
seg_len = sizeof(fakeseg);
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_fake,dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_fake,IP4_TOS(ip),IP6_FLOW(ip6hdr),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
zeropkt, split_pos, fakeseg, &seg_len))
return verdict;
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
@ -1216,7 +1223,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
pkt1_len = sizeof(pkt1);
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,fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
data_payload, split_pos, pkt1, &pkt1_len))
return verdict;
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
@ -1246,7 +1254,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
{
fakeseg_len = sizeof(fakeseg);
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_fake,dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_fake,IP4_TOS(ip),IP6_FLOW(ip6hdr),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
zeropkt, split_pos, fakeseg, &fakeseg_len))
return verdict;
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
@ -1274,7 +1283,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->th_seq,-dp->desync_seqovl), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
ttl_orig,fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
seg, seg_len, pkt1, &pkt1_len))
return verdict;
DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ",split_pos-1, split_pos, dp->desync_seqovl);
@ -1293,7 +1303,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
{
pkt1_len = sizeof(pkt1);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->th_seq,split_pos), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
ttl_orig,fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
data_payload+split_pos, len_payload-split_pos, pkt1, &pkt1_len))
return verdict;
DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ",split_pos,len_payload-1, len_payload-split_pos);
@ -1701,7 +1712,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
break;
}
case DESYNC_FAKE:
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_fake, dp->desync_fooling_mode, NULL, 0, 0, fake, fake_size, pkt1, &pkt1_len))
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_fake, IP4_TOS(ip),IP6_FLOW(ip6hdr), dp->desync_fooling_mode, NULL, 0, 0, fake, fake_size, pkt1, &pkt1_len))
return verdict;
DLOG("sending fake request : ");
hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n");
@ -1716,7 +1727,8 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (ip6hdr && (dp->desync_mode2==DESYNC_NONE || !desync_valid_second_stage_udp(dp->desync_mode2)))
{
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
ttl_orig,fooling_orig,NULL,0,0,
ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr),
fooling_orig,NULL,0,0,
data_payload, len_payload, pkt1, &pkt1_len))
{
return verdict;
@ -1751,7 +1763,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
{
case DESYNC_UDPLEN:
pkt1_len = sizeof(pkt1);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, data_payload, len_payload, pkt1, &pkt1_len))
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr), fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, data_payload, len_payload, pkt1, &pkt1_len))
{
DLOG("could not construct packet with modified length. too large ?\n");
return verdict;
@ -1776,7 +1788,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
memcpy(pkt2+pkt2_len,data_payload+1,szcopy);
pkt2_len+=szcopy;
pkt1_len = sizeof(pkt1);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len))
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,IP4_TOS(ip),IP6_FLOW(ip6hdr), fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len))
{
DLOG("could not construct packet with modified length. too large ?\n");
return verdict;