nfqws: extend conntrack

This commit is contained in:
bol-van 2021-03-19 15:39:32 +03:00
parent 5e1adaa348
commit 5ddc0aa01b
5 changed files with 57 additions and 21 deletions

View File

@ -98,6 +98,7 @@ t_conntrack6 *ConntrackPoolSearch6(t_conntrack6 *p, const t_conn6 *c)
static void ConntrackInitTrack(t_ctrack *t)
{
memset(t,0,sizeof(*t));
t->scale_orig = t->scale_reply = SCALE_NONE;
time(&t->t_start);
}
@ -122,6 +123,7 @@ static t_conntrack6 *ConntrackNew6(t_conntrack6 **pp, const t_conn6 *c)
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
{
uint8_t scale;
if (tcp_syn_segment(tcphdr))
{
if (t->state==FIN) ConntrackInitTrack(t); // erase current entry
@ -148,17 +150,23 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
if (!bReverse && !t->ack0) t->ack0 = htonl(tcphdr->th_ack)-1;
}
}
scale = tcp_find_scale_factor(tcphdr);
if (bReverse)
{
t->seq_last = htonl(tcphdr->th_ack);
t->ack_last = htonl(tcphdr->th_seq) + len_payload;
t->pcounter_reply++;
t->winsize_reply = htons(tcphdr->th_win);
if (scale!=SCALE_NONE) t->scale_reply = scale;
}
else
{
t->seq_last = htonl(tcphdr->th_seq) + len_payload;
t->ack_last = htonl(tcphdr->th_ack);
t->pcounter_orig++;
t->winsize_orig = htons(tcphdr->th_win);
if (scale!=SCALE_NONE) t->scale_orig = scale;
}
time(&t->t_last);
}
@ -271,13 +279,15 @@ void ConntrackPoolPurge(t_conntrack *p)
HASH_ITER(hh, p, t, tmp) { \
*sa1=0; inet_ntop(AF_INET##f, &t->conn.e1.adr, sa1, sizeof(sa1)); \
*sa2=0; inet_ntop(AF_INET##f, &t->conn.e2.adr, sa2, sizeof(sa2)); \
printf("[%s]:%u => [%s]:%u : %s : t0=%lld last=t0+%lld now=last+%lld cutoff=%u packets_orig=%llu packets_reply=%llu seq0=%u rseq=%u ack0=%u rack=%u\n", \
printf("[%s]:%u => [%s]:%u : %s : t0=%lld last=t0+%lld now=last+%lld cutoff=%u packets_orig=%llu packets_reply=%llu seq0=%u rseq=%u ack0=%u rack=%u wsize_orig=%u:%d wsize_reply=%u:%d\n", \
sa1, t->conn.e1.port, sa2, t->conn.e2.port, \
connstate_s[t->track.state], \
(unsigned long long)t->track.t_start, (unsigned long long)(t->track.t_last - t->track.t_start), (unsigned long long)(tnow - t->track.t_last), \
t->track.b_cutoff, \
(unsigned long long)t->track.pcounter_orig, (unsigned long long)t->track.pcounter_reply, \
t->track.seq0, t->track.seq_last - t->track.seq0, t->track.ack0, t->track.ack_last - t->track.ack0); \
t->track.seq0, t->track.seq_last - t->track.seq0, t->track.ack0, t->track.ack_last - t->track.ack0, \
t->track.winsize_orig, t->track.scale_orig==SCALE_NONE ? -1 : t->track.scale_orig, \
t->track.winsize_reply, t->track.scale_reply==SCALE_NONE ? -1 : t->track.scale_reply ); \
};
void ConntrackPoolDump4(t_conntrack4 *p)
{

View File

@ -51,6 +51,8 @@ typedef struct
uint32_t seq0, ack0; // starting seq and ack
uint32_t seq_last, ack_last; // current seq and ack
uint64_t pcounter_orig, pcounter_reply; // packet counter
uint16_t winsize_orig, winsize_reply; // last seen window size
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
bool b_cutoff; // mark for deletion
} t_ctrack;

View File

@ -46,8 +46,14 @@ uint32_t *tcp_find_timestamps(struct tcphdr *tcp)
uint8_t *t = tcp_find_option(tcp,8);
return (t && t[1]==10) ? (uint32_t*)(t+2) : NULL;
}
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp)
{
uint8_t *scale = tcp_find_option((struct tcphdr*)tcp,3); // tcp option 3 - scale factor
if (scale && scale[1]==3) return scale[2];
return SCALE_NONE;
}
static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uint32_t ack_seq, uint8_t fooling, uint16_t nsport, uint16_t ndport, uint16_t nwsize, uint32_t *timestamps)
static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uint32_t ack_seq, uint8_t fooling, uint16_t nsport, uint16_t ndport, uint16_t nwsize, uint8_t scale_factor, uint32_t *timestamps)
{
char *tcpopt = (char*)(tcp+1);
uint8_t t=0;
@ -87,14 +93,21 @@ static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uin
*(uint32_t*)(tcpopt+t+6) = (timestamps && !(fooling & TCP_FOOL_TS)) ? timestamps[1] : -1;
t+=10;
}
if (scale_factor!=SCALE_NONE)
{
tcpopt[t++]=3;
tcpopt[t++]=3;
tcpopt[t++]=scale_factor;
}
while (t&3) tcpopt[t++]=1; // noop
tcp->th_off += t>>2;
}
static uint16_t tcpopt_len(uint8_t fooling, uint32_t *timestamps)
static uint16_t tcpopt_len(uint8_t fooling, uint32_t *timestamps, uint8_t scale_factor)
{
uint16_t t=0;
if (fooling & TCP_FOOL_MD5SIG) t=18;
if ((fooling & TCP_FOOL_TS) || timestamps) t+=10;
if (scale_factor!=SCALE_NONE) t+=3;
return (t+3)&~3;
}
@ -253,6 +266,7 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const void *data,size_t
{
int sock=rawsend_socket(dst->sa_family,fwmark);
if (sock==-1) return false;
int salen = dst->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
struct sockaddr_storage dst2;
memcpy(&dst2,dst,salen);
@ -323,13 +337,14 @@ bool prepare_tcp_segment4(
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t fooling,
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen)
{
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps);
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps, scale_factor);
uint16_t pktlen = sizeof(struct ip) + sizeof(struct tcphdr) + tcpoptlen + len;
if (pktlen>*buflen)
{
@ -350,7 +365,7 @@ bool prepare_tcp_segment4(
ip->ip_src = src->sin_addr;
ip->ip_dst = dst->sin_addr;
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin_port,dst->sin_port,wsize,timestamps);
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin_port,dst->sin_port,wsize,scale_factor,timestamps);
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
tcp4_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,&ip->ip_src,&ip->ip_dst);
@ -366,13 +381,14 @@ bool prepare_tcp_segment6(
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t fooling,
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen)
{
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps);
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps, scale_factor);
uint16_t payloadlen = sizeof(struct tcphdr) + tcpoptlen + len;
uint16_t pktlen = sizeof(struct ip6_hdr) + payloadlen;
if (pktlen>*buflen)
@ -391,7 +407,7 @@ bool prepare_tcp_segment6(
ip6->ip6_src = src->sin6_addr;
ip6->ip6_dst = dst->sin6_addr;
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin6_port,dst->sin6_port,wsize,timestamps);
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin6_port,dst->sin6_port,wsize,scale_factor,timestamps);
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
tcp6_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,&ip6->ip6_src,&ip6->ip6_dst);
@ -406,6 +422,7 @@ bool prepare_tcp_segment(
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t fooling,
@ -413,9 +430,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,seq,ack_seq,wsize,timestamps,ttl,fooling,data,len,buf,buflen) :
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,seq,ack_seq,wsize,scale_factor,timestamps,ttl,fooling,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,seq,ack_seq,wsize,timestamps,ttl,fooling,data,len,buf,buflen) :
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,seq,ack_seq,wsize,scale_factor,timestamps,ttl,fooling,data,len,buf,buflen) :
false;
}
@ -663,7 +680,7 @@ void tcp_rewrite_wscale(struct tcphdr *tcp, uint8_t scale_factor)
{
uint8_t *scale,scale_factor_old;
if (scale_factor!=(uint8_t)-1)
if (scale_factor!=SCALE_NONE)
{
scale = tcp_find_option(tcp,3); // tcp option 3 - scale factor
if (scale && scale[1]==3) // length should be 3
@ -680,7 +697,7 @@ void tcp_rewrite_wscale(struct tcphdr *tcp, uint8_t scale_factor)
}
}
}
// scale_factor=-1 - do not change
// scale_factor=SCALE_NONE - do not change
void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_factor)
{
uint16_t winsize_old;

View File

@ -19,12 +19,15 @@ uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
#define TCP_FOOL_TS 4
#define TCP_FOOL_BADSEQ 8
#define SCALE_NONE ((uint8_t)-1)
// seq and wsize have network byte order
bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t fooling,
@ -35,6 +38,7 @@ bool prepare_tcp_segment6(
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t fooling,
@ -45,6 +49,7 @@ bool prepare_tcp_segment(
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t fooling,
@ -54,6 +59,7 @@ bool prepare_tcp_segment(
void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
// auto creates internal socket and uses it for subsequent calls
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len);
@ -77,6 +83,6 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type);
bool tcp_synack_segment(const struct tcphdr *tcphdr);
bool tcp_syn_segment(const struct tcphdr *tcphdr);
bool tcp_ack_segment(const struct tcphdr *tcphdr);
// scale_factor=-1 - do not change
// scale_factor=SCALE_NONE - do not change
void tcp_rewrite_wscale(struct tcphdr *tcp, uint8_t scale_factor);
void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_factor);

View File

@ -240,6 +240,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
uint8_t flags_orig = *((uint8_t*)tcphdr+13);
uint32_t *timestamps = tcp_find_timestamps(tcphdr);
enum dpi_desync_mode desync_mode = params.desync_mode;
uint8_t scale_factor = tcp_find_scale_factor(tcphdr);
bool b;
newlen = sizeof(newdata);
@ -247,7 +248,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
switch(desync_mode)
{
case DESYNC_FAKE:
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, 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,
ttl_fake,params.desync_tcp_fooling_mode,
fake, fake_size, newdata, &newlen))
{
@ -259,7 +260,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
break;
case DESYNC_RST:
case DESYNC_RSTACK:
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, timestamps,
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,params.desync_tcp_fooling_mode,
NULL, 0, newdata, &newlen))
{
@ -311,7 +312,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
if (split_pos<len_payload)
{
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, timestamps,
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,TCP_FOOL_NONE,
data_payload+split_pos, len_payload-split_pos, newdata, &newlen))
return res;
@ -325,7 +326,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
if (desync_mode==DESYNC_DISORDER)
{
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, 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,
ttl_fake,params.desync_tcp_fooling_mode,
zeropkt, split_pos, fakeseg, &fakeseg_len))
return res;
@ -337,7 +338,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
newlen = sizeof(newdata);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, 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,
ttl_orig,TCP_FOOL_NONE,
data_payload, split_pos, newdata, &newlen))
return res;
@ -367,7 +368,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
if (desync_mode==DESYNC_SPLIT)
{
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, 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,
ttl_fake,params.desync_tcp_fooling_mode,
zeropkt, split_pos, fakeseg, &fakeseg_len))
return res;
@ -378,7 +379,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
}
newlen = sizeof(newdata);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, 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,
ttl_orig,TCP_FOOL_NONE,
data_payload, split_pos, newdata, &newlen))
return res;
@ -398,7 +399,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
if (split_pos<len_payload)
{
newlen = sizeof(newdata);
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, timestamps,
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,TCP_FOOL_NONE,
data_payload+split_pos, len_payload-split_pos, newdata, &newlen))
return res;