From bbb6af89fea92459231a287a8458d1cc48f8bcf0 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Sat, 25 Dec 2021 10:58:42 +0300 Subject: [PATCH] New Fake Packet circumvention method: wrong SEQ/ACK numbers This method sends Fake Packet with the TCP SEQ/ACK numbers "in the past": -66000 is used for ACK (right out of the ACK permissive window in Linux stack), -10000 is used for SEQ (without any reasoning). This method is pretty effective in Russia. It also could be handy in a networks which prohibit changing TTL values (mobile networks with tethering block/premium feature). --- src/fakepackets.c | 37 ++++++++++++++++++++++++++++--------- src/fakepackets.h | 6 ++++-- src/goodbyedpi.c | 16 +++++++++++++--- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/fakepackets.c b/src/fakepackets.c index 84dce74..7fa7750 100644 --- a/src/fakepackets.c +++ b/src/fakepackets.c @@ -53,7 +53,8 @@ static int send_fake_data(const HANDLE w_filter, const BOOL is_ipv6, const BOOL is_https, const BYTE set_ttl, - const BYTE set_checksum + const BYTE set_checksum, + const BYTE set_seq ) { char packet_fake[MAX_PACKET_SIZE]; WINDIVERT_ADDRESS addr_new; @@ -69,6 +70,9 @@ static int send_fake_data(const HANDLE w_filter, memcpy(&addr_new, addr, sizeof(WINDIVERT_ADDRESS)); memcpy(packet_fake, pkt, packetLen); + addr_new.PseudoTCPChecksum = 0; + addr_new.PseudoIPChecksum = 0; + if (!is_ipv6) { // IPv4 TCP Data packet if (!WinDivertHelperParsePacket(packet_fake, packetLen, &ppIpHdr, @@ -107,8 +111,15 @@ static int send_fake_data(const HANDLE w_filter, ppIpV6Hdr->HopLimit = set_ttl; } + if (set_seq) { + // This is the smallest ACK drift Linux can't handle already, since at least v2.6.18. + // https://github.com/torvalds/linux/blob/v2.6.18/net/netfilter/nf_conntrack_proto_tcp.c#L395 + ppTcpHdr->AckNum = htonl(ntohl(ppTcpHdr->AckNum) - 66000); + // This is just random, no specifics about this value. + ppTcpHdr->SeqNum = htonl(ntohl(ppTcpHdr->SeqNum) - 10000); + } + // Recalculate the checksum - addr_new.PseudoTCPChecksum = 0; WinDivertHelperCalcChecksums(packet_fake, packetLen_new, &addr_new, NULL); if (set_checksum) { @@ -134,17 +145,23 @@ static int send_fake_request(const HANDLE w_filter, const BOOL is_ipv6, const BOOL is_https, const BYTE set_ttl, - const BYTE set_checksum + const BYTE set_checksum, + const BYTE set_seq ) { if (set_ttl) { send_fake_data(w_filter, addr, pkt, packetLen, is_ipv6, is_https, - set_ttl, FALSE); + set_ttl, FALSE, FALSE); } if (set_checksum) { send_fake_data(w_filter, addr, pkt, packetLen, is_ipv6, is_https, - FALSE, set_checksum); + FALSE, set_checksum, FALSE); + } + if (set_seq) { + send_fake_data(w_filter, addr, pkt, packetLen, + is_ipv6, is_https, + FALSE, FALSE, set_seq); } return 0; } @@ -155,11 +172,12 @@ int send_fake_http_request(const HANDLE w_filter, const UINT packetLen, const BOOL is_ipv6, const BYTE set_ttl, - const BYTE set_checksum + const BYTE set_checksum, + const BYTE set_seq ) { return send_fake_request(w_filter, addr, pkt, packetLen, is_ipv6, FALSE, - set_ttl, set_checksum); + set_ttl, set_checksum, set_seq); } int send_fake_https_request(const HANDLE w_filter, @@ -168,9 +186,10 @@ int send_fake_https_request(const HANDLE w_filter, const UINT packetLen, const BOOL is_ipv6, const BYTE set_ttl, - const BYTE set_checksum + const BYTE set_checksum, + const BYTE set_seq ) { return send_fake_request(w_filter, addr, pkt, packetLen, is_ipv6, TRUE, - set_ttl, set_checksum); + set_ttl, set_checksum, set_seq); } diff --git a/src/fakepackets.h b/src/fakepackets.h index de20c7e..9bb44d4 100644 --- a/src/fakepackets.h +++ b/src/fakepackets.h @@ -4,7 +4,8 @@ int send_fake_http_request(const HANDLE w_filter, const UINT packetLen, const BOOL is_ipv6, const BYTE set_ttl, - const BYTE set_checksum + const BYTE set_checksum, + const BYTE set_seq ); int send_fake_https_request(const HANDLE w_filter, const PWINDIVERT_ADDRESS addr, @@ -12,5 +13,6 @@ int send_fake_https_request(const HANDLE w_filter, const UINT packetLen, const BOOL is_ipv6, const BYTE set_ttl, - const BYTE set_checksum + const BYTE set_checksum, + const BYTE set_seq ); diff --git a/src/goodbyedpi.c b/src/goodbyedpi.c index a80b6e5..0b87ffe 100644 --- a/src/goodbyedpi.c +++ b/src/goodbyedpi.c @@ -125,6 +125,7 @@ static struct option long_options[] = { {"ip-id", required_argument, 0, 'i' }, {"set-ttl", required_argument, 0, '$' }, {"wrong-chksum",no_argument, 0, '%' }, + {"wrong-seq", no_argument, 0, ')' }, {"native-frag", no_argument, 0, '*' }, {"reverse-frag",no_argument, 0, '(' }, {0, 0, 0, 0 } @@ -453,6 +454,7 @@ int main(int argc, char *argv[]) { do_dns_verb = 0, do_blacklist = 0, do_fake_packet = 0, do_wrong_chksum = 0, + do_wrong_seq = 0, do_native_frag = 0, do_reverse_frag = 0; unsigned int http_fragment_size = 0; unsigned int https_fragment_size = 0; @@ -665,6 +667,10 @@ int main(int argc, char *argv[]) { do_fake_packet = 1; do_wrong_chksum = 1; break; + case ')': + do_fake_packet = 1; + do_wrong_seq = 1; + break; case '*': do_native_frag = 1; do_fragment_http_persistent = 1; @@ -703,6 +709,7 @@ int main(int argc, char *argv[]) { " --wrong-chksum activate Fake Request Mode and send it with incorrect TCP checksum.\n" " May not work in a VM or with some routers, but is safer than set-ttl.\n" " Could be combined with --set-ttl\n" + " --wrong-seq activate Fake Request Mode and send it with TCP SEQ/ACK in the past.\n" " --native-frag fragment (split) the packets by sending them in smaller packets, without\n" " shrinking the Window Size. Works faster (does not slow down the connection)\n" " and better.\n" @@ -730,13 +737,15 @@ int main(int argc, char *argv[]) { "Mix Host: %d\nHTTP AllPorts: %d\nHTTP Persistent Nowait: %d\n" "DNS redirect: %d\nDNSv6 redirect: %d\n" "Fake requests, TTL: %hu\nFake requests, wrong checksum: %d\n", + "Fake requests, wrong SEQ/ACK: %d\n", do_passivedpi, (do_fragment_http ? http_fragment_size : 0), (do_fragment_http_persistent ? http_fragment_size : 0), (do_fragment_https ? https_fragment_size : 0), do_native_frag, do_reverse_frag, do_host, do_host_removespace, do_additional_space, do_host_mixedcase, do_http_allports, do_fragment_http_persistent_nowait, do_dnsv4_redirect, - do_dnsv6_redirect, ttl_of_fake_packet, do_wrong_chksum + do_dnsv6_redirect, ttl_of_fake_packet, do_wrong_chksum, + do_wrong_seq ); if (do_fragment_http && http_fragment_size > 2) { @@ -863,7 +872,7 @@ int main(int argc, char *argv[]) { if (packet_dataLen >=2 && memcmp(packet_data, "\x16\x03", 2) == 0) { if (do_fake_packet) { send_fake_https_request(w_filter, &addr, packet, packetLen, packet_v6, - ttl_of_fake_packet, do_wrong_chksum); + ttl_of_fake_packet, do_wrong_chksum, do_wrong_seq); } if (do_native_frag) { // Signal for native fragmentation code handler @@ -899,7 +908,8 @@ int main(int argc, char *argv[]) { if (do_fake_packet) send_fake_http_request(w_filter, &addr, packet, packetLen, packet_v6, - ttl_of_fake_packet, do_wrong_chksum); + ttl_of_fake_packet, do_wrong_chksum, do_wrong_seq); + } if (do_host_mixedcase) { mix_case(host_addr, host_len);