Do not force user to specify queue number explicitly

This commit is contained in:
Vadim Vetrov 2024-08-10 21:38:25 +03:00
parent e719c1319b
commit 74a9ae3eb1
No known key found for this signature in database
GPG Key ID: E8A308689D7A73A5
4 changed files with 58 additions and 29 deletions

View File

@ -47,6 +47,7 @@ Also DNS over HTTPS (DOH) is preferred for additional anonimity.
## Flags ## Flags
Available flags: Available flags:
- `--queue-num=<number of netfilter queue>` - The number of netfilter queue youtubeUnblock will be linked to. Defaults to 537.
- `--sni-domains=<comma separated domain list>|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. - `--sni-domains=<comma separated domain list>|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=<delay>` - This flag forces youtubeUnblock to wait little bit before send the 2nd part of the split packet. - `--seg2delay=<delay>` - 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. - `--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.

View File

@ -70,4 +70,6 @@ extern struct config_t config;
// Larger packets will be fragmented. Applicable for Chrome's kyber. // Larger packets will be fragmented. Applicable for Chrome's kyber.
#define AVAILABLE_MTU 1384 #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"; 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";

View File

@ -34,7 +34,7 @@ LIBNETFILTER_QUEUE := $(DEPSDIR)/lib/libnetfilter_queue.a
default: all default: all
run_dev: dev run_dev: dev
bash -c "sudo $(APP) 537" bash -c "sudo $(APP)"
dev: dev_attrs all dev: dev_attrs all

View File

@ -60,6 +60,8 @@ struct config_t config = {
#endif #endif
.domains_str = defaul_snistr, .domains_str = defaul_snistr,
.domains_strlen = sizeof(defaul_snistr), .domains_strlen = sizeof(defaul_snistr),
.queue_start_num = DEFAULT_QUEUE_NUM,
}; };
static long parse_numeric_option(const char* value) { static long parse_numeric_option(const char* value) {
@ -88,8 +90,9 @@ static void print_version() {
static void print_usage(const char *argv0) { static void print_usage(const char *argv0) {
print_version(); print_version();
printf("Usage: %s <queue_num> [ OPTIONS ] \n", argv0); printf("Usage: %s [ OPTIONS ] \n", argv0);
printf("Options:\n"); printf("Options:\n");
printf("\t--queue-num=<number of netfilter queue>\n");
printf("\t--sni-domains=<comma separated domain list>|all\n"); printf("\t--sni-domains=<comma separated domain list>|all\n");
printf("\t--fake-sni={ack,ttl,none}\n"); printf("\t--fake-sni={ack,ttl,none}\n");
printf("\t--fake-sni-ttl=<ttl>\n"); printf("\t--fake-sni-ttl=<ttl>\n");
@ -109,6 +112,7 @@ static void print_usage(const char *argv0) {
#define OPT_THREADS 6 #define OPT_THREADS 6
#define OPT_SILENT 7 #define OPT_SILENT 7
#define OPT_NO_GSO 8 #define OPT_NO_GSO 8
#define OPT_QUEUE_NUM 9
static struct option long_opt[] = { static struct option long_opt[] = {
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
@ -121,6 +125,7 @@ static struct option long_opt[] = {
{"threads", 1, 0, OPT_THREADS}, {"threads", 1, 0, OPT_THREADS},
{"silent", 0, 0, OPT_SILENT}, {"silent", 0, 0, OPT_SILENT},
{"no-gso", 0, 0, OPT_NO_GSO}, {"no-gso", 0, 0, OPT_NO_GSO},
{"queue-num", 1, 0, OPT_QUEUE_NUM},
{0,0,0,0} {0,0,0,0}
}; };
@ -129,12 +134,6 @@ static int parse_args(int argc, char *argv[]) {
int optIdx; int optIdx;
long num; long num;
if (argc < 2) {
print_usage(argv[0]);
errno = EINVAL;
return -1;
}
while ((opt = getopt_long(argc, argv, "hv", long_opt, &optIdx)) != -1) { while ((opt = getopt_long(argc, argv, "hv", long_opt, &optIdx)) != -1) {
switch (opt) { switch (opt) {
case 'h': case 'h':
@ -155,7 +154,6 @@ static int parse_args(int argc, char *argv[]) {
} }
config.domains_str = optarg; config.domains_str = optarg;
config.domains_strlen = strlen(config.domains_str); config.domains_strlen = strlen(config.domains_str);
printf("asdffdsa\n");
break; break;
case OPT_FRAG: case OPT_FRAG:
@ -212,16 +210,21 @@ static int parse_args(int argc, char *argv[]) {
config.fake_sni_ttl = num; config.fake_sni_ttl = num;
break; 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: default:
goto error; goto error;
} }
} }
config.queue_start_num = parse_numeric_option(argv[optind]);
if (errno != 0) {
printf("Invalid queue number\n");
goto error;
}
errno = 0; errno = 0;
return 0; return 0;
@ -496,7 +499,6 @@ static int process_packet(const struct packet_data packet, struct queue_data qda
goto fallback; goto fallback;
} }
struct verdict vrd = analyze_tls_data(data, dlen); struct verdict vrd = analyze_tls_data(data, dlen);
verdnlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, qdata.queue_num); verdnlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, qdata.queue_num);
@ -523,22 +525,46 @@ static int process_packet(const struct packet_data packet, struct queue_data qda
(struct tcphdr *)tcph, (struct iphdr *)iph); (struct tcphdr *)tcph, (struct iphdr *)iph);
if (config.fake_sni_strategy != FKSN_STRAT_NONE) { if (config.fake_sni_strategy != FKSN_STRAT_NONE) {
uint8_t rfsiph[60];
uint8_t rfstcph[60];
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]; uint8_t fake_sni[MNL_SOCKET_BUFFER_SIZE];
uint32_t fsn_len = MNL_SOCKET_BUFFER_SIZE; uint32_t fsn_len = MNL_SOCKET_BUFFER_SIZE;
ret = gen_fake_sni(fsiph, fstcph, fake_sni, &fsn_len);
ret = gen_fake_sni(iph, tcph, fake_sni, &fsn_len);
if (ret < 0) { if (ret < 0) {
errno = -ret; errno = -ret;
perror("gen_fake_sni"); perror("gen_fake_sni");
goto fallback; goto fallback;
} }
printf("%d\n", i);
ret = send_raw_socket(fake_sni, fsn_len); ret = send_raw_socket(fake_sni, fsn_len);
if (ret < 0) { if (ret < 0) {
errno = -ret; errno = -ret;
perror("send fake sni"); perror("send fake sni");
goto fallback; 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;
}
} }
size_t ipd_offset; size_t ipd_offset;
@ -731,7 +757,7 @@ int init_queue(int queue_num) {
.queue_num = queue_num .queue_num = queue_num
}; };
printf("Queue %d started!\n", qdata.queue_num); printf("Queue %d started\n", qdata.queue_num);
while (1) { while (1) {
ret = mnl_socket_recvfrom(nl, buf, BUF_SIZE); ret = mnl_socket_recvfrom(nl, buf, BUF_SIZE);