diff --git a/binaries/aarch64/nfqws b/binaries/aarch64/nfqws index 2ab321a..4da8068 100755 Binary files a/binaries/aarch64/nfqws and b/binaries/aarch64/nfqws differ diff --git a/binaries/armhf/nfqws b/binaries/armhf/nfqws index 96fbb7b..6fcc17e 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 79d3a82..b00f7c1 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 d92b077..52e4d3c 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 20bacca..a21833b 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 ce03b29..d84c5ba 100755 Binary files a/binaries/ppc/nfqws and b/binaries/ppc/nfqws differ diff --git a/binaries/x86/nfqws b/binaries/x86/nfqws index a2ec476..419b002 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 cc64236..0b9773b 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 index 70b5a59..46cf6c0 100644 --- a/nfq/checksum.c +++ b/nfq/checksum.c @@ -119,7 +119,7 @@ uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8 } -void tcp_fix_checksum(struct tcphdr *tcp,int len, in_addr_t src_addr, in_addr_t dest_addr) +void tcp4_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)); @@ -129,3 +129,10 @@ void tcp6_fix_checksum(struct tcphdr *tcp,int len, const struct in6_addr *src_ad tcp->check = 0; tcp->check = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_TCP,csum_partial(tcp, len)); } +void tcp_fix_checksum(struct tcphdr *tcp,int len,const struct iphdr *iphdr,const struct ip6_hdr *ip6hdr) +{ + if (iphdr) + tcp4_fix_checksum(tcp, len, iphdr->saddr, iphdr->daddr); + else if (ip6hdr) + tcp6_fix_checksum(tcp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst); +} diff --git a/nfq/checksum.h b/nfq/checksum.h index f5cff15..84d8050 100644 --- a/nfq/checksum.h +++ b/nfq/checksum.h @@ -12,5 +12,6 @@ uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8 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 tcp4_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); +void tcp_fix_checksum(struct tcphdr *tcp,int len,const struct iphdr *iphdr,const struct ip6_hdr *ip6hdr); diff --git a/nfq/darkmagic.c b/nfq/darkmagic.c index 2b088e0..a552ae2 100644 --- a/nfq/darkmagic.c +++ b/nfq/darkmagic.c @@ -192,7 +192,7 @@ bool prepare_tcp_segment4( fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin_port,dst->sin_port,wsize,timestamps); memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len); - tcp_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,ip->saddr,ip->daddr); + tcp4_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,ip->saddr,ip->daddr); if (fooling & TCP_FOOL_BADSUM) tcp->check^=0xBEAF; *buflen = pktlen; diff --git a/nfq/darkmagic.h b/nfq/darkmagic.h index 63864b5..403f379 100644 --- a/nfq/darkmagic.h +++ b/nfq/darkmagic.h @@ -1,5 +1,7 @@ #pragma once +#include "checksum.h" + #include #include #include @@ -7,7 +9,7 @@ #include #include #include -#include "checksum.h" + // returns netorder value uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment); diff --git a/nfq/desync.c b/nfq/desync.c index 563e24c..96b701b 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -58,9 +58,12 @@ void desync_init() // result : true - drop original packet, false = dont drop -bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *iphdr, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, uint8_t *data_payload, size_t len_payload) +packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struct iphdr *iphdr, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, size_t len_tcp, uint8_t *data_payload, size_t len_payload) { - if (!!iphdr == !!ip6hdr) return false; // one and only one must be present + packet_process_result res=pass; + + if (!!iphdr == !!ip6hdr) return res; // one and only one must be present + if (params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace) return res; // nothing to do. do not waste cpu if (!tcphdr->syn && len_payload) { @@ -69,8 +72,9 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip size_t fake_size; char host[256]; bool bHaveHost=false; + bool bIsHttp; - if (IsHttp(data_payload,len_payload)) + if (bIsHttp = IsHttp(data_payload,len_payload)) { DLOG("packet contains HTTP request\n") fake = (uint8_t*)fake_http_request; @@ -78,8 +82,8 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip if (params.hostlist || params.debug) bHaveHost=HttpExtractHost(data_payload,len_payload,host,sizeof(host)); if (params.hostlist && !bHaveHost) { - DLOG("not applying dpi-desync to HTTP without Host:\n") - return false; + DLOG("not applying tampering to HTTP without Host:\n") + return res; } } else if (IsTLSClientHello(data_payload,len_payload)) @@ -92,16 +96,15 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip bHaveHost=TLSHelloExtractHost(data_payload,len_payload,host,sizeof(host)); if (params.desync_skip_nosni && !bHaveHost) { - DLOG("not applying dpi-desync to TLS ClientHello without hostname in the SNI\n") - return false; + DLOG("not applying tampering to TLS ClientHello without hostname in the SNI\n") + return res; } } - } else { - if (!params.desync_any_proto) return false; - DLOG("applying dpi-desync to unknown protocol\n") + if (!params.desync_any_proto) return res; + DLOG("applying tampering to unknown protocol\n") fake = zeropkt; fake_size = 256; } @@ -111,11 +114,42 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip DLOG("hostname: %s\n",host) if (params.hostlist && !SearchHostList(params.hostlist,host,params.debug)) { - DLOG("not applying dpi-desync to this request\n") - return false; + DLOG("not applying tampering to this request\n") + return res; + } + + uint8_t *phost; + if (bIsHttp && (params.hostcase || params.hostnospace) && (phost = (uint8_t*)memmem(data_payload, len_payload, "\r\nHost: ", 8))) + { + if (params.hostcase) + { + DLOG("modifying Host: => %c%c%c%c:\n", params.hostspell[0], params.hostspell[1], params.hostspell[2], params.hostspell[3]) + memcpy(phost + 2, params.hostspell, 4); + res=modify; + } + uint8_t *pua; + if (params.hostnospace && + (pua = (uint8_t*)memmem(data_payload, len_payload, "\r\nUser-Agent: ", 14)) && + (pua = (uint8_t*)memmem(pua + 1, len_payload - (pua - data_payload) - 1, "\r\n", 2))) + { + DLOG("removing space after Host: and adding it to User-Agent:\n") + if (pua > phost) + { + memmove(phost + 7, phost + 8, pua - phost - 8); + phost[pua - phost - 1] = ' '; + } + else + { + memmove(pua + 1, pua, phost - pua + 7); + *pua = ' '; + } + res=modify; + } } } + if (params.desync_mode==DESYNC_NONE) return res; + extract_endpoints(iphdr, ip6hdr, tcphdr, &src, &dst); if (params.debug) { @@ -150,7 +184,7 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip data_payload+split_pos, len_payload-split_pos, newdata, &newlen) || !rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) { - return false; + return res; } } @@ -164,7 +198,7 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip zeropkt, split_pos, fakeseg, &fakeseg_len) || !rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) { - return false; + return res; } } @@ -176,17 +210,17 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip data_payload, split_pos, newdata, &newlen) || !rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) { - return false; + return res; } if (params.desync_mode==DESYNC_DISORDER) { DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos) if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) - return false; + return res; } - return true; + return drop; } break; case DESYNC_SPLIT: @@ -205,7 +239,7 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip zeropkt, split_pos, fakeseg, &fakeseg_len) || !rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) { - return false; + return res; } } @@ -216,14 +250,14 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip data_payload, split_pos, newdata, &newlen) || !rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen)) { - return false; + return res; } if (params.desync_mode==DESYNC_SPLIT) { DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos) if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len)) - return false; + return res; } if (split_pos #include @@ -24,4 +25,4 @@ enum dpi_desync_mode { }; void desync_init(); -bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *iphdr, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, uint8_t *data_payload, size_t len_payload); +packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struct iphdr *iphdr, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, size_t len_tcp, uint8_t *data_payload, size_t len_payload); diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 53b115e..124c785 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -1,5 +1,6 @@ #define _GNU_SOURCE +#include "nfqws.h" #include "sec.h" #include "desync.h" #include "helpers.h" @@ -138,17 +139,6 @@ static inline bool tcp_synack_segment(const struct tcphdr *tcphdr) tcphdr->syn == 1 && tcphdr->fin == 0; } -static inline bool tcp_ack_segment(const struct tcphdr *tcphdr) -{ - /* check for set bits in TCP hdr */ - return tcphdr->urg == 0 && - tcphdr->ack == 1 && - tcphdr->rst == 0 && - tcphdr->syn == 0 && - tcphdr->fin == 0; -} - - static void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize) { uint16_t winsize_old; @@ -157,77 +147,19 @@ static void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize) DLOG("Window size change %u => %u\n", winsize_old, winsize) } - // data/len points to data payload static bool modify_tcp_packet(uint8_t *data, size_t len, struct tcphdr *tcphdr) { - const char **method; - size_t method_len = 0; - uint8_t *phost, *pua; - bool bRet = false; - - if (tcp_synack_segment(tcphdr)) + if (tcp_synack_segment(tcphdr) && params.wsize) { - if (params.wsize) - { - tcp_rewrite_winsize(tcphdr, (uint16_t)params.wsize); - bRet = true; - } + tcp_rewrite_winsize(tcphdr, (uint16_t)params.wsize); + return true; } - else if ((params.hostcase || params.hostnospace) && IsHttp(data,len)) - { - if (params.hostlist) - { - char host[256]; - if (HttpExtractHost(data,len,host,sizeof(host))) - { - DLOG("hostname: %s\n",host) - if (!SearchHostList(params.hostlist,host,params.debug)) - { - DLOG("not applying tampering to this request\n") - return false; - } - } - else - { - DLOG("could not extract host from http request. not applying tampering\n") - return false; - } - } - if (phost = (uint8_t*)memmem(data, len, "\r\nHost: ", 8)) - { - if (params.hostcase) - { - DLOG("modifying Host: => %c%c%c%c:\n", params.hostspell[0], params.hostspell[1], params.hostspell[2], params.hostspell[3]) - memcpy(phost + 2, params.hostspell, 4); - bRet = true; - } - if (params.hostnospace && (pua = (uint8_t*)memmem(data, len, "\r\nUser-Agent: ", 14)) && (pua = (uint8_t*)memmem(pua + 1, len - (pua - data) - 1, "\r\n", 2))) - { - DLOG("removing space after Host: and adding it to User-Agent:\n") - if (pua > phost) - { - memmove(phost + 7, phost + 8, pua - phost - 8); - phost[pua - phost - 1] = ' '; - } - else - { - memmove(pua + 1, pua, phost - pua + 7); - *pua = ' '; - } - bRet = true; - } - } - } - return bRet; + return false; } -typedef enum -{ - pass = 0, modify, drop -} packet_process_result; static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt, uint32_t *mark) { struct iphdr *iphdr = NULL; @@ -235,7 +167,7 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt struct tcphdr *tcphdr = NULL; size_t len = len_pkt, len_tcp; uint8_t *data = data_pkt; - packet_process_result res = pass; + packet_process_result res = pass, res2; uint8_t proto; if (*mark & params.desync_fwmark) return res; @@ -266,18 +198,10 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt if (modify_tcp_packet(data, len, tcphdr)) res = modify; - if (params.desync_mode!=DESYNC_NONE) - { - if (dpi_desync_packet(data_pkt, len_pkt, iphdr, ip6hdr, tcphdr, data, len)) - res = drop; - } - if (res==modify) - { - if (iphdr) - tcp_fix_checksum(tcphdr, len_tcp, iphdr->saddr, iphdr->daddr); - else - tcp6_fix_checksum(tcphdr, len_tcp, &ip6hdr->ip6_src, &ip6hdr->ip6_dst); - } + + res2 = dpi_desync_packet(data_pkt, len_pkt, iphdr, ip6hdr, tcphdr, len_tcp, data, len); + res = (res2==pass && res==modify) ? modify : res2; + if (res==modify) tcp_fix_checksum(tcphdr,len_tcp,iphdr,ip6hdr); } return res; } @@ -320,7 +244,7 @@ static void exithelp() " --pidfile=\t\t\t; write pid to file\n" " --user=\t\t\t; drop root privs\n" " --uid=uid[:gid]\t\t\t; drop root privs\n" - " --wsize=\t\t\t; set window size. 0 = do not modify\n" + " --wsize=\t\t\t; set window size. 0 = do not modify. OBSOLETE !\n" " --hostcase\t\t\t\t; change Host: => host:\n" " --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n" " --hostnospace\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n" diff --git a/nfq/nfqws.h b/nfq/nfqws.h new file mode 100644 index 0000000..216bb9e --- /dev/null +++ b/nfq/nfqws.h @@ -0,0 +1,6 @@ +#pragma once + +typedef enum +{ + pass = 0, modify, drop +} packet_process_result;