Browse Source

nfqws: endian-correct seq increment, preserve window size

pull/53/head
bol-van 6 years ago
parent
commit
696c04ae1b
  1. BIN
      binaries/aarch64/nfqws
  2. BIN
      binaries/armhf/nfqws
  3. BIN
      binaries/mips32r1-lsb/nfqws
  4. BIN
      binaries/mips32r1-msb/nfqws
  5. BIN
      binaries/mips64r2-msb/nfqws
  6. BIN
      binaries/ppc/nfqws
  7. BIN
      binaries/x86/nfqws
  8. BIN
      binaries/x86_64/nfqws
  9. 131
      nfq/checksum.c
  10. 16
      nfq/checksum.h
  11. 118
      nfq/darkmagic.c
  12. 11
      nfq/darkmagic.h
  13. 10
      nfq/nfqws.c

BIN
binaries/aarch64/nfqws

Binary file not shown.

BIN
binaries/armhf/nfqws

Binary file not shown.

BIN
binaries/mips32r1-lsb/nfqws

Binary file not shown.

BIN
binaries/mips32r1-msb/nfqws

Binary file not shown.

BIN
binaries/mips64r2-msb/nfqws

Binary file not shown.

BIN
binaries/ppc/nfqws

Binary file not shown.

BIN
binaries/x86/nfqws

Binary file not shown.

BIN
binaries/x86_64/nfqws

Binary file not shown.

131
nfq/checksum.c

@ -0,0 +1,131 @@
#define _GNU_SOURCE
#include "checksum.h"
#include <netinet/in.h>
//#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
//#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
static uint16_t from64to16(uint64_t x)
{
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x>>16) + (uint16_t)(x>>32) + (uint16_t)(x>>48);
return (uint16_t)u + (uint16_t)(u>>16);
}
static uint16_t do_csum(const uint8_t * buff, size_t len)
{
uint8_t odd;
size_t count;
uint64_t result,w,carry=0;
uint16_t u16;
if (len <= 0) return 0;
odd = (uint8_t)(1 & (size_t)buff);
if (odd)
{
// any endian compatible
u16 = 0;
*((uint8_t*)&u16+1) = *buff;
result = u16;
len--;
buff++;
}
else
result = 0;
count = len >> 1; /* nr of 16-bit words.. */
if (count)
{
if (2 & (size_t) buff)
{
result += *(uint16_t *) buff;
count--;
len -= 2;
buff += 2;
}
count >>= 1; /* nr of 32-bit words.. */
if (count)
{
if (4 & (size_t) buff)
{
result += *(uint32_t *) buff;
count--;
len -= 4;
buff += 4;
}
count >>= 1; /* nr of 64-bit words.. */
if (count)
{
do
{
w = *(uint64_t *) buff;
count--;
buff += 8;
result += carry;
result += w;
carry = (w > result);
} while (count);
result += carry;
result = (result & 0xffffffff) + (result >> 32);
}
if (len & 4)
{
result += *(uint32_t *) buff;
buff += 4;
}
}
if (len & 2)
{
result += *(uint16_t *) buff;
buff += 2;
}
}
if (len & 1)
{
// any endian compatible
u16 = 0;
*(uint8_t*)&u16 = *buff;
result += u16;
}
u16 = from64to16(result);
if (odd) u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
return u16;
}
uint16_t csum_partial(const void *buff, size_t len)
{
return do_csum(buff,len);
}
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum)
{
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len+proto));
}
uint16_t ip4_compute_csum(const void *buff, size_t len)
{
return ~from64to16(do_csum(buff,len));
}
void ip4_fix_checksum(struct iphdr *ip)
{
ip->check = 0;
ip->check = ip4_compute_csum(ip, ip->ihl<<2);
}
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum)
{
uint64_t a = (uint64_t)sum + htonl(len+proto) +
*(uint32_t*)saddr + *((uint32_t*)saddr+1) + *((uint32_t*)saddr+2) + *((uint32_t*)saddr+3) +
*(uint32_t*)daddr + *((uint32_t*)daddr+1) + *((uint32_t*)daddr+2) + *((uint32_t*)daddr+3);
return ~from64to16(a);
}
void tcp_fix_checksum(struct tcphdr *tcp,int len, in_addr_t src_addr, in_addr_t dest_addr)
{
tcp->check = 0;
tcp->check = csum_tcpudp_magic(src_addr,dest_addr,len,IPPROTO_TCP,csum_partial(tcp, len));
}
void tcp6_fix_checksum(struct tcphdr *tcp,int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
{
tcp->check = 0;
tcp->check = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_TCP,csum_partial(tcp, len));
}

16
nfq/checksum.h

@ -0,0 +1,16 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <netinet/ip6.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
uint16_t csum_partial(const void *buff, size_t len);
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum);
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum);
uint16_t ip4_compute_csum(const void *buff, size_t len);
void ip4_fix_checksum(struct iphdr *ip);
void tcp_fix_checksum(struct tcphdr *tcp,int len, in_addr_t src_addr, in_addr_t dest_addr);
void tcp6_fix_checksum(struct tcphdr *tcp,int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr);

118
nfq/darkmagic.c

@ -1,114 +1,17 @@
#define _GNU_SOURCE
#include "darkmagic.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "darkmagic.h"
uint16_t tcp_checksum(const void *buff, int len, in_addr_t src_addr, in_addr_t dest_addr)
{
const uint16_t *buf=buff;
uint16_t *ip_src=(uint16_t *)&src_addr, *ip_dst=(uint16_t *)&dest_addr;
uint32_t sum;
int length=len;
// Calculate the sum
sum = 0;
while (len > 1)
{
sum += *buf++;
if (sum & 0x80000000)
sum = (sum & 0xFFFF) + (sum >> 16);
len -= 2;
}
if ( len & 1 )
{
// Add the padding if the packet lenght is odd
uint16_t v=0;
*(uint8_t *)&v = *((uint8_t *)buf);
sum += v;
}
// Add the pseudo-header
sum += *(ip_src++);
sum += *ip_src;
sum += *(ip_dst++);
sum += *ip_dst;
sum += htons(IPPROTO_TCP);
sum += htons(length);
// Add the carries
while (sum >> 16)
sum = (sum & 0xFFFF) + (sum >> 16);
// Return the one's complement of sum
return (uint16_t)(~sum);
}
void tcp_fix_checksum(struct tcphdr *tcp,int len, in_addr_t src_addr, in_addr_t dest_addr)
{
tcp->check = 0;
tcp->check = tcp_checksum(tcp,len,src_addr,dest_addr);
}
uint16_t tcp6_checksum(const void *buff, int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
{
const uint16_t *buf=buff;
const uint16_t *ip_src=(uint16_t *)src_addr, *ip_dst=(uint16_t *)dest_addr;
uint32_t sum;
int length=len;
// Calculate the sum
sum = 0;
while (len > 1)
{
sum += *buf++;
if (sum & 0x80000000)
sum = (sum & 0xFFFF) + (sum >> 16);
len -= 2;
}
if ( len & 1 )
{
// Add the padding if the packet lenght is odd
uint16_t v=0;
*(uint8_t *)&v = *((uint8_t *)buf);
sum += v;
}
// Add the pseudo-header
sum += *(ip_src++);
sum += *(ip_src++);
sum += *(ip_src++);
sum += *(ip_src++);
sum += *(ip_src++);
sum += *(ip_src++);
sum += *(ip_src++);
sum += *ip_src;
sum += *(ip_dst++);
sum += *(ip_dst++);
sum += *(ip_dst++);
sum += *(ip_dst++);
sum += *(ip_dst++);
sum += *(ip_dst++);
sum += *(ip_dst++);
sum += *ip_dst;
sum += htons(IPPROTO_TCP);
sum += htons(length);
// Add the carries
while (sum >> 16)
sum = (sum & 0xFFFF) + (sum >> 16);
// Return the one's complement of sum
return (uint16_t)(~sum);
}
void tcp6_fix_checksum(struct tcphdr *tcp,int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
{
tcp->check = 0;
tcp->check = tcp6_checksum(tcp,len,src_addr,dest_addr);
return htonl(ntohl(netorder_value)+cpuorder_increment);
}
static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uint32_t ack_seq, enum tcp_fooling_mode fooling, uint16_t nsport, uint16_t ndport)
static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uint32_t ack_seq, enum tcp_fooling_mode fooling, uint16_t nsport, uint16_t ndport, uint16_t nwsize)
{
char *tcpopt = (char*)(tcp+1);
memset(tcp,0,sizeof(*tcp));
@ -118,7 +21,7 @@ static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uin
tcp->ack_seq = ack_seq;
tcp->doff = 5;
*((uint8_t*)tcp+13)= tcp_flags;
tcp->window = htons(65535);
tcp->window = nwsize;
if (fooling==TCP_FOOL_MD5SIG)
{
tcp->doff += 5; // +20 bytes
@ -185,6 +88,7 @@ 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 ttl,
enum tcp_fooling_mode fooling,
const void *data, uint16_t len,
@ -212,7 +116,7 @@ bool prepare_tcp_segment4(
ip->saddr = src->sin_addr.s_addr;
ip->daddr = dst->sin_addr.s_addr;
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin_port,dst->sin_port);
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin_port,dst->sin_port,wsize);
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
tcp_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,ip->saddr,ip->daddr);
@ -227,6 +131,7 @@ bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t ttl,
enum tcp_fooling_mode fooling,
const void *data, uint16_t len,
@ -252,7 +157,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);
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin6_port,dst->sin6_port,wsize);
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
tcp6_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,&ip6->ip6_src,&ip6->ip6_dst);
@ -266,15 +171,16 @@ bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t ttl,
enum tcp_fooling_mode fooling,
const void *data, uint16_t len,
char *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,ttl,fooling,data,len,buf,buflen) :
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,seq,ack_seq,wsize,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,ttl,fooling,data,len,buf,buflen) :
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,seq,ack_seq,wsize,ttl,fooling,data,len,buf,buflen) :
false;
}

11
nfq/darkmagic.h

@ -7,21 +7,22 @@
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "checksum.h"
uint16_t tcp_checksum(const void *buff, int len, in_addr_t src_addr, in_addr_t dest_addr);
void tcp_fix_checksum(struct tcphdr *tcp,int len, in_addr_t src_addr, in_addr_t dest_addr);
uint16_t tcp6_checksum(const void *buff, int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr);
void tcp6_fix_checksum(struct tcphdr *tcp,int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr);
// returns netorder value
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
enum tcp_fooling_mode {
TCP_FOOL_NONE=0,
TCP_FOOL_MD5SIG=1,
TCP_FOOL_BADSUM=2
};
// 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 ttl,
enum tcp_fooling_mode fooling,
const void *data, uint16_t len,
@ -30,6 +31,7 @@ bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t ttl,
enum tcp_fooling_mode fooling,
const void *data, uint16_t len,
@ -38,6 +40,7 @@ bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags,
uint32_t seq, uint32_t ack_seq,
uint16_t wsize,
uint8_t ttl,
enum tcp_fooling_mode fooling,
const void *data, uint16_t len,

10
nfq/nfqws.c

@ -534,7 +534,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
switch(params.desync_mode)
{
case DESYNC_FAKE:
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq,
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window,
ttl_fake,params.desync_tcp_fooling_mode,
fake, fake_size, newdata, &newlen))
{
@ -543,7 +543,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
break;
case DESYNC_RST:
case DESYNC_RSTACK:
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (params.desync_mode==DESYNC_RSTACK ? TH_ACK:0), tcphdr->seq, tcphdr->ack_seq,
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (params.desync_mode==DESYNC_RSTACK ? TH_ACK:0), tcphdr->seq, tcphdr->ack_seq, tcphdr->window,
ttl_fake,params.desync_tcp_fooling_mode,
NULL, 0, newdata, &newlen))
{
@ -560,7 +560,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
if (split_pos<len_payload)
{
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu\n",split_pos,len_payload-1, len_payload-split_pos)
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq+split_pos, tcphdr->ack_seq,
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->seq,split_pos), tcphdr->ack_seq, tcphdr->window,
ttl_orig,TCP_FOOL_NONE,
data_payload+split_pos, len_payload-split_pos, newdata, &newlen) ||
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
@ -574,7 +574,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
{
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos)
fakeseg_len = sizeof(fakeseg);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq,
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window,
ttl_fake,params.desync_tcp_fooling_mode,
zeropkt, split_pos, fakeseg, &fakeseg_len) ||
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
@ -586,7 +586,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos)
newlen = sizeof(newdata);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq,
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window,
ttl_orig,TCP_FOOL_NONE,
data_payload, split_pos, newdata, &newlen) ||
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))

Loading…
Cancel
Save