From d9955d78aa079065acf92fa6420657b48442bbd3 Mon Sep 17 00:00:00 2001 From: Tarik Date: Sat, 23 May 2026 11:51:15 +0300 Subject: [PATCH] Fixing errors regarding whitelisting feature. --- README.md | 2 +- src/blackwhitelist.c | 12 +++++---- src/goodbyedpi.c | 58 +++++++++++++++++++++++++++++++------------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 9d04c6b..3db22bf 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Usage: goodbyedpi.exe [OPTION...] --blacklist perform circumvention tricks only to host names and subdomains from supplied text file (HTTP Host/TLS SNI). This option can be supplied multiple times. - --whitelist does not perform circumvention tricks to host names and subdomains from + --whitelist do not perform circumvention tricks to host names and subdomains from supplied text file. This option can be supplied multiple times. --allow-no-sni perform circumvention if TLS SNI can't be detected with --blacklist enabled. diff --git a/src/blackwhitelist.c b/src/blackwhitelist.c index a69f9ca..5062d77 100644 --- a/src/blackwhitelist.c +++ b/src/blackwhitelist.c @@ -1,5 +1,5 @@ /* - * Blacklist for GoodbyeDPI HTTP DPI circumvention tricks + * Blacklist and whitelist for GoodbyeDPI HTTP DPI circumvention tricks * * This is a simple domain hash table. * Domain records are added from a text file, where every @@ -71,15 +71,18 @@ static int blackwhitelist_load_list(const char *filename, blackwhitelist_record_ line); continue; } - if (strlen(line) < 2) { - printf("WARNING: host %s is less than 2 characters, skipping\n", line); + if (strlen(line) < 3) { + printf("WARNING: host %s is less than 3 bytes, skipping\n", line); continue; } if (add_hostname(line, list)) cnt++; } free(line); - if (!*list) return FALSE; + if (!*list) { + fclose(fp); + return FALSE; + } printf("Loaded %d hosts from file %s\n", cnt, filename); fclose(fp); return TRUE; @@ -108,7 +111,6 @@ static int blackwhitelist_check_hostname(const char *host_addr, size_t host_len, tokenized_host = strchr(current_host, '.'); while (tokenized_host != NULL && tokenized_host < (current_host + HOST_MAXLEN)) { - /* Search hostname only if there is next token */ if (strchr(tokenized_host + 1, '.') && check_get_hostname(tokenized_host + 1, list)) return TRUE; tokenized_host = strchr(tokenized_host + 1, '.'); diff --git a/src/goodbyedpi.c b/src/goodbyedpi.c index 31e5d01..975e7e6 100644 --- a/src/goodbyedpi.c +++ b/src/goodbyedpi.c @@ -177,7 +177,7 @@ static struct option long_options[] = { {"dnsv6-port", required_argument, 0, '@' }, {"dns-verb", no_argument, 0, 'v' }, {"blacklist", required_argument, 0, 'b' }, - {"whitelist", required_argument, 0, 't' }, + {"whitelist", required_argument, 0, 'W' }, {"allow-no-sni",no_argument, 0, ']' }, {"frag-by-sni", no_argument, 0, '>' }, {"ip-id", required_argument, 0, 'i' }, @@ -267,6 +267,36 @@ static void finalize_filter_strings() { filter_passive_string = newstr; } +static int host_is_circumvented(int do_blacklist, int do_whitelist, int do_allow_no_sni, + int sni_ok, const char *host_addr, size_t host_len) { + int host_blacklisted = 1; + int host_whitelisted = 0; + + if (do_blacklist || do_whitelist) { + if (sni_ok) { + if (do_blacklist) + host_blacklisted = blackwhitelist_check_hostname_blacklist(host_addr, host_len); + if (do_whitelist) + host_whitelisted = blackwhitelist_check_hostname_whitelist(host_addr, host_len); + } else { + host_blacklisted = 0; + } + + if (do_blacklist) { + if (!sni_ok) + return do_allow_no_sni; + return host_blacklisted && !host_whitelisted; + } + + if (!sni_ok) + return 0; + + return !host_whitelisted; + } + + return 1; +} + static char* dumb_memmem(const char* haystack, unsigned int hlen, const char* needle, unsigned int nlen) { @@ -688,7 +718,7 @@ int main(int argc, char *argv[]) { max_payload_size = 1200; } - while ((opt = getopt_long(argc, argv, "123456789pqrsaf:e:mwk:n", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "123456789pqrsaf:e:mwk:nW", long_options, NULL)) != -1) { switch (opt) { case '1': do_passivedpi = do_host = do_host_removespace \ @@ -867,14 +897,14 @@ int main(int argc, char *argv[]) { do_blacklist = 1; if (!blackwhitelist_load_blacklist(optarg)) { printf("Can't load blacklist from file!\n"); - exit(EXIT_FAILURE); + exit(ERROR_BLACKLIST_LOAD); } break; - case 't': // --whitelist + case 'W': // --whitelist do_whitelist = 1; if (!blackwhitelist_load_whitelist(optarg)) { printf("Can't load whitelist from file!\n"); - exit(EXIT_FAILURE); + exit(ERROR_BLACKLIST_LOAD); } break; case ']': // --allow-no-sni @@ -1003,7 +1033,7 @@ int main(int argc, char *argv[]) { " --blacklist perform circumvention tricks only to host names and subdomains from\n" " supplied text file (HTTP Host/TLS SNI).\n" " This option can be supplied multiple times.\n" - " --whitelist does not perform circumvention tricks to host names and subdomains from\n" + " --whitelist do not perform circumvention tricks to host names and subdomains from\n" " supplied text file.\n" " This option can be supplied multiple times.\n" " --allow-no-sni perform circumvention if TLS SNI can't be detected with --blacklist enabled.\n" @@ -1276,18 +1306,12 @@ int main(int argc, char *argv[]) { if ((packet_dataLen == 2 && memcmp(packet_data, "\x16\x03", 2) == 0) || (packet_dataLen >= 3 && ( memcmp(packet_data, "\x16\x03\x01", 3) == 0 || memcmp(packet_data, "\x16\x03\x03", 3) == 0 ))) { - if (do_blacklist || do_whitelist) { + if (do_blacklist || do_whitelist || do_fragment_by_sni) { sni_ok = extract_sni(packet_data, packet_dataLen, &host_addr, &host_len); } - if ( - ((do_blacklist && sni_ok && - blackwhitelist_check_hostname_blacklist(host_addr, host_len) - ) || - (do_blacklist && !sni_ok && do_allow_no_sni) || - (!do_blacklist)) && - (do_whitelist ? !blackwhitelist_check_hostname_whitelist(host_addr, host_len) : 1) - ) + if (host_is_circumvented(do_blacklist, do_whitelist, do_allow_no_sni, + sni_ok, host_addr, host_len)) { #ifdef DEBUG char lsni[HOST_MAXLEN + 1] = {0}; @@ -1322,8 +1346,8 @@ int main(int argc, char *argv[]) { if (find_header_and_get_info(packet_data, packet_dataLen, http_host_find, &hdr_name_addr, &hdr_value_addr, &hdr_value_len) && hdr_value_len > 0 && hdr_value_len <= HOST_MAXLEN && - (do_blacklist ? blackwhitelist_check_hostname_blacklist(hdr_value_addr, hdr_value_len) : 1) && - (do_whitelist ? !blackwhitelist_check_hostname_whitelist(hdr_value_addr, hdr_value_len) : 1)) + host_is_circumvented(do_blacklist, do_whitelist, 1, + 1, hdr_value_addr, hdr_value_len)) { host_addr = hdr_value_addr; host_len = hdr_value_len;