diff --git a/README.md b/README.md index 22f0a0b..aa2db74 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Download [latest version from Releases page](https://github.com/ValdikSS/Goodbye ``` Usage: goodbyedpi.exe [OPTION...] -p block passive DPI + -q block QUIC/HTTP3 -r replace Host with hoSt -s remove space between host header and its value -m mix Host header case (test.com -> tEsT.cOm) @@ -77,8 +78,13 @@ LEGACY modesets: -4 -p -r -s (best speed) Modern modesets (more stable, more compatible, faster): - -5 -f 2 -e 2 --auto-ttl --reverse-frag --max-payload (this is the default) + -5 -f 2 -e 2 --auto-ttl --reverse-frag --max-payload -6 -f 2 -e 2 --wrong-seq --reverse-frag --max-payload + -7 -f 2 -e 2 --wrong-chksum --reverse-frag --max-payload + -8 -f 2 -e 2 --wrong-seq --wrong-chksum --reverse-frag --max-payload + -9 -f 2 -e 2 --wrong-seq --wrong-chksum --reverse-frag --max-payload -q (this is the default) + + Note: combination of --wrong-seq and --wrong-chksum generates two different fake packets. ``` To check if your ISP's DPI could be circumvented, first make sure that your provider does not poison DNS answers by enabling "Secure DNS (DNS over HTTPS)" option in your browser. diff --git a/src/fakepackets.c b/src/fakepackets.c index 6d59cd8..4b6bb92 100644 --- a/src/fakepackets.c +++ b/src/fakepackets.c @@ -11,41 +11,74 @@ static const unsigned char fake_http_request[] = "GET / HTTP/1.1\r\nHost: www.w3 "User-Agent: curl/7.65.3\r\nAccept: */*\r\n" "Accept-Encoding: deflate, gzip, br\r\n\r\n"; static const unsigned char fake_https_request[] = { - 0x16, 0x03, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0xfc, 0x03, 0x03, 0x9a, 0x8f, 0xa7, 0x6a, 0x5d, - 0x57, 0xf3, 0x62, 0x19, 0xbe, 0x46, 0x82, 0x45, 0xe2, 0x59, 0x5c, 0xb4, 0x48, 0x31, 0x12, 0x15, - 0x14, 0x79, 0x2c, 0xaa, 0xcd, 0xea, 0xda, 0xf0, 0xe1, 0xfd, 0xbb, 0x20, 0xf4, 0x83, 0x2a, 0x94, - 0xf1, 0x48, 0x3b, 0x9d, 0xb6, 0x74, 0xba, 0x3c, 0x81, 0x63, 0xbc, 0x18, 0xcc, 0x14, 0x45, 0x57, - 0x6c, 0x80, 0xf9, 0x25, 0xcf, 0x9c, 0x86, 0x60, 0x50, 0x31, 0x2e, 0xe9, 0x00, 0x22, 0x13, 0x01, - 0x13, 0x03, 0x13, 0x02, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x2c, 0xc0, 0x30, - 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x33, 0x00, 0x39, 0x00, 0x2f, 0x00, 0x35, - 0x01, 0x00, 0x01, 0x91, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0x00, 0x0a, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, - 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x01, 0x00, - 0x01, 0x01, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0e, - 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x00, 0x05, - 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x6b, 0x00, 0x69, 0x00, 0x1d, 0x00, - 0x20, 0xb0, 0xe4, 0xda, 0x34, 0xb4, 0x29, 0x8d, 0xd3, 0x5c, 0x70, 0xd3, 0xbe, 0xe8, 0xa7, 0x2a, - 0x6b, 0xe4, 0x11, 0x19, 0x8b, 0x18, 0x9d, 0x83, 0x9a, 0x49, 0x7c, 0x83, 0x7f, 0xa9, 0x03, 0x8c, - 0x3c, 0x00, 0x17, 0x00, 0x41, 0x04, 0x4c, 0x04, 0xa4, 0x71, 0x4c, 0x49, 0x75, 0x55, 0xd1, 0x18, - 0x1e, 0x22, 0x62, 0x19, 0x53, 0x00, 0xde, 0x74, 0x2f, 0xb3, 0xde, 0x13, 0x54, 0xe6, 0x78, 0x07, - 0x94, 0x55, 0x0e, 0xb2, 0x6c, 0xb0, 0x03, 0xee, 0x79, 0xa9, 0x96, 0x1e, 0x0e, 0x98, 0x17, 0x78, - 0x24, 0x44, 0x0c, 0x88, 0x80, 0x06, 0x8b, 0xd4, 0x80, 0xbf, 0x67, 0x7c, 0x37, 0x6a, 0x5b, 0x46, - 0x4c, 0xa7, 0x98, 0x6f, 0xb9, 0x22, 0x00, 0x2b, 0x00, 0x09, 0x08, 0x03, 0x04, 0x03, 0x03, 0x03, - 0x02, 0x03, 0x01, 0x00, 0x0d, 0x00, 0x18, 0x00, 0x16, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x08, - 0x04, 0x08, 0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x03, 0x02, 0x01, 0x00, - 0x2d, 0x00, 0x02, 0x01, 0x01, 0x00, 0x1c, 0x00, 0x02, 0x40, 0x01, 0x00, 0x15, 0x00, 0x96, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00 +0x16, 0x03, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, /* ........ */ +0xfc, 0x03, 0x03, 0xe4, 0x5d, 0x79, 0x60, 0xec, /* ....]y`. */ +0x73, 0xa8, 0xaf, 0xc0, 0x1b, 0x6e, 0xba, 0x51, /* s....n.Q */ +0xd4, 0x2f, 0x0c, 0xa9, 0xa3, 0xdf, 0xb0, 0xf4, /* ./...... */ +0x1e, 0x60, 0x1b, 0x71, 0x09, 0xfd, 0xd4, 0x6a, /* .`.q...j */ +0xca, 0x9f, 0xf6, 0x20, 0x3c, 0x6a, 0x0f, 0xfa, /* ... = 1200 " \ + "and udp.Payload[0] >= 0xC0 and udp.Payload32[1b] == 0x01" #define FILTER_PASSIVE_STRING_TEMPLATE "inbound and ip and tcp and " \ "!impostor and !loopback and " \ "((ip.Id <= 0xF and ip.Id >= 0x0) " IPID_TEMPLATE ") and " \ @@ -218,7 +221,10 @@ static void add_ip_id_str(int id) { static void add_maxpayloadsize_str(unsigned short maxpayload) { char *newstr; /* 0x47455420 is "GET ", 0x504F5354 is "POST", big endian. */ - const char *maxpayloadsize_str = "and (tcp.PayloadLength ? tcp.PayloadLength < %hu or tcp.Payload32[0] == 0x47455420 or tcp.Payload32[0] == 0x504F5354 : true)"; + const char *maxpayloadsize_str = + "and (tcp.PayloadLength ? tcp.PayloadLength < %hu " \ + "or tcp.Payload32[0] == 0x47455420 or tcp.Payload32[0] == 0x504F5354 " \ + "or (tcp.Payload[0] == 0x16 and tcp.Payload[1] == 0x03 and tcp.Payload[2] <= 0x03): true)"; char *addfilter = malloc(strlen(maxpayloadsize_str) + 16); sprintf(addfilter, maxpayloadsize_str, maxpayload); @@ -576,7 +582,8 @@ int main(int argc, char *argv[]) { conntrack_info_t dns_conn_info; tcp_conntrack_info_t tcp_conn_info; - int do_passivedpi = 0, do_fragment_http = 0, + int do_passivedpi = 0, do_block_quic = 0, + do_fragment_http = 0, do_fragment_http_persistent = 0, do_fragment_http_persistent_nowait = 0, do_fragment_https = 0, do_host = 0, @@ -648,17 +655,19 @@ int main(int argc, char *argv[]) { ); if (argc == 1) { - /* enable mode -5 by default */ + /* enable mode -9 by default */ do_fragment_http = do_fragment_https = 1; do_reverse_frag = do_native_frag = 1; http_fragment_size = https_fragment_size = 2; do_fragment_http_persistent = do_fragment_http_persistent_nowait = 1; do_fake_packet = 1; - do_auto_ttl = 1; + do_wrong_chksum = 1; + do_wrong_seq = 1; + do_block_quic = 1; max_payload_size = 1200; } - while ((opt = getopt_long(argc, argv, "123456prsaf:e:mwk:n", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "123456789pqrsaf:e:mwk:n", long_options, NULL)) != -1) { switch (opt) { case '1': do_passivedpi = do_host = do_host_removespace \ @@ -699,9 +708,27 @@ int main(int argc, char *argv[]) { do_wrong_seq = 1; max_payload_size = 1200; break; + case '9': // +7+8 + do_block_quic = 1; + // fall through + case '8': // +7 + do_wrong_seq = 1; + // fall through + case '7': + do_fragment_http = do_fragment_https = 1; + do_reverse_frag = do_native_frag = 1; + http_fragment_size = https_fragment_size = 2; + do_fragment_http_persistent = do_fragment_http_persistent_nowait = 1; + do_fake_packet = 1; + do_wrong_chksum = 1; + max_payload_size = 1200; + break; case 'p': do_passivedpi = 1; break; + case 'q': + do_block_quic = 1; + break; case 'r': do_host = 1; break; @@ -901,6 +928,7 @@ int main(int argc, char *argv[]) { default: puts("Usage: goodbyedpi.exe [OPTION...]\n" " -p block passive DPI\n" + " -q block QUIC/HTTP3\n" " -r replace Host with hoSt\n" " -s remove space between host header and its value\n" " -a additional space between Method and Request-URI (enables -s, may break sites)\n" @@ -955,8 +983,13 @@ int main(int argc, char *argv[]) { " -4 -p -r -s (best speed)" "\n" "Modern modesets (more stable, more compatible, faster):\n" - " -5 -f 2 -e 2 --auto-ttl --reverse-frag --max-payload (this is the default)\n" - " -6 -f 2 -e 2 --wrong-seq --reverse-frag --max-payload\n"); + " -5 -f 2 -e 2 --auto-ttl --reverse-frag --max-payload\n" + " -6 -f 2 -e 2 --wrong-seq --reverse-frag --max-payload\n" + " -7 -f 2 -e 2 --wrong-chksum --reverse-frag --max-payload\n" + " -8 -f 2 -e 2 --wrong-seq --wrong-chksum --reverse-frag --max-payload\n" + " -9 -f 2 -e 2 --wrong-seq --wrong-chksum --reverse-frag --max-payload -q (this is the default)\n\n" + "Note: combination of --wrong-seq and --wrong-chksum generates two different fake packets.\n" + ); exit(EXIT_FAILURE); } } @@ -977,6 +1010,7 @@ int main(int argc, char *argv[]) { } printf("Block passive: %d\n" /* 1 */ + "Block QUIC/HTTP3: %d\n" /* 1 */ "Fragment HTTP: %u\n" /* 2 */ "Fragment persistent HTTP: %u\n" /* 3 */ "Fragment HTTPS: %u\n" /* 4 */ @@ -996,7 +1030,7 @@ int main(int argc, char *argv[]) { "Fake requests, wrong checksum: %d\n" /* 18 */ "Fake requests, wrong SEQ/ACK: %d\n" /* 19 */ "Max payload size: %hu\n", /* 20 */ - do_passivedpi, /* 1 */ + do_passivedpi, do_block_quic, /* 1 */ (do_fragment_http ? http_fragment_size : 0), /* 2 */ (do_fragment_http_persistent ? http_fragment_size : 0),/* 3 */ (do_fragment_https ? https_fragment_size : 0), /* 4 */ @@ -1048,6 +1082,15 @@ int main(int argc, char *argv[]) { filter_num++; } + if (do_block_quic) { + filters[filter_num] = init( + FILTER_PASSIVE_BLOCK_QUIC, + WINDIVERT_FLAG_DROP); + if (filters[filter_num] == NULL) + die(); + filter_num++; + } + /* * IPv4 & IPv6 filter for inbound HTTP redirection packets and * active DPI circumvention