Add multiple sections with config sets for various domains

This commit is contained in:
Vadim Vetrov 2024-10-13 23:31:26 +03:00
parent 58f4802f64
commit 4c7b63fa7f
No known key found for this signature in database
GPG Key ID: E8A308689D7A73A5
11 changed files with 450 additions and 413 deletions

View File

@ -231,6 +231,8 @@ Available flags:
- `--packet-mark=<mark>` Use this option if youtubeUnblock conflicts with other systems rely on packet mark. Note that you may want to change accept rule for iptables to follow the mark. - `--packet-mark=<mark>` Use this option if youtubeUnblock conflicts with other systems rely on packet mark. Note that you may want to change accept rule for iptables to follow the mark.
- `--fbegin` and `--fend` flags: youtubeUnblock supports multiple sets of strategies for specific filters. You may want to initiate a new set after the default one, like: `--sni-domains=googlevideo.com --faking-strategy=md5sum --fbegin --sni-domains=youtube.com --faking-strategy=tcp_check --fend --fbegin --sni-domains=l.google.com --faking-strategy=pastseq --fend`. Note, that the priority of these sets goes backwards: last is first, default (one that does not start with --fbegin) is last. If you start the new section, the default settings are implemented just like youtubeUnblock without any parameters. Note that the config above is just an example and won't work for you.
## Troubleshooting ## Troubleshooting
If you got troubles with some sites and you sure that they are blocked by SNI (youtube for example), use may play around with [flags](#flags) and their combinations. At first it is recommended to try `--faking-strategy` flag and `--frag-sni-faked=1`. If you got troubles with some sites and you sure that they are blocked by SNI (youtube for example), use may play around with [flags](#flags) and their combinations. At first it is recommended to try `--faking-strategy` flag and `--frag-sni-faked=1`.

321
args.c
View File

@ -12,8 +12,7 @@
static char custom_fake_buf[MAX_FAKE_SIZE]; static char custom_fake_buf[MAX_FAKE_SIZE];
struct config_t config = { static const struct section_config_t default_section_config = {
.threads = THREADS_NUM,
.frag_sni_reverse = 1, .frag_sni_reverse = 1,
.frag_sni_faked = 0, .frag_sni_faked = 0,
.fragmentation_strategy = FRAGMENTATION_STRATEGY, .fragmentation_strategy = FRAGMENTATION_STRATEGY,
@ -24,31 +23,12 @@ struct config_t config = {
.fake_sni_type = FAKE_PAYLOAD_DEFAULT, .fake_sni_type = FAKE_PAYLOAD_DEFAULT,
.frag_middle_sni = 1, .frag_middle_sni = 1,
.frag_sni_pos = 1, .frag_sni_pos = 1,
.use_ipv6 = 1,
.fakeseq_offset = 10000, .fakeseq_offset = 10000,
.mark = DEFAULT_RAWSOCKET_MARK,
.synfake = 0, .synfake = 0,
.synfake_len = 0, .synfake_len = 0,
.quic_drop = 0,
.sni_detection = SNI_DETECTION_PARSE,
#ifdef SEG2_DELAY
.seg2_delay = SEG2_DELAY,
#else
.seg2_delay = 0, .seg2_delay = 0,
#endif
#ifdef USE_GSO
.use_gso = true,
#else
.use_gso = false,
#endif
#ifdef DEBUG
.verbose = 1,
#else
.verbose = 0,
#endif
.domains_str = defaul_snistr, .domains_str = defaul_snistr,
.domains_strlen = sizeof(defaul_snistr), .domains_strlen = sizeof(defaul_snistr),
@ -56,11 +36,25 @@ struct config_t config = {
.exclude_domains_str = "", .exclude_domains_str = "",
.exclude_domains_strlen = 0, .exclude_domains_strlen = 0,
.queue_start_num = DEFAULT_QUEUE_NUM,
.fake_sni_pkt = fake_sni_old, .fake_sni_pkt = fake_sni_old,
.fake_sni_pkt_sz = sizeof(fake_sni_old) - 1, // - 1 for null-terminator .fake_sni_pkt_sz = sizeof(fake_sni_old) - 1, // - 1 for null-terminator
.fake_custom_pkt = custom_fake_buf, .fake_custom_pkt = custom_fake_buf,
.fake_custom_pkt_sz = 0 .fake_custom_pkt_sz = 0,
.sni_detection = SNI_DETECTION_PARSE,
};
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,
.custom_configs_len = 0
}; };
#define OPT_SNI_DOMAINS 1 #define OPT_SNI_DOMAINS 1
@ -71,6 +65,8 @@ struct config_t config = {
#define OPT_FAKE_SNI_SEQ_LEN 11 #define OPT_FAKE_SNI_SEQ_LEN 11
#define OPT_FAKE_SNI_TYPE 27 #define OPT_FAKE_SNI_TYPE 27
#define OPT_FAKE_CUSTOM_PAYLOAD 28 #define OPT_FAKE_CUSTOM_PAYLOAD 28
#define OPT_START_SECTION 29
#define OPT_END_SECTION 30
#define OPT_FRAG 4 #define OPT_FRAG 4
#define OPT_FRAG_SNI_REVERSE 12 #define OPT_FRAG_SNI_REVERSE 12
#define OPT_FRAG_SNI_FAKED 13 #define OPT_FRAG_SNI_FAKED 13
@ -91,7 +87,7 @@ struct config_t config = {
#define OPT_NO_GSO 8 #define OPT_NO_GSO 8
#define OPT_QUEUE_NUM 9 #define OPT_QUEUE_NUM 9
#define OPT_MAX OPT_FAKE_CUSTOM_PAYLOAD #define OPT_MAX OPT_END_SECTION
static struct option long_opt[] = { static struct option long_opt[] = {
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
@ -123,6 +119,8 @@ static struct option long_opt[] = {
{"no-ipv6", 0, 0, OPT_NO_IPV6}, {"no-ipv6", 0, 0, OPT_NO_IPV6},
{"queue-num", 1, 0, OPT_QUEUE_NUM}, {"queue-num", 1, 0, OPT_QUEUE_NUM},
{"packet-mark", 1, 0, OPT_PACKET_MARK}, {"packet-mark", 1, 0, OPT_PACKET_MARK},
{"fbegin", 0, 0, OPT_START_SECTION},
{"fend", 0, 0, OPT_END_SECTION},
{0,0,0,0} {0,0,0,0}
}; };
@ -182,16 +180,27 @@ void print_usage(const char *argv0) {
printf("\t--trace\n"); printf("\t--trace\n");
printf("\t--no-gso\n"); printf("\t--no-gso\n");
printf("\t--no-ipv6\n"); printf("\t--no-ipv6\n");
printf("\t--fbegin\n");
printf("\t--fend\n");
printf("\n"); printf("\n");
} }
int parse_args(int argc, char *argv[]) { int parse_args(int argc, char *argv[]) {
int opt; int opt;
int optIdx; int optIdx = 0;
long num; long num;
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;
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) {
/* config_t scoped configs */
case 'h': case 'h':
print_usage(argv[0]); print_usage(argv[0]);
goto stop_exec; goto stop_exec;
@ -199,49 +208,98 @@ int parse_args(int argc, char *argv[]) {
print_version(); print_version();
goto stop_exec; goto stop_exec;
case OPT_TRACE: case OPT_TRACE:
if (section_iter != SECT_ITER_DEFAULT)
goto invalid_opt;
config.verbose = 2; config.verbose = 2;
break; break;
case OPT_SILENT: case OPT_SILENT:
if (section_iter != SECT_ITER_DEFAULT)
goto invalid_opt;
config.verbose = 0; config.verbose = 0;
break; break;
case OPT_NO_GSO: case OPT_NO_GSO:
if (section_iter != SECT_ITER_DEFAULT)
goto invalid_opt;
config.use_gso = 0; config.use_gso = 0;
break; break;
case OPT_NO_IPV6: case OPT_NO_IPV6:
if (section_iter != SECT_ITER_DEFAULT)
goto invalid_opt;
config.use_ipv6 = 0; config.use_ipv6 = 0;
break; break;
case OPT_QUIC_DROP: case OPT_THREADS:
config.quic_drop = 1; if (section_iter != SECT_ITER_DEFAULT)
break; goto invalid_opt;
case OPT_SNI_DOMAINS:
if (!strcmp(optarg, "all")) {
config.all_domains = 1;
}
config.domains_str = optarg; num = parse_numeric_option(optarg);
config.domains_strlen = strlen(config.domains_str); if (errno != 0 || num < 0 || num > MAX_THREADS) {
break;
case OPT_EXCLUDE_DOMAINS:
config.exclude_domains_str = optarg;
config.exclude_domains_strlen = strlen(config.exclude_domains_str);
break;
case OPT_SNI_DETECTION:
if (strcmp(optarg, "parse") == 0) {
config.sni_detection = SNI_DETECTION_PARSE;
} else if (strcmp(optarg, "brute") == 0) {
config.sni_detection = SNI_DETECTION_BRUTE;
} else {
goto invalid_opt; goto invalid_opt;
} }
config.threads = num;
break;
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;
}
config.queue_start_num = num;
break;
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;
break;
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++];
*sect_config = default_section_config;
section_iter = SECT_ITER_INSIDE;
break;
case OPT_END_SECTION:
if (section_iter != SECT_ITER_INSIDE)
goto invalid_opt;
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;
}
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);
break; break;
case OPT_FRAG: case OPT_FRAG:
if (strcmp(optarg, "tcp") == 0) { if (strcmp(optarg, "tcp") == 0) {
config.fragmentation_strategy = FRAG_STRAT_TCP; sect_config->fragmentation_strategy = FRAG_STRAT_TCP;
} else if (strcmp(optarg, "ip") == 0) { } else if (strcmp(optarg, "ip") == 0) {
config.fragmentation_strategy = FRAG_STRAT_IP; sect_config->fragmentation_strategy = FRAG_STRAT_IP;
} else if (strcmp(optarg, "none") == 0) { } else if (strcmp(optarg, "none") == 0) {
config.fragmentation_strategy = FRAG_STRAT_NONE; sect_config->fragmentation_strategy = FRAG_STRAT_NONE;
} else { } else {
goto invalid_opt; goto invalid_opt;
} }
@ -249,9 +307,9 @@ int parse_args(int argc, char *argv[]) {
break; break;
case OPT_FRAG_SNI_FAKED: case OPT_FRAG_SNI_FAKED:
if (strcmp(optarg, "1") == 0) { if (strcmp(optarg, "1") == 0) {
config.frag_sni_faked = 1; sect_config->frag_sni_faked = 1;
} else if (strcmp(optarg, "0") == 0) { } else if (strcmp(optarg, "0") == 0) {
config.frag_sni_faked = 0; sect_config->frag_sni_faked = 0;
} else { } else {
goto invalid_opt; goto invalid_opt;
} }
@ -259,9 +317,9 @@ int parse_args(int argc, char *argv[]) {
break; break;
case OPT_FRAG_SNI_REVERSE: case OPT_FRAG_SNI_REVERSE:
if (strcmp(optarg, "1") == 0) { if (strcmp(optarg, "1") == 0) {
config.frag_sni_reverse = 1; sect_config->frag_sni_reverse = 1;
} else if (strcmp(optarg, "0") == 0) { } else if (strcmp(optarg, "0") == 0) {
config.frag_sni_reverse = 0; sect_config->frag_sni_reverse = 0;
} else { } else {
goto invalid_opt; goto invalid_opt;
} }
@ -269,9 +327,9 @@ int parse_args(int argc, char *argv[]) {
break; break;
case OPT_FRAG_MIDDLE_SNI: case OPT_FRAG_MIDDLE_SNI:
if (strcmp(optarg, "1") == 0) { if (strcmp(optarg, "1") == 0) {
config.frag_middle_sni = 1; sect_config->frag_middle_sni = 1;
} else if (strcmp(optarg, "0") == 0) { } else if (strcmp(optarg, "0") == 0) {
config.frag_middle_sni = 0; sect_config->frag_middle_sni = 0;
} else { } else {
goto invalid_opt; goto invalid_opt;
} }
@ -283,19 +341,19 @@ int parse_args(int argc, char *argv[]) {
goto invalid_opt; goto invalid_opt;
} }
config.frag_sni_pos = num; sect_config->frag_sni_pos = num;
break; break;
case OPT_FAKING_STRATEGY: case OPT_FAKING_STRATEGY:
if (strcmp(optarg, "randseq") == 0) { if (strcmp(optarg, "randseq") == 0) {
config.faking_strategy = FAKE_STRAT_RAND_SEQ; sect_config->faking_strategy = FAKE_STRAT_RAND_SEQ;
} else if (strcmp(optarg, "ttl") == 0) { } else if (strcmp(optarg, "ttl") == 0) {
config.faking_strategy = FAKE_STRAT_TTL; sect_config->faking_strategy = FAKE_STRAT_TTL;
} else if (strcmp(optarg, "tcp_check") == 0) { } else if (strcmp(optarg, "tcp_check") == 0) {
config.faking_strategy = FAKE_STRAT_TCP_CHECK; sect_config->faking_strategy = FAKE_STRAT_TCP_CHECK;
} else if (strcmp(optarg, "pastseq") == 0) { } else if (strcmp(optarg, "pastseq") == 0) {
config.faking_strategy = FAKE_STRAT_PAST_SEQ; sect_config->faking_strategy = FAKE_STRAT_PAST_SEQ;
} else if (strcmp(optarg, "md5sum") == 0) { } else if (strcmp(optarg, "md5sum") == 0) {
config.faking_strategy = FAKE_STRAT_TCP_MD5SUM; sect_config->faking_strategy = FAKE_STRAT_TCP_MD5SUM;
} else { } else {
goto invalid_opt; goto invalid_opt;
} }
@ -307,7 +365,7 @@ int parse_args(int argc, char *argv[]) {
goto invalid_opt; goto invalid_opt;
} }
config.faking_ttl = num; sect_config->faking_ttl = num;
break; break;
case OPT_FAKE_SEQ_OFFSET: case OPT_FAKE_SEQ_OFFSET:
num = parse_numeric_option(optarg); num = parse_numeric_option(optarg);
@ -315,13 +373,13 @@ int parse_args(int argc, char *argv[]) {
goto invalid_opt; goto invalid_opt;
} }
config.fakeseq_offset = num; sect_config->fakeseq_offset = num;
break; break;
case OPT_FAKE_SNI: case OPT_FAKE_SNI:
if (strcmp(optarg, "1") == 0) { if (strcmp(optarg, "1") == 0) {
config.fake_sni = 1; sect_config->fake_sni = 1;
} else if (strcmp(optarg, "0") == 0) { } else if (strcmp(optarg, "0") == 0) {
config.fake_sni = 0; sect_config->fake_sni = 0;
} else { } else {
goto invalid_opt; goto invalid_opt;
} }
@ -333,15 +391,15 @@ int parse_args(int argc, char *argv[]) {
goto invalid_opt; goto invalid_opt;
} }
config.fake_sni_seq_len = num; sect_config->fake_sni_seq_len = num;
break; break;
case OPT_FAKE_SNI_TYPE: case OPT_FAKE_SNI_TYPE:
if (strcmp(optarg, "default") == 0) { if (strcmp(optarg, "default") == 0) {
config.fake_sni_type = FAKE_PAYLOAD_DEFAULT; sect_config->fake_sni_type = FAKE_PAYLOAD_DEFAULT;
} else if (strcmp(optarg, "random") == 0) { } else if (strcmp(optarg, "random") == 0) {
config.fake_sni_type = FAKE_PAYLOAD_RANDOM; sect_config->fake_sni_type = FAKE_PAYLOAD_RANDOM;
} else if (strcmp(optarg, "custom") == 0) { } else if (strcmp(optarg, "custom") == 0) {
config.fake_sni_type = FAKE_PAYLOAD_CUSTOM; sect_config->fake_sni_type = FAKE_PAYLOAD_CUSTOM;
} else { } else {
goto invalid_opt; goto invalid_opt;
} }
@ -368,8 +426,8 @@ int parse_args(int argc, char *argv[]) {
sscanf(custom_hex_fake + (i << 1), "%2hhx", custom_buf + i); sscanf(custom_hex_fake + (i << 1), "%2hhx", custom_buf + i);
} }
config.fake_custom_pkt_sz = custom_len; sect_config->fake_custom_pkt_sz = custom_len;
config.fake_custom_pkt = (char *)custom_buf; sect_config->fake_custom_pkt = (char *)custom_buf;
} }
break; break;
case OPT_FK_WINSIZE: case OPT_FK_WINSIZE:
@ -378,66 +436,37 @@ int parse_args(int argc, char *argv[]) {
goto invalid_opt; goto invalid_opt;
} }
config.fk_winsize = num; sect_config->fk_winsize = num;
break; break;
case OPT_SYNFAKE:
if (strcmp(optarg, "1") == 0) {
config.synfake = 1;
} else if (strcmp(optarg, "0") == 0) {
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;
}
config.synfake_len = num;
break;
case OPT_SEG2DELAY: case OPT_SEG2DELAY:
num = parse_numeric_option(optarg); num = parse_numeric_option(optarg);
if (errno != 0 || num < 0) { if (errno != 0 || num < 0) {
goto invalid_opt; goto invalid_opt;
} }
config.seg2_delay = num; sect_config->seg2_delay = num;
break; break;
case OPT_THREADS: case OPT_QUIC_DROP:
num = parse_numeric_option(optarg); sect_config->quic_drop = 1;
if (errno != 0 || num < 0 || num > MAX_THREADS) { break;
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 {
goto invalid_opt; goto invalid_opt;
} }
config.threads = num;
break; break;
case OPT_QUEUE_NUM:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0) {
goto invalid_opt;
}
config.queue_start_num = num;
break;
case OPT_PACKET_MARK:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0) {
goto invalid_opt;
}
config.mark = num;
break;
default: default:
goto error; goto error;
} }
} }
// out:
errno = 0; errno = 0;
return 0; return 0;
stop_exec: stop_exec:
@ -453,7 +482,24 @@ error:
} }
void print_welcome() { void print_welcome() {
switch (config.fragmentation_strategy) { if (config.use_gso) {
printf("GSO is enabled\n");
}
if (config.use_ipv6) {
printf("IPv6 is enabled\n");
} else {
printf("IPv6 is disabled\n");
}
printf("Detected %d config sections\n", config.custom_configs_len + 1);
printf("The sections will be processed in ordred they goes in this output");
ITER_CONFIG_SECTIONS(section) {
int section_number = CONFIG_SECTION_NUMBER(section);
printf("Section #%d\n", section_number);
switch (section->fragmentation_strategy) {
case FRAG_STRAT_TCP: case FRAG_STRAT_TCP:
printf("Using TCP segmentation\n"); printf("Using TCP segmentation\n");
break; break;
@ -465,35 +511,35 @@ void print_welcome() {
break; break;
} }
if (config.seg2_delay) { if (section->seg2_delay) {
printf("Some outgoing googlevideo request segments will be delayed for %d ms as of seg2_delay define\n", config.seg2_delay); printf("Some outgoing googlevideo request segments will be delayed for %d ms as of seg2_delay define\n", section->seg2_delay);
} }
if (config.fake_sni) { if (section->fake_sni) {
printf("Fake SNI will be sent before each target client hello\n"); printf("Fake SNI will be sent before each target client hello\n");
} else { } else {
printf("Fake SNI is disabled\n"); printf("Fake SNI is disabled\n");
} }
if (config.frag_sni_reverse) { if (section->frag_sni_reverse) {
printf("Fragmentation Client Hello will be reversed\n"); printf("Fragmentation Client Hello will be reversed\n");
} }
if (config.frag_sni_faked) { if (section->frag_sni_faked) {
printf("Fooling packets will be sent near the original Client Hello\n"); printf("Fooling packets will be sent near the original Client Hello\n");
} }
if (config.fake_sni_seq_len > 1) { if (section->fake_sni_seq_len > 1) {
printf("Faking sequence of length %d will be built as fake sni\n", config.fake_sni_seq_len); printf("Faking sequence of length %d will be built as fake sni\n", section->fake_sni_seq_len);
} }
switch (config.faking_strategy) { switch (section->faking_strategy) {
case FAKE_STRAT_TTL: case FAKE_STRAT_TTL:
printf("TTL faking strategy will be used with TTL %d\n", config.faking_ttl); printf("TTL faking strategy will be used with TTL %d\n", section->faking_ttl);
break; break;
case FAKE_STRAT_RAND_SEQ: case FAKE_STRAT_RAND_SEQ:
printf("Random seq faking strategy will be used\n"); printf("Random seq faking strategy will be used\n");
printf("Fake seq offset set to %u\n", config.fakeseq_offset); printf("Fake seq offset set to %u\n", section->fakeseq_offset);
break; break;
case FAKE_STRAT_TCP_CHECK: case FAKE_STRAT_TCP_CHECK:
printf("TCP checksum faking strategy will be used\n"); printf("TCP checksum faking strategy will be used\n");
@ -506,36 +552,27 @@ void print_welcome() {
break; break;
} }
if (config.fk_winsize) { if (section->fk_winsize) {
printf("Response TCP window will be set to %d with the appropriate scale\n", config.fk_winsize); printf("Response TCP window will be set to %d with the appropriate scale\n", section->fk_winsize);
} }
if (config.synfake) { if (section->synfake) {
printf("Fake SYN payload will be sent with each TCP request SYN packet\n"); printf("Fake SYN payload will be sent with each TCP request SYN packet\n");
} }
if (section->quic_drop) {
if (config.use_gso) {
printf("GSO is enabled\n");
}
if (config.use_ipv6) {
printf("IPv6 is enabled\n");
} else {
printf("IPv6 is disabled\n");
}
if (config.quic_drop) {
printf("All QUIC packets will be dropped\n"); printf("All QUIC packets will be dropped\n");
} }
if (config.sni_detection == SNI_DETECTION_BRUTE) { if (section->sni_detection == SNI_DETECTION_BRUTE) {
printf("Server Name Extension will be parsed in the bruteforce mode\n"); printf("Server Name Extension will be parsed in the bruteforce mode\n");
} }
if (config.all_domains) { if (section->all_domains) {
printf("All Client Hello will be targetted by youtubeUnblock!\n"); printf("All Client Hello will be targetted by youtubeUnblock!\n");
} } else {
printf("Target sni domains: %s\n", section->domains_str);
}
}
} }

View File

@ -18,11 +18,10 @@ struct instance_config_t {
}; };
extern struct instance_config_t instance_config; extern struct instance_config_t instance_config;
struct config_t { struct section_config_t {
unsigned int queue_start_num; const char *domains_str;
int threads; unsigned int domains_strlen;
int use_gso;
int use_ipv6;
int fragmentation_strategy; int fragmentation_strategy;
int frag_sni_reverse; int frag_sni_reverse;
int frag_sni_faked; int frag_sni_faked;
@ -39,18 +38,13 @@ struct config_t {
#define FAKE_PAYLOAD_DEFAULT 2 #define FAKE_PAYLOAD_DEFAULT 2
int fake_sni_type; int fake_sni_type;
#define VERBOSE_INFO 0
#define VERBOSE_DEBUG 1
#define VERBOSE_TRACE 2
int verbose;
int quic_drop; int quic_drop;
#define SNI_DETECTION_PARSE 0
#define SNI_DETECTION_BRUTE 1
int sni_detection;
/* In milliseconds */ /* In milliseconds */
unsigned int seg2_delay; unsigned int seg2_delay;
const char *domains_str; int synfake;
unsigned int domains_strlen; unsigned int synfake_len;
const char *exclude_domains_str; const char *exclude_domains_str;
unsigned int exclude_domains_strlen; unsigned int exclude_domains_strlen;
unsigned int all_domains; unsigned int all_domains;
@ -61,16 +55,42 @@ struct config_t {
const char *fake_custom_pkt; const char *fake_custom_pkt;
unsigned int fake_custom_pkt_sz; unsigned int fake_custom_pkt_sz;
unsigned int fk_winsize; unsigned int fk_winsize;
int fakeseq_offset; int fakeseq_offset;
#define SNI_DETECTION_PARSE 0
#define SNI_DETECTION_BRUTE 1
int sni_detection;
};
#define MAX_CONFIGLIST_LEN 64
struct config_t {
unsigned int queue_start_num;
int threads;
int use_gso;
int use_ipv6;
unsigned int mark; unsigned int mark;
int synfake;
unsigned int synfake_len; #define VERBOSE_INFO 0
#define VERBOSE_DEBUG 1
#define VERBOSE_TRACE 2
int verbose;
struct section_config_t default_config;
struct section_config_t custom_configs[MAX_CONFIGLIST_LEN];
int custom_configs_len;
}; };
extern struct config_t config; extern struct config_t config;
#define ITER_CONFIG_SECTIONS(section) \
for (struct section_config_t *section = &config.default_config + config.custom_configs_len; section >= &config.default_config; section--)
#define CONFIG_SECTION_NUMBER(section) (int)((section) - &config.default_config)
#define MAX_THREADS 16 #define MAX_THREADS 16
#ifndef THREADS_NUM #ifndef THREADS_NUM

113
kargs.c
View File

@ -4,11 +4,11 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include "types.h" #include "types.h"
static char custom_fake_buf[MAX_FAKE_SIZE];
#define STR_MAXLEN 2048 #define STR_MAXLEN 2048
struct config_t config = { static char custom_fake_buf[MAX_FAKE_SIZE];
static const struct section_config_t default_section_config = {
.frag_sni_reverse = 1, .frag_sni_reverse = 1,
.frag_sni_faked = 0, .frag_sni_faked = 0,
.fragmentation_strategy = FRAGMENTATION_STRATEGY, .fragmentation_strategy = FRAGMENTATION_STRATEGY,
@ -16,45 +16,44 @@ struct config_t config = {
.faking_ttl = FAKE_TTL, .faking_ttl = FAKE_TTL,
.fake_sni = 1, .fake_sni = 1,
.fake_sni_seq_len = 1, .fake_sni_seq_len = 1,
.fake_sni_type = FAKE_PAYLOAD_DEFAULT,
.frag_middle_sni = 1, .frag_middle_sni = 1,
.frag_sni_pos = 1, .frag_sni_pos = 1,
.use_ipv6 = 1,
.fakeseq_offset = 10000, .fakeseq_offset = 10000,
.mark = DEFAULT_RAWSOCKET_MARK,
.synfake = 0, .synfake = 0,
.synfake_len = 0, .synfake_len = 0,
.fake_sni_type = FAKE_PAYLOAD_DEFAULT, .quic_drop = 0,
.sni_detection = SNI_DETECTION_PARSE,
#ifdef SEG2_DELAY
.seg2_delay = SEG2_DELAY,
#else
.seg2_delay = 0, .seg2_delay = 0,
#endif
#ifdef USE_GSO
.use_gso = 1,
#else
.use_gso = false,
#endif
#ifdef DEBUG
.verbose = 2,
#else
.verbose = 1,
#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, .exclude_domains_str = "",
.exclude_domains_strlen = 0,
.fake_sni_pkt = fake_sni_old, .fake_sni_pkt = fake_sni_old,
.fake_sni_pkt_sz = sizeof(fake_sni_old) - 1, // - 1 for null-terminator .fake_sni_pkt_sz = sizeof(fake_sni_old) - 1, // - 1 for null-terminator
.fake_custom_pkt = custom_fake_buf, .fake_custom_pkt = custom_fake_buf,
.fake_custom_pkt_sz = 0 .fake_custom_pkt_sz = 0,
.sni_detection = SNI_DETECTION_PARSE,
}; };
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 = 1,
.default_config = default_section_config,
.custom_configs_len = 0
};
static struct section_config_t *const def_section = &config.default_config;
static int unumeric_set(const char *val, const struct kernel_param *kp) { static int unumeric_set(const char *val, const struct kernel_param *kp) {
int n = 0, ret; int n = 0, ret;
ret = kstrtoint(val, 10, &n); ret = kstrtoint(val, 10, &n);
@ -113,19 +112,19 @@ static const struct kernel_param_ops inverse_boolean_ops = {
.get = inverse_boolean_get, .get = inverse_boolean_get,
}; };
module_param_cb(fake_sni, &boolean_parameter_ops, &config.fake_sni, 0664); module_param_cb(fake_sni, &boolean_parameter_ops, &def_section->fake_sni, 0664);
module_param_cb(fake_sni_seq_len, &unumeric_parameter_ops, &config.fake_sni_seq_len, 0664); module_param_cb(fake_sni_seq_len, &unumeric_parameter_ops, &def_section->fake_sni_seq_len, 0664);
module_param_cb(faking_ttl, &unumeric_parameter_ops, &config.faking_ttl, 0664); module_param_cb(faking_ttl, &unumeric_parameter_ops, &def_section->faking_ttl, 0664);
module_param_cb(fake_seq_offset, &unumeric_parameter_ops, &config.fakeseq_offset, 0664); module_param_cb(fake_seq_offset, &unumeric_parameter_ops, &def_section->fakeseq_offset, 0664);
module_param_cb(frag_sni_reverse, &unumeric_parameter_ops, &config.frag_sni_reverse, 0664); module_param_cb(frag_sni_reverse, &unumeric_parameter_ops, &def_section->frag_sni_reverse, 0664);
module_param_cb(frag_sni_faked, &boolean_parameter_ops, &config.frag_sni_faked, 0664); module_param_cb(frag_sni_faked, &boolean_parameter_ops, &def_section->frag_sni_faked, 0664);
module_param_cb(frag_middle_sni, &boolean_parameter_ops, &config.frag_middle_sni, 0664); module_param_cb(frag_middle_sni, &boolean_parameter_ops, &def_section->frag_middle_sni, 0664);
module_param_cb(frag_sni_pos, &unumeric_parameter_ops, &config.frag_sni_pos, 0664); module_param_cb(frag_sni_pos, &unumeric_parameter_ops, &def_section->frag_sni_pos, 0664);
module_param_cb(fk_winsize, &unumeric_parameter_ops, &config.fk_winsize, 0664); module_param_cb(fk_winsize, &unumeric_parameter_ops, &def_section->fk_winsize, 0664);
module_param_cb(synfake, &boolean_parameter_ops, &config.synfake, 0664); module_param_cb(synfake, &boolean_parameter_ops, &def_section->synfake, 0664);
module_param_cb(synfake_len, &unumeric_parameter_ops, &config.synfake_len, 0664); module_param_cb(synfake_len, &unumeric_parameter_ops, &def_section->synfake_len, 0664);
module_param_cb(packet_mark, &unumeric_parameter_ops, &config.mark, 0664); module_param_cb(packet_mark, &unumeric_parameter_ops, &config.mark, 0664);
// module_param_cb(seg2delay, &unumeric_parameter_ops, &config.seg2_delay, 0664); // module_param_cb(seg2delay, &unumeric_parameter_ops, &def_section->seg2_delay, 0664);
static int sni_domains_set(const char *val, const struct kernel_param *kp) { static int sni_domains_set(const char *val, const struct kernel_param *kp) {
size_t len; size_t len;
@ -144,13 +143,13 @@ static int sni_domains_set(const char *val, const struct kernel_param *kp) {
ret = param_set_charp(val, kp); ret = param_set_charp(val, kp);
if (ret < 0) { if (ret < 0) {
config.domains_strlen = 0; def_section->domains_strlen = 0;
} else { } else {
config.domains_strlen = len; def_section->domains_strlen = len;
if (len == 3 && !strncmp(val, "all", len)) { if (len == 3 && !strncmp(val, "all", len)) {
config.all_domains = 1; def_section->all_domains = 1;
} else { } else {
config.all_domains = 0; def_section->all_domains = 0;
} }
} }
@ -163,7 +162,7 @@ static const struct kernel_param_ops sni_domains_ops = {
.get = param_get_charp, .get = param_get_charp,
}; };
module_param_cb(sni_domains, &sni_domains_ops, &config.domains_str, 0664); module_param_cb(sni_domains, &sni_domains_ops, &def_section->domains_str, 0664);
static int exclude_domains_set(const char *val, const struct kernel_param *kp) { static int exclude_domains_set(const char *val, const struct kernel_param *kp) {
size_t len; size_t len;
@ -178,9 +177,9 @@ static int exclude_domains_set(const char *val, const struct kernel_param *kp) {
ret = param_set_charp(val, kp); ret = param_set_charp(val, kp);
if (ret < 0) { if (ret < 0) {
config.exclude_domains_strlen = 0; def_section->exclude_domains_strlen = 0;
} else { } else {
config.exclude_domains_strlen = len; def_section->exclude_domains_strlen = len;
} }
return ret; return ret;
@ -191,10 +190,10 @@ static const struct kernel_param_ops exclude_domains_ops = {
.get = param_get_charp, .get = param_get_charp,
}; };
module_param_cb(exclude_domains, &exclude_domains_ops, &config.exclude_domains_str, 0664); module_param_cb(exclude_domains, &exclude_domains_ops, &def_section->exclude_domains_str, 0664);
module_param_cb(no_ipv6, &inverse_boolean_ops, &config.use_ipv6, 0664); module_param_cb(no_ipv6, &inverse_boolean_ops, &config.use_ipv6, 0664);
module_param_cb(quic_drop, &boolean_parameter_ops, &config.quic_drop, 0664); module_param_cb(quic_drop, &boolean_parameter_ops, &def_section->quic_drop, 0664);
static int verbosity_set(const char *val, const struct kernel_param *kp) { static int verbosity_set(const char *val, const struct kernel_param *kp) {
size_t len; size_t len;
@ -297,7 +296,7 @@ static const struct kernel_param_ops frag_strat_ops = {
.get = frag_strat_get, .get = frag_strat_get,
}; };
module_param_cb(fragmentation_strategy, &frag_strat_ops, &config.fragmentation_strategy, 0664); module_param_cb(fragmentation_strategy, &frag_strat_ops, &def_section->fragmentation_strategy, 0664);
static int fake_strat_set(const char *val, const struct kernel_param *kp) { static int fake_strat_set(const char *val, const struct kernel_param *kp) {
size_t len; size_t len;
@ -358,7 +357,7 @@ static const struct kernel_param_ops fake_strat_ops = {
.get = fake_strat_get, .get = fake_strat_get,
}; };
module_param_cb(faking_strategy, &fake_strat_ops, &config.faking_strategy, 0664); module_param_cb(faking_strategy, &fake_strat_ops, &def_section->faking_strategy, 0664);
static int sni_detection_set(const char *val, const struct kernel_param *kp) { static int sni_detection_set(const char *val, const struct kernel_param *kp) {
size_t len; size_t len;
@ -404,7 +403,7 @@ static const struct kernel_param_ops sni_detection_ops = {
.get = sni_detection_get, .get = sni_detection_get,
}; };
module_param_cb(sni_detection, &sni_detection_ops, &config.sni_detection, 0664); module_param_cb(sni_detection, &sni_detection_ops, &def_section->sni_detection, 0664);
static int fake_type_set(const char *val, const struct kernel_param *kp) { static int fake_type_set(const char *val, const struct kernel_param *kp) {
size_t len; size_t len;
@ -455,7 +454,7 @@ static const struct kernel_param_ops fake_type_ops = {
.get = fake_type_get, .get = fake_type_get,
}; };
module_param_cb(fake_sni_type, &fake_type_ops, &config.fake_sni_type, 0664); module_param_cb(fake_sni_type, &fake_type_ops, &def_section->fake_sni_type, 0664);
static int fake_custom_pl_set(const char *val, const struct kernel_param *kp) { static int fake_custom_pl_set(const char *val, const struct kernel_param *kp) {
size_t len; size_t len;
@ -488,16 +487,16 @@ static int fake_custom_pl_set(const char *val, const struct kernel_param *kp) {
sscanf(custom_hex_fake + (i << 1), "%2hhx", custom_buf + i); sscanf(custom_hex_fake + (i << 1), "%2hhx", custom_buf + i);
} }
config.fake_custom_pkt_sz = custom_len; def_section->fake_custom_pkt_sz = custom_len;
config.fake_custom_pkt = (char *)custom_buf; def_section->fake_custom_pkt = (char *)custom_buf;
return 0; return 0;
} }
static int fake_custom_pl_get(char *buffer, const struct kernel_param *kp) { static int fake_custom_pl_get(char *buffer, const struct kernel_param *kp) {
int cflen = config.fake_custom_pkt_sz; int cflen = def_section->fake_custom_pkt_sz;
const uint8_t *cbf_data = config.fake_custom_pkt; const uint8_t *cbf_data = def_section->fake_custom_pkt;
int bflen = config.fake_custom_pkt_sz << 1; int bflen = def_section->fake_custom_pkt_sz << 1;
for (int i = 0; i < cflen; i++) { for (int i = 0; i < cflen; i++) {
sprintf(buffer + (i << 1), "%02x", *((unsigned char *)cbf_data + i)); sprintf(buffer + (i << 1), "%02x", *((unsigned char *)cbf_data + i));
@ -511,4 +510,4 @@ static const struct kernel_param_ops fake_custom_pl_ops = {
.get = fake_custom_pl_get, .get = fake_custom_pl_get,
}; };
module_param_cb(fake_custom_payload, &fake_custom_pl_ops, &config.fake_custom_pkt, 0664); module_param_cb(fake_custom_payload, &fake_custom_pl_ops, &def_section->fake_custom_pkt, 0664);

View File

@ -171,26 +171,11 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
uint32_t buff1_size = MAX_PACKET_SIZE; uint32_t buff1_size = MAX_PACKET_SIZE;
uint32_t buff2_size = MAX_PACKET_SIZE; uint32_t buff2_size = MAX_PACKET_SIZE;
switch (config.fragmentation_strategy) {
case FRAG_STRAT_TCP:
if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128, if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128,
buff1, &buff1_size, buff2, &buff2_size)) < 0) { buff1, &buff1_size, buff2, &buff2_size)) < 0) {
goto erret_lc; goto erret_lc;
} }
break;
case FRAG_STRAT_IP:
if ((ret = ip4_frag(pkt, pktlen, AVAILABLE_MTU-128,
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
goto erret_lc;
}
break;
default:
pr_info("send_raw_socket: Packet is too big but fragmentation is disabled!");
ret = -EINVAL;
goto erret_lc;
}
int sent = 0; int sent = 0;
ret = send_raw_socket(buff1, buff1_size); ret = send_raw_socket(buff1, buff1_size);

151
mangle.c
View File

@ -26,6 +26,8 @@ int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
int ipver = netproto_version(raw_payload, raw_payload_len); int ipver = netproto_version(raw_payload, raw_payload_len);
int ret; int ret;
lgtrace_start();
lgtrace_addp("IPv%d", ipver);
if (ipver == IP4VERSION) { if (ipver == IP4VERSION) {
ret = ip4_payload_split((uint8_t *)raw_payload, raw_payload_len, ret = ip4_payload_split((uint8_t *)raw_payload, raw_payload_len,
@ -52,21 +54,39 @@ int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
goto accept; goto accept;
} }
int verdict = PKT_CONTINUE;
if (transport_proto == IPPROTO_TCP)
lgtrace_addp("TCP");
else if (transport_proto == IPPROTO_UDP)
lgtrace_addp("UDP");
ITER_CONFIG_SECTIONS(section) {
lgtrace_addp("Section #%d", CONFIG_SECTION_NUMBER(section));
switch (transport_proto) { switch (transport_proto) {
case IPPROTO_TCP: case IPPROTO_TCP:
return process_tcp_packet(raw_payload, raw_payload_len); verdict = process_tcp_packet(section, raw_payload, raw_payload_len);
break;
case IPPROTO_UDP: case IPPROTO_UDP:
return process_udp_packet(raw_payload, raw_payload_len); verdict = process_udp_packet(section, raw_payload, raw_payload_len);
default: break;
goto accept; }
if (verdict == PKT_CONTINUE)
continue;
lgtrace_end();
return verdict;
} }
accept: accept:
lgtrace_end();
return PKT_ACCEPT; return PKT_ACCEPT;
} }
int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) { int process_tcp_packet(const struct section_config_t *section, const uint8_t *raw_payload, uint32_t raw_payload_len) {
const void *ipxh; const void *ipxh;
uint32_t iph_len; uint32_t iph_len;
const struct tcphdr *tcph; const struct tcphdr *tcph;
@ -77,9 +97,6 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
int ipxv = netproto_version(raw_payload, raw_payload_len); int ipxv = netproto_version(raw_payload, raw_payload_len);
lgtrace_start("TCP");
lgtrace_addp("IPv%d", ipxv);
int ret = tcp_payload_split((uint8_t *)raw_payload, raw_payload_len, int ret = tcp_payload_split((uint8_t *)raw_payload, raw_payload_len,
(void *)&ipxh, &iph_len, (void *)&ipxh, &iph_len,
(struct tcphdr **)&tcph, &tcph_len, (struct tcphdr **)&tcph, &tcph_len,
@ -90,7 +107,7 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
goto accept; goto accept;
} }
if (tcph->syn && config.synfake) { if (tcph->syn && section->synfake) {
lgtrace_addp("TCP syn alter"); lgtrace_addp("TCP syn alter");
NETBUF_ALLOC(payload, MAX_PACKET_SIZE); NETBUF_ALLOC(payload, MAX_PACKET_SIZE);
@ -101,12 +118,12 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
memcpy(payload, ipxh, iph_len); memcpy(payload, ipxh, iph_len);
memcpy(payload + iph_len, tcph, tcph_len); memcpy(payload + iph_len, tcph, tcph_len);
uint32_t fake_len = config.fake_sni_pkt_sz; uint32_t fake_len = section->fake_sni_pkt_sz;
if (config.synfake_len) if (section->synfake_len)
fake_len = min(config.synfake_len, fake_len); fake_len = min(section->synfake_len, fake_len);
memcpy(payload + iph_len + tcph_len, config.fake_sni_pkt, fake_len); memcpy(payload + iph_len + tcph_len, section->fake_sni_pkt, fake_len);
struct tcphdr *tcph = (struct tcphdr *)(payload + iph_len); struct tcphdr *tcph = (struct tcphdr *)(payload + iph_len);
@ -130,16 +147,15 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
NETBUF_FREE(payload); NETBUF_FREE(payload);
goto accept; goto accept;
} }
lgtrace_addp("rawsocket sent %d", ret);
NETBUF_FREE(payload); NETBUF_FREE(payload);
goto drop; goto drop;
} }
if (tcph->syn) goto accept; if (tcph->syn) goto continue_flow;
struct tls_verdict vrd = analyze_tls_data(data, dlen); struct tls_verdict vrd = analyze_tls_data(section, data, dlen);
lgtrace_addp("Analyzed"); lgtrace_addp("TLS analyzed");
if (vrd.sni_len != 0) { if (vrd.sni_len != 0) {
lgtrace_addp("SNI detected: %.*s", vrd.sni_len, data + vrd.sni_offset); lgtrace_addp("SNI detected: %.*s", vrd.sni_len, data + vrd.sni_offset);
@ -173,8 +189,8 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
goto accept_lc; goto accept_lc;
} }
if (config.fk_winsize) { if (section->fk_winsize) {
tcph->window = htons(config.fk_winsize); tcph->window = htons(section->fk_winsize);
set_tcp_checksum(tcph, iph, iph_len); set_tcp_checksum(tcph, iph, iph_len);
} }
@ -194,14 +210,14 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
lgdebugmsg("WARNING! Client Hello packet is too big and may cause issues!"); lgdebugmsg("WARNING! Client Hello packet is too big and may cause issues!");
} }
if (config.fake_sni) { if (section->fake_sni) {
post_fake_sni(args_default_fake_type(), iph, iph_len, tcph, tcph_len); post_fake_sni(args_default_fake_type(section), iph, iph_len, tcph, tcph_len);
} }
size_t ipd_offset; size_t ipd_offset;
size_t mid_offset; size_t mid_offset;
switch (config.fragmentation_strategy) { switch (section->fragmentation_strategy) {
case FRAG_STRAT_TCP: { case FRAG_STRAT_TCP: {
ipd_offset = vrd.sni_target_offset; ipd_offset = vrd.sni_target_offset;
mid_offset = ipd_offset + vrd.sni_target_len / 2; mid_offset = ipd_offset + vrd.sni_target_len / 2;
@ -209,11 +225,11 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
uint32_t poses[2]; uint32_t poses[2];
int cnt = 0; int cnt = 0;
if (config.frag_sni_pos && dlen > config.frag_sni_pos) { if (section->frag_sni_pos && dlen > section->frag_sni_pos) {
poses[cnt++] = config.frag_sni_pos; poses[cnt++] = section->frag_sni_pos;
} }
if (config.frag_middle_sni) { if (section->frag_middle_sni) {
poses[cnt++] = mid_offset; poses[cnt++] = mid_offset;
} }
@ -223,7 +239,7 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
poses[1] = tmp; poses[1] = tmp;
} }
ret = send_tcp_frags(payload, payload_len, poses, cnt, 0); ret = send_tcp_frags(section, payload, payload_len, poses, cnt, 0);
if (ret < 0) { if (ret < 0) {
lgerror("tcp4 send frags", ret); lgerror("tcp4 send frags", ret);
goto accept_lc; goto accept_lc;
@ -241,13 +257,13 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
uint32_t poses[2]; uint32_t poses[2];
int cnt = 0; int cnt = 0;
if (config.frag_sni_pos && dlen > config.frag_sni_pos) { if (section->frag_sni_pos && dlen > section->frag_sni_pos) {
poses[cnt] = config.frag_sni_pos + ((char *)data - (char *)tcph); poses[cnt] = section->frag_sni_pos + ((char *)data - (char *)tcph);
poses[cnt] += 8 - poses[cnt] % 8; poses[cnt] += 8 - poses[cnt] % 8;
cnt++; cnt++;
} }
if (config.frag_middle_sni) { if (section->frag_middle_sni) {
poses[cnt++] = mid_offset; poses[cnt++] = mid_offset;
} }
@ -257,7 +273,7 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
poses[1] = tmp; poses[1] = tmp;
} }
ret = send_ip4_frags(payload, payload_len, poses, cnt, 0); ret = send_ip4_frags(section, payload, payload_len, poses, cnt, 0);
if (ret < 0) { if (ret < 0) {
lgerror("ip4 send frags", ret); lgerror("ip4 send frags", ret);
goto accept_lc; goto accept_lc;
@ -292,27 +308,24 @@ drop_lc:
} }
continue_flow:
lgtrace_addp("continue_flow");
return PKT_CONTINUE;
accept: accept:
lgtrace_addp("accept"); lgtrace_addp("accept");
lgtrace_end();
return PKT_ACCEPT; return PKT_ACCEPT;
drop: drop:
lgtrace_addp("drop"); lgtrace_addp("drop");
lgtrace_end();
return PKT_DROP; return PKT_DROP;
} }
int process_udp_packet(const uint8_t *pkt, uint32_t pktlen) { int process_udp_packet(const struct section_config_t *section, const uint8_t *pkt, uint32_t pktlen) {
const void *iph; const void *iph;
uint32_t iph_len; uint32_t iph_len;
const struct udphdr *udph; const struct udphdr *udph;
const uint8_t *data; const uint8_t *data;
uint32_t dlen; uint32_t dlen;
int ipver = netproto_version(pkt, pktlen); int ipver = netproto_version(pkt, pktlen);
lgtrace_start("Got udp packet");
lgtrace_addp("IPv%d", ipver);
int ret = udp_payload_split((uint8_t *)pkt, pktlen, int ret = udp_payload_split((uint8_t *)pkt, pktlen,
(void **)&iph, &iph_len, (void **)&iph, &iph_len,
@ -334,7 +347,7 @@ int process_udp_packet(const uint8_t *pkt, uint32_t pktlen) {
} }
if (config.quic_drop) { if (section->quic_drop) {
lgtrace_addp("QUIC probe"); lgtrace_addp("QUIC probe");
const struct quic_lhdr *qch; const struct quic_lhdr *qch;
uint32_t qch_len; uint32_t qch_len;
@ -368,9 +381,6 @@ int process_udp_packet(const uint8_t *pkt, uint32_t pktlen) {
lgtrace_addp("quic initial message"); lgtrace_addp("quic initial message");
} }
accept_quic:
;
/* /*
if (1) { if (1) {
lgtrace_addp("Probe udp"); lgtrace_addp("Probe udp");
@ -402,29 +412,26 @@ accept_quic:
*/ */
continue_flow:
lgtrace_addp("continue_flow");
return PKT_CONTINUE;
accept_quic:
accept: accept:
lgtrace_addp("accepted");
lgtrace_end();
return PKT_ACCEPT; return PKT_ACCEPT;
drop: drop:
lgtrace_addp("dropped");
lgtrace_end();
return PKT_DROP; return PKT_DROP;
} }
int send_ip4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) { int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) {
if (poses_sz == 0) { if (poses_sz == 0) {
if (config.seg2_delay && ((dvs > 0) ^ config.frag_sni_reverse)) { if (section->seg2_delay && ((dvs > 0) ^ section->frag_sni_reverse)) {
if (!instance_config.send_delayed_packet) { if (!instance_config.send_delayed_packet) {
return -EINVAL; return -EINVAL;
} }
lgtrace_addp("Sent %d delayed for %d", pktlen, config.seg2_delay); lgtrace_addp("Sent %d delayed for %d", pktlen, section->seg2_delay);
instance_config.send_delayed_packet( instance_config.send_delayed_packet(
packet, pktlen, config.seg2_delay); packet, pktlen, section->seg2_delay);
return 0; return 0;
} else { } else {
@ -479,21 +486,21 @@ int send_ip4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses
dvs += frag_pos; dvs += frag_pos;
if (config.frag_sni_reverse) if (section->frag_sni_reverse)
goto send_frag2; goto send_frag2;
send_frag1: send_frag1:
ret = send_ip4_frags(frag1, f1len, NULL, 0, 0); ret = send_ip4_frags(section, frag1, f1len, NULL, 0, 0);
if (ret < 0) { if (ret < 0) {
goto erret_lc; goto erret_lc;
} }
if (config.frag_sni_reverse) if (section->frag_sni_reverse)
goto out_lc; goto out_lc;
send_fake: send_fake:
/* /*
if (config.frag_sni_faked) { if (section->frag_sni_faked) {
ITER_FAKE_STRAT(config.faking_strategy, strategy) { ITER_FAKE_STRAT(section->faking_strategy, strategy) {
uint32_t iphfl; uint32_t iphfl;
fake_pad_len = f2len; fake_pad_len = f2len;
ret = ip4_payload_split(frag2, f2len, NULL, &iphfl, NULL, NULL); ret = ip4_payload_split(frag2, f2len, NULL, &iphfl, NULL, NULL);
@ -517,16 +524,16 @@ send_fake:
} }
*/ */
if (config.frag_sni_reverse) if (section->frag_sni_reverse)
goto send_frag1; goto send_frag1;
send_frag2: send_frag2:
ret = send_ip4_frags(frag2, f2len, poses + 1, poses_sz - 1, dvs); ret = send_ip4_frags(section, frag2, f2len, poses + 1, poses_sz - 1, dvs);
if (ret < 0) { if (ret < 0) {
goto erret_lc; goto erret_lc;
} }
if (config.frag_sni_reverse) if (section->frag_sni_reverse)
goto send_fake; goto send_fake;
out_lc: out_lc:
@ -545,15 +552,15 @@ out:
return 0; return 0;
} }
int send_tcp_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) { int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) {
if (poses_sz == 0) { if (poses_sz == 0) {
if (config.seg2_delay && ((dvs > 0) ^ config.frag_sni_reverse)) { if (section->seg2_delay && ((dvs > 0) ^ section->frag_sni_reverse)) {
if (!instance_config.send_delayed_packet) { if (!instance_config.send_delayed_packet) {
return -EINVAL; return -EINVAL;
} }
instance_config.send_delayed_packet( instance_config.send_delayed_packet(
packet, pktlen, config.seg2_delay); packet, pktlen, section->seg2_delay);
return 0; return 0;
} else { } else {
@ -601,49 +608,49 @@ int send_tcp_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses
dvs += poses[0]; dvs += poses[0];
if (config.frag_sni_reverse) if (section->frag_sni_reverse)
goto send_frag2; goto send_frag2;
send_frag1: send_frag1:
{ {
ret = send_tcp_frags(frag1, f1len, NULL, 0, 0); ret = send_tcp_frags(section, frag1, f1len, NULL, 0, 0);
if (ret < 0) { if (ret < 0) {
goto erret_lc; goto erret_lc;
} }
if (config.frag_sni_reverse) if (section->frag_sni_reverse)
goto out_lc; goto out_lc;
} }
send_fake: send_fake:
if (config.frag_sni_faked) { if (section->frag_sni_faked) {
uint32_t iphfl, tcphfl; uint32_t iphfl, tcphfl;
void *iph; void *iph;
struct tcphdr *tcph; struct tcphdr *tcph;
ret = tcp_payload_split(frag2, f2len, &iph, &iphfl, &tcph, &tcphfl, NULL, NULL); ret = tcp_payload_split(frag2, f2len, &iph, &iphfl, &tcph, &tcphfl, NULL, NULL);
struct fake_type f_type = args_default_fake_type(); struct fake_type f_type = args_default_fake_type(section);
if ((f_type.strategy.strategy & FAKE_STRAT_PAST_SEQ) == FAKE_STRAT_PAST_SEQ) { if ((f_type.strategy.strategy & FAKE_STRAT_PAST_SEQ) == FAKE_STRAT_PAST_SEQ) {
f_type.strategy.strategy ^= FAKE_STRAT_PAST_SEQ; f_type.strategy.strategy ^= FAKE_STRAT_PAST_SEQ;
f_type.strategy.strategy |= FAKE_STRAT_RAND_SEQ; f_type.strategy.strategy |= FAKE_STRAT_RAND_SEQ;
f_type.strategy.randseq_offset = dvs; f_type.strategy.randseq_offset = dvs;
} }
f_type.seg2delay = config.seg2_delay; f_type.seg2delay = section->seg2_delay;
post_fake_sni(f_type, iph, iphfl, tcph, tcphfl); post_fake_sni(f_type, iph, iphfl, tcph, tcphfl);
} }
if (config.frag_sni_reverse) if (section->frag_sni_reverse)
goto send_frag1; goto send_frag1;
send_frag2: send_frag2:
{ {
ret = send_tcp_frags(frag2, f2len, poses + 1, poses_sz - 1, dvs); ret = send_tcp_frags(section, frag2, f2len, poses + 1, poses_sz - 1, dvs);
if (ret < 0) { if (ret < 0) {
goto erret_lc; goto erret_lc;
} }
if (config.frag_sni_reverse) if (section->frag_sni_reverse)
goto send_fake; goto send_fake;
} }
out_lc: out_lc:

View File

@ -6,6 +6,8 @@
#define PKT_ACCEPT 0 #define PKT_ACCEPT 0
#define PKT_DROP 1 #define PKT_DROP 1
// Used for section config
#define PKT_CONTINUE 2
/** /**
* Processes the packet and returns verdict. * Processes the packet and returns verdict.
@ -18,14 +20,14 @@ int process_packet(const uint8_t *packet, uint32_t packet_len);
* Processe the TCP packet. * Processe the TCP packet.
* Returns verdict. * Returns verdict.
*/ */
int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len); int process_tcp_packet(const struct section_config_t *section, const uint8_t *raw_payload, uint32_t raw_payload_len);
/** /**
* Processes the UDP packet. * Processes the UDP packet.
* Returns verdict. * Returns verdict.
*/ */
int process_udp_packet(const uint8_t *pkt, uint32_t pktlen); int process_udp_packet(const struct section_config_t *section, const uint8_t *pkt, uint32_t pktlen);
@ -41,7 +43,7 @@ int post_fake_sni(struct fake_type f_type,
* Poses are relative to start of TCP payload. * Poses are relative to start of TCP payload.
* dvs used internally and should be zero. * dvs used internally and should be zero.
*/ */
int send_tcp_frags( int send_tcp_frags(const struct section_config_t *section,
const uint8_t *packet, uint32_t pktlen, const uint8_t *packet, uint32_t pktlen,
const uint32_t *poses, uint32_t poses_len, uint32_t dvs); const uint32_t *poses, uint32_t poses_len, uint32_t dvs);
@ -50,7 +52,7 @@ int send_tcp_frags(
* Poses are relative to start of TCP payload. * Poses are relative to start of TCP payload.
* dvs used internally and should be zero. * dvs used internally and should be zero.
*/ */
int send_ip4_frags( int send_ip4_frags(const struct section_config_t *section,
const uint8_t *packet, uint32_t pktlen, const uint8_t *packet, uint32_t pktlen,
const uint32_t *poses, uint32_t poses_len, uint32_t dvs); const uint32_t *poses, uint32_t poses_len, uint32_t dvs);
#endif /* YU_MANGLE_H */ #endif /* YU_MANGLE_H */

45
tls.c
View File

@ -21,6 +21,7 @@
* dlen Length of `data`. * dlen Length of `data`.
*/ */
struct tls_verdict analyze_tls_data( struct tls_verdict analyze_tls_data(
const struct section_config_t *section,
const uint8_t *data, const uint8_t *data,
uint32_t dlen) uint32_t dlen)
{ {
@ -43,7 +44,7 @@ struct tls_verdict analyze_tls_data(
if (tls_content_type != TLS_CONTENT_TYPE_HANDSHAKE) if (tls_content_type != TLS_CONTENT_TYPE_HANDSHAKE)
goto nextMessage; goto nextMessage;
if (config.sni_detection == SNI_DETECTION_BRUTE) { if (section->sni_detection == SNI_DETECTION_BRUTE) {
goto brute; goto brute;
} }
@ -126,22 +127,22 @@ struct tls_verdict analyze_tls_data(
vrd.sni_len = sni_len; vrd.sni_len = sni_len;
vrd.sni_target_len = vrd.sni_len; vrd.sni_target_len = vrd.sni_len;
if (config.all_domains) { if (section->all_domains) {
vrd.target_sni = 1; vrd.target_sni = 1;
goto check_domain; goto check_domain;
} }
unsigned int j = 0; unsigned int j = 0;
for (unsigned int i = 0; i <= config.domains_strlen; i++) { for (unsigned int i = 0; i <= section->domains_strlen; i++) {
if ( i > j && if ( i > j &&
(i == config.domains_strlen || (i == section->domains_strlen ||
config.domains_str[i] == '\0' || section->domains_str[i] == '\0' ||
config.domains_str[i] == ',' || section->domains_str[i] == ',' ||
config.domains_str[i] == '\n' )) { section->domains_str[i] == '\n' )) {
unsigned int domain_len = (i - j); unsigned int domain_len = (i - j);
const char *sni_startp = sni_name + sni_len - domain_len; const char *sni_startp = sni_name + sni_len - domain_len;
const char *domain_startp = config.domains_str + j; const char *domain_startp = section->domains_str + j;
if (sni_len >= domain_len && if (sni_len >= domain_len &&
sni_len < 128 && sni_len < 128 &&
@ -159,18 +160,18 @@ struct tls_verdict analyze_tls_data(
} }
check_domain: check_domain:
if (vrd.target_sni == 1 && config.exclude_domains_strlen != 0) { if (vrd.target_sni == 1 && section->exclude_domains_strlen != 0) {
unsigned int j = 0; unsigned int j = 0;
for (unsigned int i = 0; i <= config.exclude_domains_strlen; i++) { for (unsigned int i = 0; i <= section->exclude_domains_strlen; i++) {
if ( i > j && if ( i > j &&
(i == config.exclude_domains_strlen || (i == section->exclude_domains_strlen ||
config.exclude_domains_str[i] == '\0' || section->exclude_domains_str[i] == '\0' ||
config.exclude_domains_str[i] == ',' || section->exclude_domains_str[i] == ',' ||
config.exclude_domains_str[i] == '\n' )) { section->exclude_domains_str[i] == '\n' )) {
unsigned int domain_len = (i - j); unsigned int domain_len = (i - j);
const char *sni_startp = sni_name + sni_len - domain_len; const char *sni_startp = sni_name + sni_len - domain_len;
const char *domain_startp = config.exclude_domains_str + j; const char *domain_startp = section->exclude_domains_str + j;
if (sni_len >= domain_len && if (sni_len >= domain_len &&
sni_len < 128 && sni_len < 128 &&
@ -203,7 +204,7 @@ out:
brute: brute:
if (config.all_domains) { if (section->all_domains) {
vrd.target_sni = 1; vrd.target_sni = 1;
vrd.sni_len = 0; vrd.sni_len = 0;
vrd.sni_offset = dlen / 2; vrd.sni_offset = dlen / 2;
@ -211,15 +212,15 @@ brute:
} }
unsigned int j = 0; unsigned int j = 0;
for (unsigned int i = 0; i <= config.domains_strlen; i++) { for (unsigned int i = 0; i <= section->domains_strlen; i++) {
if ( i > j && if ( i > j &&
(i == config.domains_strlen || (i == section->domains_strlen ||
config.domains_str[i] == '\0' || section->domains_str[i] == '\0' ||
config.domains_str[i] == ',' || section->domains_str[i] == ',' ||
config.domains_str[i] == '\n' )) { section->domains_str[i] == '\n' )) {
unsigned int domain_len = (i - j); unsigned int domain_len = (i - j);
const char *domain_startp = config.domains_str + j; const char *domain_startp = section->domains_str + j;
if (domain_len + dlen + 1> MAX_PACKET_SIZE) { if (domain_len + dlen + 1> MAX_PACKET_SIZE) {
continue; continue;

2
tls.h
View File

@ -20,7 +20,7 @@ struct tls_verdict {
* Processes the packet and finds TLS Client Hello information inside it. * Processes the packet and finds TLS Client Hello information inside it.
* data pointer points to start of TLS Message (TCP Payload) * data pointer points to start of TLS Message (TCP Payload)
*/ */
struct tls_verdict analyze_tls_data(const uint8_t *data, uint32_t dlen); struct tls_verdict analyze_tls_data(const struct section_config_t *section, const uint8_t *data, uint32_t dlen);
/** /**

24
utils.h
View File

@ -157,34 +157,34 @@ int seqovl_packet(uint8_t *payload, uint32_t *plen, uint32_t seq_delta);
static inline struct failing_strategy args_default_failing_strategy(void) { static inline struct failing_strategy args_default_failing_strategy(const struct section_config_t *section) {
struct failing_strategy fl_strat = { struct failing_strategy fl_strat = {
.strategy = (unsigned int)config.faking_strategy, .strategy = (unsigned int)section->faking_strategy,
.faking_ttl = config.faking_ttl, .faking_ttl = section->faking_ttl,
.randseq_offset = (uint32_t)config.fakeseq_offset .randseq_offset = (uint32_t)section->fakeseq_offset
}; };
return fl_strat; return fl_strat;
} }
static inline struct fake_type args_default_fake_type(void) { static inline struct fake_type args_default_fake_type(const struct section_config_t *section) {
struct fake_type f_type = { struct fake_type f_type = {
.sequence_len = config.fake_sni_seq_len, .sequence_len = section->fake_sni_seq_len,
.strategy = args_default_failing_strategy(), .strategy = args_default_failing_strategy(section),
}; };
switch (config.fake_sni_type) { switch (section->fake_sni_type) {
case FAKE_PAYLOAD_RANDOM: case FAKE_PAYLOAD_RANDOM:
f_type.type = FAKE_PAYLOAD_RANDOM; f_type.type = FAKE_PAYLOAD_RANDOM;
break; break;
case FAKE_PAYLOAD_CUSTOM: case FAKE_PAYLOAD_CUSTOM:
f_type.type = FAKE_PAYLOAD_CUSTOM; f_type.type = FAKE_PAYLOAD_CUSTOM;
f_type.fake_data = config.fake_custom_pkt; f_type.fake_data = section->fake_custom_pkt;
f_type.fake_len = config.fake_custom_pkt_sz; f_type.fake_len = section->fake_custom_pkt_sz;
break; break;
default: default:
f_type.type = FAKE_PAYLOAD_CUSTOM; f_type.type = FAKE_PAYLOAD_CUSTOM;
f_type.fake_data = config.fake_sni_pkt; f_type.fake_data = section->fake_sni_pkt;
f_type.fake_len = config.fake_sni_pkt_sz; f_type.fake_len = section->fake_sni_pkt_sz;
} }
return f_type; return f_type;

View File

@ -264,28 +264,12 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
uint8_t buff2[MNL_SOCKET_BUFFER_SIZE]; uint8_t buff2[MNL_SOCKET_BUFFER_SIZE];
uint32_t buff2_size = MNL_SOCKET_BUFFER_SIZE; uint32_t buff2_size = MNL_SOCKET_BUFFER_SIZE;
switch (config.fragmentation_strategy) {
case FRAG_STRAT_TCP:
if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128, if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128,
buff1, &buff1_size, buff2, &buff2_size)) < 0) { buff1, &buff1_size, buff2, &buff2_size)) < 0) {
errno = -ret; errno = -ret;
return ret; return ret;
} }
break;
case FRAG_STRAT_IP:
if ((ret = ip4_frag(pkt, pktlen, AVAILABLE_MTU-128,
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
errno = -ret;
return ret;
}
break;
default:
errno = EINVAL;
printf("send_raw_socket: Packet is too big but fragmentation is disabled!\n");
return -EINVAL;
}
int sent = 0; int sent = 0;
int status = send_raw_socket(buff1, buff1_size); int status = send_raw_socket(buff1, buff1_size);