diff --git a/binaries/aarch64/nfqws b/binaries/aarch64/nfqws index 6fedd57..ac07df0 100755 Binary files a/binaries/aarch64/nfqws and b/binaries/aarch64/nfqws differ diff --git a/binaries/armhf/nfqws b/binaries/armhf/nfqws index 88944d5..a7dbd23 100755 Binary files a/binaries/armhf/nfqws and b/binaries/armhf/nfqws differ diff --git a/binaries/mips32r1-lsb/nfqws b/binaries/mips32r1-lsb/nfqws index e16d325..0a13a11 100755 Binary files a/binaries/mips32r1-lsb/nfqws and b/binaries/mips32r1-lsb/nfqws differ diff --git a/binaries/mips32r1-msb/nfqws b/binaries/mips32r1-msb/nfqws index a5b15e4..73179f7 100755 Binary files a/binaries/mips32r1-msb/nfqws and b/binaries/mips32r1-msb/nfqws differ diff --git a/binaries/mips64r2-msb/nfqws b/binaries/mips64r2-msb/nfqws index d9340a3..d055514 100755 Binary files a/binaries/mips64r2-msb/nfqws and b/binaries/mips64r2-msb/nfqws differ diff --git a/binaries/ppc/nfqws b/binaries/ppc/nfqws index 5b347df..fa53c58 100755 Binary files a/binaries/ppc/nfqws and b/binaries/ppc/nfqws differ diff --git a/binaries/x86/nfqws b/binaries/x86/nfqws index 9743f20..5bbb93a 100755 Binary files a/binaries/x86/nfqws and b/binaries/x86/nfqws differ diff --git a/binaries/x86_64/nfqws b/binaries/x86_64/nfqws index 5690c1e..f51c218 100755 Binary files a/binaries/x86_64/nfqws and b/binaries/x86_64/nfqws differ diff --git a/nfq/checksum.c b/nfq/checksum.c new file mode 100644 index 0000000..70b5a59 --- /dev/null +++ b/nfq/checksum.c @@ -0,0 +1,131 @@ +#define _GNU_SOURCE +#include "checksum.h" +#include + +//#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)); +} diff --git a/nfq/checksum.h b/nfq/checksum.h new file mode 100644 index 0000000..f5cff15 --- /dev/null +++ b/nfq/checksum.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include +#include +#include + +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); diff --git a/nfq/darkmagic.c b/nfq/darkmagic.c index f6107d6..41cdbed 100644 --- a/nfq/darkmagic.c +++ b/nfq/darkmagic.c @@ -1,114 +1,17 @@ #define _GNU_SOURCE -#include "darkmagic.h" #include #include #include #include +#include "darkmagic.h" -uint16_t tcp_checksum(const void *buff, int len, in_addr_t src_addr, in_addr_t dest_addr) +uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment) { - 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) -{ - 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; } diff --git a/nfq/darkmagic.h b/nfq/darkmagic.h index d9dbe98..72593b9 100644 --- a/nfq/darkmagic.h +++ b/nfq/darkmagic.h @@ -7,21 +7,22 @@ #include #include #include +#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, diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 5dfe943..0f579a9 100644 --- a/nfq/nfqws.c +++ b/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_posseq+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))