From 0126e403fd3b04d562bead1c751dfab34d4f0ed9 Mon Sep 17 00:00:00 2001 From: Vadim Vetrov Date: Sat, 10 Aug 2024 21:38:25 +0300 Subject: [PATCH] Do not force user to specify queue number explicitly --- README.md | 1 + config.h | 2 ++ uspace.mk | 2 +- youtubeUnblock.c | 82 +++++++++++++++++++++++++++++++----------------- 4 files changed, 58 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index e26975e..d142402 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Also DNS over HTTPS (DOH) is preferred for additional anonimity. ## Flags Available flags: +- `--queue-num=` - The number of netfilter queue youtubeUnblock will be linked to. Defaults to 537. - `--sni-domains=|all` - List of domains you want to be handled by sni. Use this string if you want to change default domains. Defaults to `googlevideo.com,youtube.com,ggpht.com,ytimg.com`. You can pass all if you want for every Client Hello to be handled. - `--seg2delay=` - This flag forces youtubeUnblock to wait little bit before send the 2nd part of the split packet. - `--fake-sni={ack,ttl, none}` This flag enables fake-sni which forces youtubeUnblock to send at least three packets instead of one with TLS ClientHello: Fake ClientHello, 1st part of original ClientHello, 2nd part of original ClientHello. This flag may be related to some Operation not permitted error messages, so befor open an issue refer to FAQ for EPERMS. Note, that this flag is set to `ack` by default. You may disable fake sni by setting it to `none`. Note, that your ISP may have conntrack drop on invalid state enabled, so this flag won't work. Use `ttl` to escape that. diff --git a/config.h b/config.h index 8f6def4..28b59c6 100644 --- a/config.h +++ b/config.h @@ -70,4 +70,6 @@ extern struct config_t config; // Larger packets will be fragmented. Applicable for Chrome's kyber. #define AVAILABLE_MTU 1384 +#define DEFAULT_QUEUE_NUM 537 + static const char defaul_snistr[] = "googlevideo.com,ggpht.com,ytimg.com,youtube.com,play.google.com,youtu.be,googleapis.com,googleusercontent.com,gstatic.com,l.google.com"; diff --git a/uspace.mk b/uspace.mk index afb58f1..5aaa254 100644 --- a/uspace.mk +++ b/uspace.mk @@ -34,7 +34,7 @@ LIBNETFILTER_QUEUE := $(DEPSDIR)/lib/libnetfilter_queue.a default: all run_dev: dev - bash -c "sudo $(APP) 537" + bash -c "sudo $(APP)" dev: dev_attrs all diff --git a/youtubeUnblock.c b/youtubeUnblock.c index 4f1cf42..dbf04e3 100644 --- a/youtubeUnblock.c +++ b/youtubeUnblock.c @@ -60,6 +60,8 @@ struct config_t config = { #endif .domains_str = defaul_snistr, .domains_strlen = sizeof(defaul_snistr), + + .queue_start_num = DEFAULT_QUEUE_NUM, }; static long parse_numeric_option(const char* value) { @@ -88,8 +90,9 @@ static void print_version() { static void print_usage(const char *argv0) { print_version(); - printf("Usage: %s [ OPTIONS ] \n", argv0); + printf("Usage: %s [ OPTIONS ] \n", argv0); printf("Options:\n"); + printf("\t--queue-num=\n"); printf("\t--sni-domains=|all\n"); printf("\t--fake-sni={ack,ttl,none}\n"); printf("\t--fake-sni-ttl=\n"); @@ -109,6 +112,7 @@ static void print_usage(const char *argv0) { #define OPT_THREADS 6 #define OPT_SILENT 7 #define OPT_NO_GSO 8 +#define OPT_QUEUE_NUM 9 static struct option long_opt[] = { {"help", 0, 0, 'h'}, @@ -121,6 +125,7 @@ static struct option long_opt[] = { {"threads", 1, 0, OPT_THREADS}, {"silent", 0, 0, OPT_SILENT}, {"no-gso", 0, 0, OPT_NO_GSO}, + {"queue-num", 1, 0, OPT_QUEUE_NUM}, {0,0,0,0} }; @@ -129,12 +134,6 @@ static int parse_args(int argc, char *argv[]) { 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': @@ -155,7 +154,6 @@ static int parse_args(int argc, char *argv[]) { } config.domains_str = optarg; config.domains_strlen = strlen(config.domains_str); - printf("asdffdsa\n"); break; case OPT_FRAG: @@ -212,16 +210,21 @@ static int parse_args(int argc, char *argv[]) { config.fake_sni_ttl = num; break; + case OPT_QUEUE_NUM: + num = parse_numeric_option(optarg); + if (errno != 0 || num < 0) { + printf("Invalid option %s\n", long_opt[optIdx].name); + goto error; + } + + config.queue_start_num = num; + break; default: goto error; } } - config.queue_start_num = parse_numeric_option(argv[optind]); - if (errno != 0) { - printf("Invalid queue number\n"); - goto error; - } + errno = 0; return 0; @@ -496,7 +499,6 @@ static int process_packet(const struct packet_data packet, struct queue_data qda goto fallback; } - struct verdict vrd = analyze_tls_data(data, dlen); verdnlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, qdata.queue_num); @@ -523,21 +525,45 @@ static int process_packet(const struct packet_data packet, struct queue_data qda (struct tcphdr *)tcph, (struct iphdr *)iph); if (config.fake_sni_strategy != FKSN_STRAT_NONE) { - uint8_t fake_sni[MNL_SOCKET_BUFFER_SIZE]; - uint32_t fsn_len = MNL_SOCKET_BUFFER_SIZE; + uint8_t rfsiph[60]; + uint8_t rfstcph[60]; - ret = gen_fake_sni(iph, tcph, fake_sni, &fsn_len); - if (ret < 0) { - errno = -ret; - perror("gen_fake_sni"); - goto fallback; - } + memcpy(rfsiph, iph, iph_len); + memcpy(rfstcph, tcph, tcph_len); + + struct iphdr *fsiph = (void *)rfsiph; + struct tcphdr *fstcph = (void *)rfstcph; + + for (int i = 0; i < 10; i++) { + uint8_t fake_sni[MNL_SOCKET_BUFFER_SIZE]; + uint32_t fsn_len = MNL_SOCKET_BUFFER_SIZE; + ret = gen_fake_sni(fsiph, fstcph, fake_sni, &fsn_len); + if (ret < 0) { + errno = -ret; + perror("gen_fake_sni"); + goto fallback; + } + + printf("%d\n", i); + ret = send_raw_socket(fake_sni, fsn_len); + if (ret < 0) { + errno = -ret; + perror("send fake sni"); + goto fallback; + } + + uint32_t iph_len; + uint32_t tcph_len; + uint32_t plen; + tcp4_payload_split(fake_sni, fsn_len, &fsiph, &iph_len, &fstcph, &tcph_len, NULL, &plen); + + + fstcph->seq = htonl(ntohl(tcph->seq) + plen * (i + 1)); + memcpy(rfsiph, fsiph, iph_len); + memcpy(rfstcph, fstcph, tcph_len); + fsiph = (void *)rfsiph; + fstcph = (void *)rfstcph; - ret = send_raw_socket(fake_sni, fsn_len); - if (ret < 0) { - errno = -ret; - perror("send fake sni"); - goto fallback; } } @@ -731,7 +757,7 @@ int init_queue(int queue_num) { .queue_num = queue_num }; - printf("Queue %d started!\n", qdata.queue_num); + printf("Queue %d started\n", qdata.queue_num); while (1) { ret = mnl_socket_recvfrom(nl, buf, BUF_SIZE);