From 916d575920d0b03a5ca3186c2b69254c3561324f Mon Sep 17 00:00:00 2001 From: zabbius Date: Fri, 9 Aug 2024 15:21:54 +0300 Subject: [PATCH 1/6] parsing args with getopt --- youtubeUnblock.c | 297 ++++++++++++++++++++++------------------------- 1 file changed, 137 insertions(+), 160 deletions(-) diff --git a/youtubeUnblock.c b/youtubeUnblock.c index 118553b..b8bc4a7 100644 --- a/youtubeUnblock.c +++ b/youtubeUnblock.c @@ -26,6 +26,9 @@ #include #include +#include +#include + #include "config.h" #include "mangle.h" @@ -59,34 +62,7 @@ struct config_t config = { .domains_strlen = sizeof(defaul_snistr), }; -const char* get_value(const char *option, const char *prefix) -{ - errno = 0; - - size_t prefix_len = strlen(prefix); - size_t option_len = strlen(option); - - if (option_len <= prefix_len || strncmp(prefix, option, prefix_len)) { - return NULL; - } - - return option + prefix_len; -} - -int parse_bool_option(const char *value) { - errno = 0; - if (strcmp(value, "1") == 0) { - return 1; - } - else if (strcmp(value, "0") == 0) { - return 0; - } - - errno = EINVAL; - return -1; -} - -long parse_numeric_option(const char* value) { +static long parse_numeric_option(const char* value) { errno = 0; char* end; @@ -99,135 +75,12 @@ long parse_numeric_option(const char* value) { return result; } -int parse_option(const char* option) { - const char* value; - int ret; - - if (!strcmp(option, "--no-gso")) { - config.use_gso = 0; - goto out; - } - - if (!strcmp(option, "--silent")) { - config.verbose = 0; - goto out; - } - - if ((value = get_value(option, "--sni-domains")) != 0) { - if (!value) { - goto err; - } - - if (strcmp(value, "all")) { - config.all_domains = 1; - } - - config.domains_str = value; - config.domains_strlen = strlen(value); - - goto out; - } - - if ((value = get_value(option, "--frag=")) != 0) { - if (!value) { - goto err; - } - - if (strcmp(value, "tcp") == 0) { - config.fragmentation_strategy = FRAG_STRAT_TCP; - } else if (strcmp(value, "ip") == 0) { - config.fragmentation_strategy = FRAG_STRAT_IP; - } else if (strcmp(value, "none") == 0) { - config.fragmentation_strategy = FRAG_STRAT_NONE; - } else { - goto err; - } - - goto out; - } - - if ((value = get_value(option, "--fake-sni=")) != 0) { - if (strcmp(value, "ack") == 0) { - config.fake_sni_strategy = FKSN_STRAT_ACK_SEQ; - } else if (strcmp(value, "ttl") == 0) { - config.fake_sni_strategy = FKSN_STRAT_TTL; - } - else if (strcmp(value, "none") == 0) { - config.fake_sni_strategy = FKSN_STRAT_NONE; - } else { - goto err; - } - - goto out; - } - - if ((value = get_value(option, "--seg2delay=")) != 0) { - long num = parse_numeric_option(value); - if (errno != 0 || - num < 0) - goto err; - - config.seg2_delay = num; - goto out; - } - - if ((value = get_value(option, "--threads=")) != 0) { - long num = parse_numeric_option(value); - if (errno != 0 || - num < 0 || - num > MAX_THREADS) { - errno = EINVAL; - goto err; - } - - config.threads = num; - goto out; - } - - if ((value = get_value(option, "--fake-sni-ttl=")) != 0) { - long num = parse_numeric_option(value); - if (errno != 0 || - num < 0 || - num > 255) { - goto err; - } - - config.fake_sni_ttl = num; - goto out; - } - -err: - errno = EINVAL; - return -1; -out: - errno = 0; - return 0; +static void print_version() { + printf("Youtube unblocker v0.0.1\n"); //TODO } -static int parse_args(int argc, const char *argv[]) { - int err; - char *end; - - if (argc < 2) { - errno = EINVAL; - goto errormsg_help; - } - - config.queue_start_num = parse_numeric_option(argv[1]); - if (errno != 0) goto errormsg_help; - - for (int i = 2; i < argc; i++) { - if (parse_option(argv[i])) { - printf("Invalid option %s\n", argv[i]); - goto errormsg_help; - } - } - - return 0; - -errormsg_help: - err = errno; - printf("Usage: %s [OPTIONS]\n", argv[0]); +static void print_usage(const char *argv0) { + printf("Usage: %s [ OPTIONS ] \n", argv0); printf("Options:\n"); printf("\t--sni-domains=|all\n"); printf("\t--fake-sni={ack,ttl,none}\n"); @@ -237,10 +90,131 @@ errormsg_help: printf("\t--threads=\n"); printf("\t--silent\n"); printf("\t--no-gso\n"); - errno = err; - if (errno == 0) errno = EINVAL; +} - return -1; +#define OPT_SNI_DOMAINS 1 +#define OPT_FAKE_SNI 2 +#define OPT_FAKE_SNI_TTL 3 +#define OPT_FRAG 4 +#define OPT_SEG2DELAY 5 +#define OPT_THREADS 6 +#define OPT_SILENT 7 +#define OPT_NO_GSO 8 + +static struct option long_opt[] = { + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'v'}, + {"sni-domains", 1, 0, OPT_SNI_DOMAINS}, + {"fake-sni", 1, 0, OPT_FAKE_SNI}, + {"fake-sni-ttl", 1, 0, OPT_FAKE_SNI_TTL}, + {"frag", 1, 0, OPT_FRAG}, + {"seg2delay", 1, 0, OPT_SEG2DELAY}, + {"threads", 1, 0, OPT_THREADS}, + {"silent", 0, 0, OPT_SILENT}, + {"no-gso", 0, 0, OPT_NO_GSO}, + {0,0,0,0} + }; + +static int parse_args(int argc, const char *argv[]) { + int opt; + int optIdx; + long num; + + if (argc < 2) { + print_usage(argv[0]); + errno = EINVAL; + return -1; + } + + while ((opt = getopt_long(argc, argv, "hv", long_opt, &optIdx)) != -1) { + switch (opt) { + case 'h': + print_usage(argv[0]); + errno = 0; + return 1; + case 'v': + print_version(); + errno = 0; + return 1; + case OPT_SILENT: + config.verbose = 0; + break; + case OPT_NO_GSO: + config.use_gso = 0; + break; + case OPT_SNI_DOMAINS: + + if (strcmp(optarg, "all")) { + config.all_domains = 1; + } + config.domains_str = optarg; + config.domains_strlen = strlen(config.domains_str); + + break; + case OPT_FRAG: + if (strcmp(optarg, "tcp") == 0) { + config.fragmentation_strategy = FRAG_STRAT_TCP; + } else if (strcmp(optarg, "ip") == 0) { + config.fragmentation_strategy = FRAG_STRAT_IP; + } else if (strcmp(optarg, "none") == 0) { + config.fragmentation_strategy = FRAG_STRAT_NONE; + } else { + errno = EINVAL; + printf("Invalid option %s\n", long_opt[optIdx].name); + return -1; + } + break; + case OPT_FAKE_SNI: + if (strcmp(optarg, "ack") == 0) { + config.fake_sni_strategy = FKSN_STRAT_ACK_SEQ; + } else if (strcmp(optarg, "ttl") == 0) { + config.fake_sni_strategy = FKSN_STRAT_TTL; + } else if (strcmp(optarg, "none") == 0) { + config.fake_sni_strategy = FKSN_STRAT_NONE; + } else { + errno = EINVAL; + printf("Invalid option %s\n", long_opt[optIdx].name); + return -1; + } + break; + case OPT_SEG2DELAY: + num = parse_numeric_option(optarg); + if (errno != 0 || num < 0) { + printf("Invalid option %s\n", long_opt[optIdx].name); + return -1; + } + config.seg2_delay = num; + break; + case OPT_THREADS: + num = parse_numeric_option(optarg); + if (errno != 0 || num < 0 || num > MAX_THREADS) { + printf("Invalid option %s\n", long_opt[optIdx].name); + return -1; + } + config.threads = num; + break; + case OPT_FAKE_SNI_TTL: + num = parse_numeric_option(optarg); + if (errno != 0 || num < 0 || num > 255) { + printf("Invalid option %s\n", long_opt[optIdx].name); + return -1; + } + config.fake_sni_ttl = num; + break; + default: + printf("Invalid option %s\n", long_opt[optIdx].name); + errno = EINVAL; + return -1; + } + } + + config.queue_start_num = parse_numeric_option(argv[optind]); + if (errno != 0) { + printf("Invalid queue numbmer\n"); + return -1; + } + + return 0; } static int open_socket(struct mnl_socket **_nl) { @@ -788,8 +762,11 @@ void *init_queue_wrapper(void *qdconf) { int main(int argc, const char *argv[]) { if (parse_args(argc, argv)) { - perror("Unable to parse args"); - exit(EXIT_FAILURE); + if (errno) { + perror("Unable to parse args"); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); } switch (config.fragmentation_strategy) { From 46e4231f7e83616d2ed71d5d935c0be33984622f Mon Sep 17 00:00:00 2001 From: zabbius Date: Fri, 9 Aug 2024 15:31:04 +0300 Subject: [PATCH 2/6] minor --- youtubeUnblock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/youtubeUnblock.c b/youtubeUnblock.c index b8bc4a7..3451efa 100644 --- a/youtubeUnblock.c +++ b/youtubeUnblock.c @@ -210,7 +210,7 @@ static int parse_args(int argc, const char *argv[]) { config.queue_start_num = parse_numeric_option(argv[optind]); if (errno != 0) { - printf("Invalid queue numbmer\n"); + printf("Invalid queue number\n"); return -1; } @@ -787,10 +787,10 @@ int main(int argc, const char *argv[]) { switch (config.fake_sni_strategy) { case FKSN_STRAT_TTL: - printf("Fake SNI will be sent before each googlevideo request, TTL strategy will be used with TTL %d\n", config.fake_sni_ttl); + printf("Fake SNI will be sent before each request, TTL strategy will be used with TTL %d\n", config.fake_sni_ttl); break; case FRAG_STRAT_IP: - printf("Fake SNI will be sent before each googlevideo request, Ack-Seq strategy will be used\n"); + printf("Fake SNI will be sent before each request, Ack-Seq strategy will be used\n"); break; default: printf("SNI fragmentation is disabled\n"); From 4963258c0bc04d0d80908f139cbb3e35d5aa0177 Mon Sep 17 00:00:00 2001 From: zabbius Date: Fri, 9 Aug 2024 15:40:04 +0300 Subject: [PATCH 3/6] const char* argv[] -> char* argv[] --- youtubeUnblock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtubeUnblock.c b/youtubeUnblock.c index 3451efa..cbaf5de 100644 --- a/youtubeUnblock.c +++ b/youtubeUnblock.c @@ -115,7 +115,7 @@ static struct option long_opt[] = { {0,0,0,0} }; -static int parse_args(int argc, const char *argv[]) { +static int parse_args(int argc, char *argv[]) { int opt; int optIdx; long num; @@ -760,7 +760,7 @@ void *init_queue_wrapper(void *qdconf) { return thres; } -int main(int argc, const char *argv[]) { +int main(int argc, char *argv[]) { if (parse_args(argc, argv)) { if (errno) { perror("Unable to parse args"); From 8d4fb1f7ad9a91d7eb2744762db8e3ecd3835ca0 Mon Sep 17 00:00:00 2001 From: Vadim Vetrov Date: Fri, 9 Aug 2024 15:58:52 +0300 Subject: [PATCH 4/6] Fix coding style of args parser --- youtubeUnblock.c | 118 ++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 53 deletions(-) diff --git a/youtubeUnblock.c b/youtubeUnblock.c index cbaf5de..9334f42 100644 --- a/youtubeUnblock.c +++ b/youtubeUnblock.c @@ -80,7 +80,9 @@ static void print_version() { } static void print_usage(const char *argv0) { - printf("Usage: %s [ OPTIONS ] \n", argv0); + print_version(); + + printf("Usage: %s [ OPTIONS ] \n", argv0); printf("Options:\n"); printf("\t--sni-domains=|all\n"); printf("\t--fake-sni={ack,ttl,none}\n"); @@ -90,30 +92,31 @@ static void print_usage(const char *argv0) { printf("\t--threads=\n"); printf("\t--silent\n"); printf("\t--no-gso\n"); + printf("\n"); } -#define OPT_SNI_DOMAINS 1 +#define OPT_SNI_DOMAINS 1 #define OPT_FAKE_SNI 2 -#define OPT_FAKE_SNI_TTL 3 +#define OPT_FAKE_SNI_TTL 3 #define OPT_FRAG 4 #define OPT_SEG2DELAY 5 #define OPT_THREADS 6 -#define OPT_SILENT 7 -#define OPT_NO_GSO 8 +#define OPT_SILENT 7 +#define OPT_NO_GSO 8 static struct option long_opt[] = { - {"help", 0, 0, 'h'}, - {"version", 0, 0, 'v'}, - {"sni-domains", 1, 0, OPT_SNI_DOMAINS}, - {"fake-sni", 1, 0, OPT_FAKE_SNI}, - {"fake-sni-ttl", 1, 0, OPT_FAKE_SNI_TTL}, - {"frag", 1, 0, OPT_FRAG}, - {"seg2delay", 1, 0, OPT_SEG2DELAY}, - {"threads", 1, 0, OPT_THREADS}, - {"silent", 0, 0, OPT_SILENT}, - {"no-gso", 0, 0, OPT_NO_GSO}, - {0,0,0,0} - }; + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'v'}, + {"sni-domains", 1, 0, OPT_SNI_DOMAINS}, + {"fake-sni", 1, 0, OPT_FAKE_SNI}, + {"fake-sni-ttl", 1, 0, OPT_FAKE_SNI_TTL}, + {"frag", 1, 0, OPT_FRAG}, + {"seg2delay", 1, 0, OPT_SEG2DELAY}, + {"threads", 1, 0, OPT_THREADS}, + {"silent", 0, 0, OPT_SILENT}, + {"no-gso", 0, 0, OPT_NO_GSO}, + {0,0,0,0} +}; static int parse_args(int argc, char *argv[]) { int opt; @@ -121,21 +124,19 @@ static int parse_args(int argc, char *argv[]) { long num; if (argc < 2) { - print_usage(argv[0]); + print_usage(argv[0]); errno = EINVAL; return -1; } while ((opt = getopt_long(argc, argv, "hv", long_opt, &optIdx)) != -1) { switch (opt) { - case 'h': - print_usage(argv[0]); - errno = 0; - return 1; - case 'v': - print_version(); - errno = 0; - return 1; + case 'h': + print_usage(argv[0]); + goto out; + case 'v': + print_version(); + goto out; case OPT_SILENT: config.verbose = 0; break; @@ -143,29 +144,29 @@ static int parse_args(int argc, char *argv[]) { config.use_gso = 0; break; case OPT_SNI_DOMAINS: - if (strcmp(optarg, "all")) { config.all_domains = 1; } config.domains_str = optarg; config.domains_strlen = strlen(config.domains_str); + printf("asdffdsa\n"); break; - case OPT_FRAG: - if (strcmp(optarg, "tcp") == 0) { + case OPT_FRAG: + if (strcmp(optarg, "tcp") == 0) { config.fragmentation_strategy = FRAG_STRAT_TCP; } else if (strcmp(optarg, "ip") == 0) { config.fragmentation_strategy = FRAG_STRAT_IP; } else if (strcmp(optarg, "none") == 0) { config.fragmentation_strategy = FRAG_STRAT_NONE; } else { - errno = EINVAL; - printf("Invalid option %s\n", long_opt[optIdx].name); - return -1; + printf("Invalid option %s\n", long_opt[optIdx].name); + goto error; } + break; - case OPT_FAKE_SNI: - if (strcmp(optarg, "ack") == 0) { + case OPT_FAKE_SNI: + if (strcmp(optarg, "ack") == 0) { config.fake_sni_strategy = FKSN_STRAT_ACK_SEQ; } else if (strcmp(optarg, "ttl") == 0) { config.fake_sni_strategy = FKSN_STRAT_TTL; @@ -173,48 +174,59 @@ static int parse_args(int argc, char *argv[]) { config.fake_sni_strategy = FKSN_STRAT_NONE; } else { errno = EINVAL; - printf("Invalid option %s\n", long_opt[optIdx].name); - return -1; + printf("Invalid option %s\n", long_opt[optIdx].name); + goto error; } + break; case OPT_SEG2DELAY: - num = parse_numeric_option(optarg); + num = parse_numeric_option(optarg); if (errno != 0 || num < 0) { - printf("Invalid option %s\n", long_opt[optIdx].name); - return -1; - } + printf("Invalid option %s\n", long_opt[optIdx].name); + goto error; + } + config.seg2_delay = num; break; - case OPT_THREADS: + case OPT_THREADS: num = parse_numeric_option(optarg); if (errno != 0 || num < 0 || num > MAX_THREADS) { - printf("Invalid option %s\n", long_opt[optIdx].name); - return -1; - } + printf("Invalid option %s\n", long_opt[optIdx].name); + goto error; + } + config.threads = num; break; - case OPT_FAKE_SNI_TTL: + case OPT_FAKE_SNI_TTL: num = parse_numeric_option(optarg); if (errno != 0 || num < 0 || num > 255) { - printf("Invalid option %s\n", long_opt[optIdx].name); - return -1; - } + printf("Invalid option %s\n", long_opt[optIdx].name); + goto error; + } + config.fake_sni_ttl = num; break; default: - printf("Invalid option %s\n", long_opt[optIdx].name); - errno = EINVAL; - return -1; - } + printf("Invalid option %s\n", long_opt[optIdx].name); + goto error; + } } config.queue_start_num = parse_numeric_option(argv[optind]); if (errno != 0) { printf("Invalid queue number\n"); - return -1; + goto error; } + errno = 0; return 0; +out: + errno = 0; + return 1; +error: + print_usage(argv[0]); + errno = EINVAL; + return -1; } static int open_socket(struct mnl_socket **_nl) { From 6bbeae3876984932e53f35c015a3771b6393cae0 Mon Sep 17 00:00:00 2001 From: Vadim Vetrov Date: Sat, 10 Aug 2024 00:35:36 +0300 Subject: [PATCH 5/6] Update version output --- youtubeUnblock.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/youtubeUnblock.c b/youtubeUnblock.c index 9334f42..9342027 100644 --- a/youtubeUnblock.c +++ b/youtubeUnblock.c @@ -76,7 +76,8 @@ static long parse_numeric_option(const char* value) { } static void print_version() { - printf("Youtube unblocker v0.0.1\n"); //TODO + printf("youtubeUnblock\n"); + printf("Bypasses youtube detection systems that relies on SNI\n"); } static void print_usage(const char *argv0) { @@ -773,8 +774,9 @@ void *init_queue_wrapper(void *qdconf) { } int main(int argc, char *argv[]) { - if (parse_args(argc, argv)) { - if (errno) { + int ret; + if ((ret = parse_args(argc, argv)) != 0) { + if (ret < 0) { perror("Unable to parse args"); exit(EXIT_FAILURE); } From 8e592d8957f74be65b8f5a563e7f25f8dce956bf Mon Sep 17 00:00:00 2001 From: Vadim Vetrov Date: Sat, 10 Aug 2024 00:40:31 +0300 Subject: [PATCH 6/6] Fix segfault on unrecognized option --- youtubeUnblock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/youtubeUnblock.c b/youtubeUnblock.c index 9342027..21ad485 100644 --- a/youtubeUnblock.c +++ b/youtubeUnblock.c @@ -65,6 +65,11 @@ struct config_t config = { static long parse_numeric_option(const char* value) { errno = 0; + if (*value == '\0') { + errno = EINVAL; + return 0; + } + char* end; long result = strtol(value, &end, 10); if (*end != '\0') { @@ -208,7 +213,6 @@ static int parse_args(int argc, char *argv[]) { config.fake_sni_ttl = num; break; default: - printf("Invalid option %s\n", long_opt[optIdx].name); goto error; } }