diff --git a/binaries/aarch64/nfqws b/binaries/aarch64/nfqws index a75627b..de0d3f7 100755 Binary files a/binaries/aarch64/nfqws and b/binaries/aarch64/nfqws differ diff --git a/binaries/arm/nfqws b/binaries/arm/nfqws index fb777b0..aacf594 100755 Binary files a/binaries/arm/nfqws and b/binaries/arm/nfqws differ diff --git a/binaries/mips32r1-lsb/nfqws b/binaries/mips32r1-lsb/nfqws index 08217c6..f71d3e6 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 756d313..c310ceb 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 9127bab..347dd10 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 edafc55..dd6994f 100755 Binary files a/binaries/ppc/nfqws and b/binaries/ppc/nfqws differ diff --git a/binaries/x86/nfqws b/binaries/x86/nfqws index 53c17c6..92babcb 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 0a30f3d..7993df3 100755 Binary files a/binaries/x86_64/nfqws and b/binaries/x86_64/nfqws differ diff --git a/nfq/desync.c b/nfq/desync.c index 7cacde6..2a790a6 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -321,6 +321,35 @@ static void reasm_orig_fin(t_ctrack *ctrack) } +static packet_process_result ct_new_postnat_fix(const t_ctrack *ctrack, struct ip *ip, packet_process_result res) +{ +#ifdef __linux__ + // if used in postnat chain, dropping initial packet will cause conntrack connection teardown + // so we need to workaround this. + // we can't use low ttl for UDP because TCP/IP stack listens to ttl expired ICMPs and notify socket + // we also can't use TCP fooling because DPI would accept fooled packets + if (ip && ctrack && ctrack->pcounter_orig==1) + { + // routers will drop IP frames with invalid checksum + if (ip->ip_p==IPPROTO_TCP) + { + // linux recalc ip checksum in tcp + // need another limiter + ip->ip_ttl=1; + } + else + ip->ip_sum ^= htons(0xBEAF); + + return res==frag ? modfrag : modify; + } + else +#endif + // ipv6 does not have checksum + // consider we are free of NAT in ipv6 case. just drop + // BSDs also do not need this + return drop; +} + // result : true - drop original packet, false = dont drop packet_process_result dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t len_pkt, struct ip *ip, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, size_t len_tcp, uint8_t *data_payload, size_t len_payload) @@ -479,26 +508,11 @@ packet_process_result dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return res; - #ifdef __linux__ - // if used in postnat chain, dropping SYN will cause conntrack connection teardown - // so we need to workaround this. - // we can't use low ttl because TCP/IP stack listens to ttl expired ICMPs in response to SYN and reset connection - // we also can't use TCP fooling because DPI would accept fooled packets - if (ip) - { - // routers will drop IP frames with invalid checksum - ip->ip_sum ^= htons(0xBEAF); - res=modify; - } - else - // ipv6 does not have checksum - // consider we are free of NAT in ipv6 case. just drop - res=drop; - #else - res=drop; - #endif + res = ct_new_postnat_fix(ctrack, ip, drop); break; } + // can do nothing else with SYN packet + return res; } if (params.desync_cutoff) @@ -1142,7 +1156,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return res; // this mode is final, no other options available - return drop; + return ct_new_postnat_fix(ctrack, ip, drop); } desync_mode = params.desync_mode2; break; @@ -1163,7 +1177,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , data_pkt, len_pkt)) return res; - return drop; + return ct_new_postnat_fix(ctrack, ip, drop); } desync_mode = params.desync_mode2; } @@ -1180,7 +1194,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, DLOG("resending original packet with increased by %d length\n", params.udplen_increment); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return res; - return drop; + return ct_new_postnat_fix(ctrack, ip, drop); case DESYNC_TAMPER: if (IsDhtD1(data_payload,len_payload)) { @@ -1205,7 +1219,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, DLOG("resending tampered DHT\n"); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return res; - return drop; + return ct_new_postnat_fix(ctrack, ip, drop); } else { @@ -1261,7 +1275,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return res; - return frag; + return ct_new_postnat_fix(ctrack, ip, frag); } } diff --git a/nfq/nfqws.c b/nfq/nfqws.c index b5dfec3..a92339f 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -146,7 +146,7 @@ static packet_process_result processPacketData(uint32_t *mark, const char *ifout // ipv6 packets were with incorrect checksum #ifdef __FreeBSD__ // FreeBSD tend to pass ipv6 frames with wrong checksum - if (res==modify || res!=frag && ip6hdr) + if (res==modify || res!=frag && res!=modfrag && ip6hdr) #else if (res==modify) #endif @@ -169,7 +169,7 @@ static packet_process_result processPacketData(uint32_t *mark, const char *ifout res = dpi_desync_udp_packet(*mark, ifout, data_pkt, len_pkt, ip, ip6hdr, udphdr, data, len); #ifdef __FreeBSD__ // FreeBSD tend to pass ipv6 frames with wrong checksum - if (res==modify || res!=frag && ip6hdr) + if (res==modify || res!=frag && res!=modfrag && ip6hdr) #else if (res==modify) #endif @@ -216,6 +216,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da switch (processPacketData(&mark, ifout, data, len)) { case modify: + case modfrag: DLOG("packet: id=%d pass modified\n", id); return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, len, data); case drop: diff --git a/nfq/nfqws.h b/nfq/nfqws.h index c9d1870..14de96d 100644 --- a/nfq/nfqws.h +++ b/nfq/nfqws.h @@ -3,5 +3,5 @@ typedef enum { // frag=drop but do not fix checksum - pass = 0, modify, drop, frag + pass = 0, modify, drop, frag, modfrag } packet_process_result;