2024-08-10 18:44:04 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2024-09-26 15:11:05 +00:00
|
|
|
#include "types.h"
|
2024-10-12 09:19:33 +00:00
|
|
|
#include "args.h"
|
2024-11-26 16:58:55 +00:00
|
|
|
#include "logging.h"
|
2024-08-10 18:44:04 +00:00
|
|
|
|
2024-09-26 15:11:05 +00:00
|
|
|
static char custom_fake_buf[MAX_FAKE_SIZE];
|
2024-08-10 18:44:04 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
struct config_t config = {
|
|
|
|
.threads = THREADS_NUM,
|
|
|
|
.queue_start_num = DEFAULT_QUEUE_NUM,
|
|
|
|
.mark = DEFAULT_RAWSOCKET_MARK,
|
|
|
|
.use_ipv6 = 1,
|
|
|
|
|
|
|
|
.verbose = VERBOSE_DEBUG,
|
|
|
|
.use_gso = true,
|
|
|
|
|
|
|
|
.default_config = default_section_config,
|
2024-10-26 13:18:13 +00:00
|
|
|
.custom_configs_len = 0,
|
|
|
|
|
|
|
|
.daemonize = 0,
|
2024-11-26 16:58:55 +00:00
|
|
|
.noclose = 0,
|
|
|
|
.syslog = 0,
|
2024-08-10 18:44:04 +00:00
|
|
|
};
|
|
|
|
|
2024-11-28 15:59:10 +00:00
|
|
|
enum {
|
|
|
|
OPT_SNI_DOMAINS,
|
|
|
|
OPT_EXCLUDE_DOMAINS,
|
|
|
|
OPT_FAKE_SNI,
|
|
|
|
OPT_FAKING_TTL,
|
|
|
|
OPT_FAKING_STRATEGY,
|
|
|
|
OPT_FAKE_SNI_SEQ_LEN,
|
|
|
|
OPT_FAKE_SNI_TYPE,
|
|
|
|
OPT_FAKE_CUSTOM_PAYLOAD,
|
|
|
|
OPT_START_SECTION,
|
|
|
|
OPT_END_SECTION,
|
|
|
|
OPT_DAEMONIZE,
|
|
|
|
OPT_NOCLOSE,
|
|
|
|
OPT_SYSLOG,
|
|
|
|
OPT_FRAG,
|
|
|
|
OPT_FRAG_SNI_REVERSE,
|
|
|
|
OPT_FRAG_SNI_FAKED,
|
|
|
|
OPT_FRAG_MIDDLE_SNI,
|
|
|
|
OPT_FRAG_SNI_POS,
|
|
|
|
OPT_FK_WINSIZE,
|
|
|
|
OPT_TRACE,
|
|
|
|
OPT_QUIC_DROP,
|
|
|
|
OPT_SNI_DETECTION,
|
|
|
|
OPT_NO_IPV6,
|
|
|
|
OPT_FAKE_SEQ_OFFSET,
|
|
|
|
OPT_PACKET_MARK,
|
|
|
|
OPT_SYNFAKE,
|
|
|
|
OPT_SYNFAKE_LEN,
|
|
|
|
OPT_SEG2DELAY,
|
|
|
|
OPT_THREADS,
|
|
|
|
OPT_SILENT,
|
|
|
|
OPT_NO_GSO,
|
|
|
|
OPT_QUEUE_NUM,
|
2024-12-06 10:45:50 +00:00
|
|
|
OPT_UDP_MODE,
|
|
|
|
OPT_UDP_FAKE_SEQ_LEN,
|
|
|
|
OPT_UDP_FAKE_PAYLOAD_LEN,
|
|
|
|
OPT_UDP_FAKING_STRATEGY,
|
|
|
|
OPT_UDP_DPORT_FILTER,
|
|
|
|
OPT_UDP_FILTER_QUIC,
|
2024-11-28 15:59:10 +00:00
|
|
|
};
|
2024-08-10 23:10:18 +00:00
|
|
|
|
2024-08-10 18:44:04 +00:00
|
|
|
static struct option long_opt[] = {
|
2024-08-10 23:10:18 +00:00
|
|
|
{"help", 0, 0, 'h'},
|
|
|
|
{"version", 0, 0, 'v'},
|
|
|
|
{"sni-domains", 1, 0, OPT_SNI_DOMAINS},
|
2024-09-03 18:22:17 +00:00
|
|
|
{"exclude-domains", 1, 0, OPT_EXCLUDE_DOMAINS},
|
2024-08-10 23:10:18 +00:00
|
|
|
{"fake-sni", 1, 0, OPT_FAKE_SNI},
|
2024-08-29 11:45:27 +00:00
|
|
|
{"synfake", 1, 0, OPT_SYNFAKE},
|
2024-08-29 12:49:01 +00:00
|
|
|
{"synfake-len", 1, 0, OPT_SYNFAKE_LEN},
|
2024-08-10 23:10:18 +00:00
|
|
|
{"fake-sni-seq-len", 1, 0, OPT_FAKE_SNI_SEQ_LEN},
|
2024-09-26 15:11:05 +00:00
|
|
|
{"fake-sni-type", 1, 0, OPT_FAKE_SNI_TYPE},
|
|
|
|
{"fake-custom-payload", 1, 0, OPT_FAKE_CUSTOM_PAYLOAD},
|
2024-08-10 23:10:18 +00:00
|
|
|
{"faking-strategy", 1, 0, OPT_FAKING_STRATEGY},
|
2024-08-27 20:23:54 +00:00
|
|
|
{"fake-seq-offset", 1, 0, OPT_FAKE_SEQ_OFFSET},
|
2024-08-10 23:10:18 +00:00
|
|
|
{"faking-ttl", 1, 0, OPT_FAKING_TTL},
|
|
|
|
{"frag", 1, 0, OPT_FRAG},
|
|
|
|
{"frag-sni-reverse", 1, 0, OPT_FRAG_SNI_REVERSE},
|
|
|
|
{"frag-sni-faked", 1, 0, OPT_FRAG_SNI_FAKED},
|
2024-08-17 09:51:53 +00:00
|
|
|
{"frag-middle-sni", 1, 0, OPT_FRAG_MIDDLE_SNI},
|
|
|
|
{"frag-sni-pos", 1, 0, OPT_FRAG_SNI_POS},
|
2024-08-11 21:45:30 +00:00
|
|
|
{"fk-winsize", 1, 0, OPT_FK_WINSIZE},
|
2024-08-13 17:48:35 +00:00
|
|
|
{"quic-drop", 0, 0, OPT_QUIC_DROP},
|
2024-08-14 23:31:48 +00:00
|
|
|
{"sni-detection", 1, 0, OPT_SNI_DETECTION},
|
2024-08-10 23:10:18 +00:00
|
|
|
{"seg2delay", 1, 0, OPT_SEG2DELAY},
|
2024-12-06 10:45:50 +00:00
|
|
|
{"udp-mode", 1, 0, OPT_UDP_MODE},
|
|
|
|
{"udp-fake-seq-len", 1, 0, OPT_UDP_FAKE_SEQ_LEN},
|
|
|
|
{"udp-fake-len", 1, 0, OPT_UDP_FAKE_PAYLOAD_LEN},
|
|
|
|
{"udp-faking-strategy", 1, 0, OPT_UDP_FAKING_STRATEGY},
|
|
|
|
{"udp-dport-filter", 1, 0, OPT_UDP_DPORT_FILTER},
|
|
|
|
{"udp-filter-quic", 1, 0, OPT_UDP_FILTER_QUIC},
|
2024-08-10 23:10:18 +00:00
|
|
|
{"threads", 1, 0, OPT_THREADS},
|
|
|
|
{"silent", 0, 0, OPT_SILENT},
|
2024-08-13 17:48:35 +00:00
|
|
|
{"trace", 0, 0, OPT_TRACE},
|
2024-08-10 23:10:18 +00:00
|
|
|
{"no-gso", 0, 0, OPT_NO_GSO},
|
2024-08-27 17:01:34 +00:00
|
|
|
{"no-ipv6", 0, 0, OPT_NO_IPV6},
|
2024-10-26 13:18:13 +00:00
|
|
|
{"daemonize", 0, 0, OPT_DAEMONIZE},
|
|
|
|
{"noclose", 0, 0, OPT_NOCLOSE},
|
2024-11-26 16:58:55 +00:00
|
|
|
{"syslog", 0, 0, OPT_SYSLOG},
|
2024-08-10 23:10:18 +00:00
|
|
|
{"queue-num", 1, 0, OPT_QUEUE_NUM},
|
2024-08-29 06:09:57 +00:00
|
|
|
{"packet-mark", 1, 0, OPT_PACKET_MARK},
|
2024-10-13 20:31:26 +00:00
|
|
|
{"fbegin", 0, 0, OPT_START_SECTION},
|
|
|
|
{"fend", 0, 0, OPT_END_SECTION},
|
2024-08-10 18:44:04 +00:00
|
|
|
{0,0,0,0}
|
|
|
|
};
|
|
|
|
|
|
|
|
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') {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_version() {
|
2024-10-28 22:09:23 +00:00
|
|
|
printf("youtubeUnblock"
|
|
|
|
#if defined(PKG_VERSION)
|
|
|
|
" " PKG_VERSION
|
|
|
|
#endif
|
|
|
|
"\n"
|
|
|
|
);
|
|
|
|
printf("Bypasses deep packet inspection systems that rely on SNI\n");
|
2024-08-11 18:43:32 +00:00
|
|
|
printf("\n");
|
2024-08-10 18:44:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_usage(const char *argv0) {
|
|
|
|
print_version();
|
|
|
|
|
|
|
|
printf("Usage: %s [ OPTIONS ] \n", argv0);
|
|
|
|
printf("Options:\n");
|
|
|
|
printf("\t--queue-num=<number of netfilter queue>\n");
|
|
|
|
printf("\t--sni-domains=<comma separated domain list>|all\n");
|
2024-09-03 18:22:17 +00:00
|
|
|
printf("\t--exclude-domains=<comma separated domain list>\n");
|
2024-08-10 23:10:18 +00:00
|
|
|
printf("\t--fake-sni={1|0}\n");
|
|
|
|
printf("\t--fake-sni-seq-len=<length>\n");
|
2024-09-26 15:11:05 +00:00
|
|
|
printf("\t--fake-sni-type={default|random|custom}\n");
|
|
|
|
printf("\t--fake-custom-payload=<hex payload>\n");
|
2024-08-27 20:23:54 +00:00
|
|
|
printf("\t--fake-seq-offset=<offset>\n");
|
2024-08-10 23:10:18 +00:00
|
|
|
printf("\t--faking-ttl=<ttl>\n");
|
2024-09-13 16:04:48 +00:00
|
|
|
printf("\t--faking-strategy={randseq|ttl|tcp_check|pastseq|md5sum}\n");
|
2024-08-29 11:45:27 +00:00
|
|
|
printf("\t--synfake={1|0}\n");
|
2024-08-29 12:49:01 +00:00
|
|
|
printf("\t--synfake-len=<len>\n");
|
2024-08-10 18:44:04 +00:00
|
|
|
printf("\t--frag={tcp,ip,none}\n");
|
2024-08-10 23:10:18 +00:00
|
|
|
printf("\t--frag-sni-reverse={0|1}\n");
|
|
|
|
printf("\t--frag-sni-faked={0|1}\n");
|
2024-08-17 09:51:53 +00:00
|
|
|
printf("\t--frag-middle-sni={0|1}\n");
|
|
|
|
printf("\t--frag-sni-pos=<pos>\n");
|
2024-08-11 21:45:30 +00:00
|
|
|
printf("\t--fk-winsize=<winsize>\n");
|
2024-08-13 17:48:35 +00:00
|
|
|
printf("\t--quic-drop\n");
|
2024-08-14 23:31:48 +00:00
|
|
|
printf("\t--sni-detection={parse|brute}\n");
|
2024-08-10 18:44:04 +00:00
|
|
|
printf("\t--seg2delay=<delay>\n");
|
2024-12-06 10:45:50 +00:00
|
|
|
printf("\t--udp-mode={drop|fake}\n");
|
|
|
|
printf("\t--udp-fake-seq-len=<amount of faking packets sent>\n");
|
|
|
|
printf("\t--udp-fake-len=<size of upd fake>\n");
|
|
|
|
printf("\t--udp-faking-strategy={checksum|ttl}\n");
|
|
|
|
printf("\t--udp-dport-filter=<5,6,200-500>\n");
|
|
|
|
printf("\t--udp-filter-quic={disabled|all}\n");
|
2024-08-10 18:44:04 +00:00
|
|
|
printf("\t--threads=<threads number>\n");
|
2024-08-29 06:09:57 +00:00
|
|
|
printf("\t--packet-mark=<mark>\n");
|
2024-08-10 18:44:04 +00:00
|
|
|
printf("\t--silent\n");
|
2024-08-13 17:48:35 +00:00
|
|
|
printf("\t--trace\n");
|
2024-08-10 18:44:04 +00:00
|
|
|
printf("\t--no-gso\n");
|
2024-08-27 17:01:34 +00:00
|
|
|
printf("\t--no-ipv6\n");
|
2024-10-26 13:18:13 +00:00
|
|
|
printf("\t--daemonize\n");
|
|
|
|
printf("\t--noclose\n");
|
2024-11-26 16:58:55 +00:00
|
|
|
printf("\t--syslog\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
printf("\t--fbegin\n");
|
|
|
|
printf("\t--fend\n");
|
2024-08-10 18:44:04 +00:00
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2024-12-06 10:45:50 +00:00
|
|
|
int parse_udp_dport_range(char *str, struct udp_dport_range **udpr, int *udpr_len) {
|
|
|
|
int ret = 0;
|
|
|
|
int seclen = 1;
|
|
|
|
int strlen = 0;
|
|
|
|
const char *p = optarg;
|
|
|
|
while (*p != '\0') {
|
|
|
|
if (*p == ',')
|
|
|
|
seclen++;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
strlen = p - optarg;
|
|
|
|
|
|
|
|
struct udp_dport_range *udp_dport_ranges = malloc(
|
|
|
|
seclen * sizeof(struct udp_dport_range));
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
|
|
p = optarg;
|
|
|
|
const char *ep = p;
|
|
|
|
while (1) {
|
|
|
|
if (*ep == '\0' || *ep == ',') {
|
|
|
|
if (ep == p) {
|
|
|
|
if (*ep == '\0')
|
|
|
|
break;
|
|
|
|
|
|
|
|
p++, ep++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *endp;
|
|
|
|
long num1 = strtol(p, &endp, 10);
|
|
|
|
long num2 = num1;
|
|
|
|
if (errno)
|
|
|
|
goto erret;
|
|
|
|
|
|
|
|
if (endp != ep) {
|
|
|
|
if (*endp == '-') {
|
|
|
|
endp++;
|
|
|
|
num2 = strtol(endp, &endp, 10);
|
|
|
|
|
|
|
|
if (endp != ep || errno)
|
|
|
|
goto erret;
|
|
|
|
} else {
|
|
|
|
goto erret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
!(num1 > 0 && num1 < (1 << 16)) ||
|
|
|
|
!(num2 > 0 && num2 < (1 << 16)) ||
|
|
|
|
num2 < num1
|
|
|
|
)
|
|
|
|
goto erret;
|
|
|
|
|
|
|
|
udp_dport_ranges[i] = (struct udp_dport_range){
|
|
|
|
.start = num1,
|
|
|
|
.end = num2
|
|
|
|
};
|
|
|
|
i++;
|
|
|
|
|
|
|
|
if (*ep == '\0') {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
p = ep + 1;
|
|
|
|
ep = p;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ep++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*udpr = udp_dport_ranges;
|
|
|
|
*udpr_len = seclen;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
erret:
|
|
|
|
free(udp_dport_ranges);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2024-08-10 18:44:04 +00:00
|
|
|
int parse_args(int argc, char *argv[]) {
|
|
|
|
int opt;
|
2024-10-13 20:31:26 +00:00
|
|
|
int optIdx = 0;
|
2024-08-10 18:44:04 +00:00
|
|
|
long num;
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
struct section_config_t *sect_config = &config.default_config;
|
|
|
|
|
|
|
|
#define SECT_ITER_DEFAULT 1
|
|
|
|
#define SECT_ITER_INSIDE 2
|
|
|
|
#define SECT_ITER_OUTSIDE 3
|
|
|
|
|
|
|
|
int section_iter = SECT_ITER_DEFAULT;
|
|
|
|
|
2024-08-10 18:44:04 +00:00
|
|
|
while ((opt = getopt_long(argc, argv, "hv", long_opt, &optIdx)) != -1) {
|
|
|
|
switch (opt) {
|
2024-10-13 20:31:26 +00:00
|
|
|
/* config_t scoped configs */
|
2024-08-12 12:22:04 +00:00
|
|
|
case 'h':
|
|
|
|
print_usage(argv[0]);
|
|
|
|
goto stop_exec;
|
|
|
|
case 'v':
|
|
|
|
print_version();
|
|
|
|
goto stop_exec;
|
2024-08-13 17:48:35 +00:00
|
|
|
case OPT_TRACE:
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section_iter != SECT_ITER_DEFAULT)
|
|
|
|
goto invalid_opt;
|
2024-08-13 17:48:35 +00:00
|
|
|
config.verbose = 2;
|
|
|
|
break;
|
2024-08-12 12:22:04 +00:00
|
|
|
case OPT_SILENT:
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section_iter != SECT_ITER_DEFAULT)
|
|
|
|
goto invalid_opt;
|
|
|
|
|
2024-08-12 12:22:04 +00:00
|
|
|
config.verbose = 0;
|
|
|
|
break;
|
|
|
|
case OPT_NO_GSO:
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section_iter != SECT_ITER_DEFAULT)
|
|
|
|
goto invalid_opt;
|
|
|
|
|
2024-08-12 12:22:04 +00:00
|
|
|
config.use_gso = 0;
|
|
|
|
break;
|
2024-08-27 17:01:34 +00:00
|
|
|
case OPT_NO_IPV6:
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section_iter != SECT_ITER_DEFAULT)
|
|
|
|
goto invalid_opt;
|
|
|
|
|
2024-08-27 17:01:34 +00:00
|
|
|
config.use_ipv6 = 0;
|
|
|
|
break;
|
2024-10-26 13:18:13 +00:00
|
|
|
case OPT_DAEMONIZE:
|
|
|
|
config.daemonize = 1;
|
|
|
|
break;
|
|
|
|
case OPT_NOCLOSE:
|
|
|
|
config.noclose = 1;
|
|
|
|
break;
|
2024-11-26 16:58:55 +00:00
|
|
|
case OPT_SYSLOG:
|
|
|
|
config.syslog = 1;
|
|
|
|
break;
|
2024-10-13 20:31:26 +00:00
|
|
|
case OPT_THREADS:
|
|
|
|
if (section_iter != SECT_ITER_DEFAULT)
|
|
|
|
goto invalid_opt;
|
|
|
|
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0 || num > MAX_THREADS) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
config.threads = num;
|
2024-08-13 17:48:35 +00:00
|
|
|
break;
|
2024-10-13 20:31:26 +00:00
|
|
|
case OPT_QUEUE_NUM:
|
|
|
|
if (section_iter != SECT_ITER_DEFAULT)
|
|
|
|
goto invalid_opt;
|
|
|
|
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0) {
|
|
|
|
goto invalid_opt;
|
2024-08-12 12:22:04 +00:00
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
config.queue_start_num = num;
|
2024-08-14 23:31:48 +00:00
|
|
|
break;
|
2024-10-13 20:31:26 +00:00
|
|
|
case OPT_PACKET_MARK:
|
|
|
|
if (section_iter != SECT_ITER_DEFAULT)
|
|
|
|
goto invalid_opt;
|
|
|
|
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
config.mark = num;
|
2024-09-03 18:22:17 +00:00
|
|
|
break;
|
2024-10-13 20:31:26 +00:00
|
|
|
case OPT_START_SECTION:
|
|
|
|
if (section_iter != SECT_ITER_DEFAULT && section_iter != SECT_ITER_OUTSIDE)
|
|
|
|
goto invalid_opt;
|
|
|
|
|
|
|
|
sect_config = &config.custom_configs[config.custom_configs_len++];
|
2024-10-13 21:11:58 +00:00
|
|
|
*sect_config = (struct section_config_t)default_section_config;
|
2024-10-13 20:31:26 +00:00
|
|
|
section_iter = SECT_ITER_INSIDE;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_END_SECTION:
|
|
|
|
if (section_iter != SECT_ITER_INSIDE)
|
2024-08-14 23:31:48 +00:00
|
|
|
goto invalid_opt;
|
2024-10-13 20:31:26 +00:00
|
|
|
|
|
|
|
section_iter = SECT_ITER_OUTSIDE;
|
|
|
|
sect_config = &config.default_config;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* section_config_t scoped configs */
|
|
|
|
case OPT_SNI_DOMAINS:
|
|
|
|
if (!strcmp(optarg, "all")) {
|
|
|
|
sect_config->all_domains = 1;
|
2024-08-14 23:31:48 +00:00
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->domains_str = optarg;
|
|
|
|
sect_config->domains_strlen = strlen(sect_config->domains_str);
|
|
|
|
break;
|
|
|
|
case OPT_EXCLUDE_DOMAINS:
|
|
|
|
sect_config->exclude_domains_str = optarg;
|
|
|
|
sect_config->exclude_domains_strlen = strlen(sect_config->exclude_domains_str);
|
2024-08-12 12:22:04 +00:00
|
|
|
break;
|
|
|
|
case OPT_FRAG:
|
|
|
|
if (strcmp(optarg, "tcp") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fragmentation_strategy = FRAG_STRAT_TCP;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else if (strcmp(optarg, "ip") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fragmentation_strategy = FRAG_STRAT_IP;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else if (strcmp(optarg, "none") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fragmentation_strategy = FRAG_STRAT_NONE;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_FRAG_SNI_FAKED:
|
|
|
|
if (strcmp(optarg, "1") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->frag_sni_faked = 1;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else if (strcmp(optarg, "0") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->frag_sni_faked = 0;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_FRAG_SNI_REVERSE:
|
|
|
|
if (strcmp(optarg, "1") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->frag_sni_reverse = 1;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else if (strcmp(optarg, "0") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->frag_sni_reverse = 0;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
2024-08-17 09:51:53 +00:00
|
|
|
break;
|
|
|
|
case OPT_FRAG_MIDDLE_SNI:
|
|
|
|
if (strcmp(optarg, "1") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->frag_middle_sni = 1;
|
2024-08-17 09:51:53 +00:00
|
|
|
} else if (strcmp(optarg, "0") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->frag_middle_sni = 0;
|
2024-08-17 09:51:53 +00:00
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_FRAG_SNI_POS:
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->frag_sni_pos = num;
|
2024-08-12 12:22:04 +00:00
|
|
|
break;
|
|
|
|
case OPT_FAKING_STRATEGY:
|
2024-08-16 19:47:55 +00:00
|
|
|
if (strcmp(optarg, "randseq") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->faking_strategy = FAKE_STRAT_RAND_SEQ;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else if (strcmp(optarg, "ttl") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->faking_strategy = FAKE_STRAT_TTL;
|
2024-08-16 19:47:55 +00:00
|
|
|
} else if (strcmp(optarg, "tcp_check") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->faking_strategy = FAKE_STRAT_TCP_CHECK;
|
2024-08-16 19:47:55 +00:00
|
|
|
} else if (strcmp(optarg, "pastseq") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->faking_strategy = FAKE_STRAT_PAST_SEQ;
|
2024-09-13 16:04:48 +00:00
|
|
|
} else if (strcmp(optarg, "md5sum") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->faking_strategy = FAKE_STRAT_TCP_MD5SUM;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_FAKING_TTL:
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0 || num > 255) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->faking_ttl = num;
|
2024-08-12 12:22:04 +00:00
|
|
|
break;
|
2024-08-27 20:23:54 +00:00
|
|
|
case OPT_FAKE_SEQ_OFFSET:
|
|
|
|
num = parse_numeric_option(optarg);
|
2024-09-26 15:11:05 +00:00
|
|
|
if (errno != 0) {
|
2024-08-27 20:23:54 +00:00
|
|
|
goto invalid_opt;
|
|
|
|
}
|
2024-08-12 12:22:04 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fakeseq_offset = num;
|
2024-08-27 20:23:54 +00:00
|
|
|
break;
|
2024-08-12 12:22:04 +00:00
|
|
|
case OPT_FAKE_SNI:
|
|
|
|
if (strcmp(optarg, "1") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fake_sni = 1;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else if (strcmp(optarg, "0") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fake_sni = 0;
|
2024-08-12 12:22:04 +00:00
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_FAKE_SNI_SEQ_LEN:
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0 || num > 255) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fake_sni_seq_len = num;
|
2024-09-26 15:11:05 +00:00
|
|
|
break;
|
|
|
|
case OPT_FAKE_SNI_TYPE:
|
|
|
|
if (strcmp(optarg, "default") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fake_sni_type = FAKE_PAYLOAD_DEFAULT;
|
2024-09-26 15:11:05 +00:00
|
|
|
} else if (strcmp(optarg, "random") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fake_sni_type = FAKE_PAYLOAD_RANDOM;
|
2024-09-26 15:11:05 +00:00
|
|
|
} else if (strcmp(optarg, "custom") == 0) {
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fake_sni_type = FAKE_PAYLOAD_CUSTOM;
|
2024-09-26 15:11:05 +00:00
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_FAKE_CUSTOM_PAYLOAD: {
|
|
|
|
uint8_t *const custom_buf = (uint8_t *)custom_fake_buf;
|
|
|
|
|
|
|
|
const char *custom_hex_fake = optarg;
|
|
|
|
size_t custom_hlen = strlen(custom_hex_fake);
|
|
|
|
if ((custom_hlen & 1) == 1) {
|
|
|
|
printf("Custom fake hex should be divisible by two\n");
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t custom_len = custom_hlen >> 1;
|
|
|
|
if (custom_len > MAX_FAKE_SIZE) {
|
|
|
|
printf("Custom fake is too large\n");
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < custom_len; i++) {
|
|
|
|
sscanf(custom_hex_fake + (i << 1), "%2hhx", custom_buf + i);
|
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fake_custom_pkt_sz = custom_len;
|
|
|
|
sect_config->fake_custom_pkt = (char *)custom_buf;
|
2024-09-28 20:06:45 +00:00
|
|
|
}
|
2024-09-26 15:11:05 +00:00
|
|
|
break;
|
2024-08-12 12:22:04 +00:00
|
|
|
case OPT_FK_WINSIZE:
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->fk_winsize = num;
|
2024-08-29 11:45:27 +00:00
|
|
|
break;
|
|
|
|
|
2024-08-12 12:22:04 +00:00
|
|
|
case OPT_SEG2DELAY:
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
sect_config->seg2_delay = num;
|
2024-08-12 12:22:04 +00:00
|
|
|
break;
|
2024-10-13 20:31:26 +00:00
|
|
|
case OPT_QUIC_DROP:
|
2024-12-06 10:45:50 +00:00
|
|
|
sect_config->udp_filter_quic = UDP_FILTER_QUIC_ALL;
|
|
|
|
sect_config->udp_mode = UDP_MODE_DROP;
|
2024-08-12 12:22:04 +00:00
|
|
|
break;
|
2024-10-13 20:31:26 +00:00
|
|
|
case OPT_SNI_DETECTION:
|
|
|
|
if (strcmp(optarg, "parse") == 0) {
|
|
|
|
sect_config->sni_detection = SNI_DETECTION_PARSE;
|
|
|
|
} else if (strcmp(optarg, "brute") == 0) {
|
|
|
|
sect_config->sni_detection = SNI_DETECTION_BRUTE;
|
|
|
|
} else {
|
2024-08-29 06:09:57 +00:00
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
2024-10-13 22:16:46 +00:00
|
|
|
break;
|
|
|
|
case OPT_SYNFAKE:
|
|
|
|
if (strcmp(optarg, "1") == 0) {
|
|
|
|
sect_config->synfake = 1;
|
|
|
|
} else if (strcmp(optarg, "0") == 0) {
|
|
|
|
sect_config->synfake = 0;
|
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_SYNFAKE_LEN:
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
sect_config->synfake_len = num;
|
2024-12-06 10:45:50 +00:00
|
|
|
break;
|
|
|
|
case OPT_UDP_MODE:
|
|
|
|
if (strcmp(optarg, "drop") == 0) {
|
|
|
|
sect_config->udp_mode = UDP_MODE_DROP;
|
|
|
|
} else if (strcmp(optarg, "fake") == 0) {
|
|
|
|
sect_config->udp_mode = UDP_MODE_FAKE;
|
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_UDP_FAKING_STRATEGY:
|
|
|
|
if (strcmp(optarg, "checksum") == 0) {
|
|
|
|
sect_config->udp_faking_strategy = FAKE_STRAT_UDP_CHECK;
|
|
|
|
} else if (strcmp(optarg, "ttl") == 0) {
|
|
|
|
sect_config->udp_faking_strategy = FAKE_STRAT_TTL;
|
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OPT_UDP_FAKE_SEQ_LEN:
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
sect_config->udp_fake_seq_len = num;
|
|
|
|
break;
|
|
|
|
case OPT_UDP_FAKE_PAYLOAD_LEN:
|
|
|
|
num = parse_numeric_option(optarg);
|
|
|
|
if (errno != 0 || num < 0 || num > 1300) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
sect_config->udp_fake_len = num;
|
|
|
|
break;
|
|
|
|
case OPT_UDP_DPORT_FILTER:
|
|
|
|
{
|
|
|
|
struct udp_dport_range *udp_dport_range;
|
|
|
|
int udp_range_len = 0;
|
|
|
|
if (parse_udp_dport_range(optarg, &udp_dport_range, &udp_range_len) < 0) {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
sect_config->udp_dport_range = udp_dport_range;
|
|
|
|
sect_config->udp_dport_range_len = udp_range_len;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OPT_UDP_FILTER_QUIC:
|
|
|
|
if (strcmp(optarg, "disabled") == 0) {
|
|
|
|
sect_config->udp_filter_quic = UDP_FILTER_QUIC_DISABLED;
|
|
|
|
} else if (strcmp(optarg, "all") == 0) {
|
|
|
|
sect_config->udp_filter_quic = UDP_FILTER_QUIC_ALL;
|
|
|
|
} else {
|
|
|
|
goto invalid_opt;
|
|
|
|
}
|
|
|
|
|
2024-08-29 06:09:57 +00:00
|
|
|
break;
|
2024-08-12 12:22:04 +00:00
|
|
|
default:
|
|
|
|
goto error;
|
2024-08-10 18:44:04 +00:00
|
|
|
}
|
2024-10-13 20:31:26 +00:00
|
|
|
|
2024-08-10 18:44:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
return 0;
|
2024-08-12 12:22:04 +00:00
|
|
|
stop_exec:
|
2024-08-10 18:44:04 +00:00
|
|
|
errno = 0;
|
|
|
|
return 1;
|
2024-08-12 12:22:04 +00:00
|
|
|
|
|
|
|
invalid_opt:
|
2024-08-12 01:52:03 +00:00
|
|
|
printf("Invalid option %s\n", long_opt[optIdx].name);
|
2024-08-12 12:22:04 +00:00
|
|
|
error:
|
2024-08-10 18:44:04 +00:00
|
|
|
print_usage(argv[0]);
|
|
|
|
errno = EINVAL;
|
2024-12-06 10:45:50 +00:00
|
|
|
return -errno;
|
2024-08-10 18:44:04 +00:00
|
|
|
}
|
2024-08-11 18:43:32 +00:00
|
|
|
|
|
|
|
void print_welcome() {
|
2024-11-26 16:58:55 +00:00
|
|
|
if (config.syslog) {
|
|
|
|
printf("Logging to system log\n");
|
|
|
|
}
|
2024-10-13 20:31:26 +00:00
|
|
|
if (config.use_gso) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("GSO is enabled\n");
|
2024-08-11 18:43:32 +00:00
|
|
|
}
|
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (config.use_ipv6) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("IPv6 is enabled\n");
|
2024-08-11 18:43:32 +00:00
|
|
|
} else {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("IPv6 is disabled\n");
|
2024-08-11 18:43:32 +00:00
|
|
|
}
|
2024-10-13 20:31:26 +00:00
|
|
|
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Detected %d config sections\n", config.custom_configs_len + 1);
|
|
|
|
lginfo("The sections will be processed in order they goes in this output\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
|
|
|
|
ITER_CONFIG_SECTIONS(section) {
|
|
|
|
int section_number = CONFIG_SECTION_NUMBER(section);
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Section #%d\n", section_number);
|
2024-10-13 20:31:26 +00:00
|
|
|
|
|
|
|
switch (section->fragmentation_strategy) {
|
|
|
|
case FRAG_STRAT_TCP:
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Using TCP segmentation\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
break;
|
|
|
|
case FRAG_STRAT_IP:
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Using IP fragmentation\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
break;
|
|
|
|
default:
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("SNI fragmentation is disabled\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
break;
|
|
|
|
}
|
2024-08-11 18:43:32 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->seg2_delay) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Some outgoing googlevideo request segments will be delayed for %d ms as of seg2_delay define\n", section->seg2_delay);
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-11 18:43:32 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->fake_sni) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Fake SNI will be sent before each target client hello\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
} else {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Fake SNI is disabled\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-11 18:43:32 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->frag_sni_reverse) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Fragmentation Client Hello will be reversed\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-11 18:43:32 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->frag_sni_faked) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Fooling packets will be sent near the original Client Hello\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-11 21:45:30 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->fake_sni_seq_len > 1) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Faking sequence of length %d will be built as fake sni\n", section->fake_sni_seq_len);
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-29 11:45:27 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
switch (section->faking_strategy) {
|
|
|
|
case FAKE_STRAT_TTL:
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("TTL faking strategy will be used with TTL %d\n", section->faking_ttl);
|
2024-10-13 20:31:26 +00:00
|
|
|
break;
|
|
|
|
case FAKE_STRAT_RAND_SEQ:
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Random seq faking strategy will be used\n");
|
|
|
|
lginfo("Fake seq offset set to %u\n", section->fakeseq_offset);
|
2024-10-13 20:31:26 +00:00
|
|
|
break;
|
|
|
|
case FAKE_STRAT_TCP_CHECK:
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("TCP checksum faking strategy will be used\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
break;
|
|
|
|
case FAKE_STRAT_PAST_SEQ:
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Past seq faking strategy will be used\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
break;
|
|
|
|
case FAKE_STRAT_TCP_MD5SUM:
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("md5sum faking strategy will be used\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
break;
|
|
|
|
}
|
2024-08-11 18:43:32 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->fk_winsize) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Response TCP window will be set to %d with the appropriate scale\n", section->fk_winsize);
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-11 18:43:32 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->synfake) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Fake SYN payload will be sent with each TCP request SYN packet\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-27 17:01:34 +00:00
|
|
|
|
2024-12-06 10:45:50 +00:00
|
|
|
if (section->udp_filter_quic && section->udp_mode == UDP_MODE_DROP) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("All QUIC packets will be dropped\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-13 17:48:35 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->sni_detection == SNI_DETECTION_BRUTE) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Server Name Extension will be parsed in the bruteforce mode\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-14 23:31:48 +00:00
|
|
|
|
2024-10-13 20:31:26 +00:00
|
|
|
if (section->all_domains) {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("All Client Hello will be targeted by youtubeUnblock!\n");
|
2024-10-13 20:31:26 +00:00
|
|
|
} else {
|
2024-11-26 16:58:55 +00:00
|
|
|
lginfo("Target sni domains: %s\n", section->domains_str);
|
2024-10-13 20:31:26 +00:00
|
|
|
}
|
2024-08-11 18:43:32 +00:00
|
|
|
}
|
|
|
|
}
|
2024-10-12 09:19:33 +00:00
|
|
|
|