Update trace logging

This commit is contained in:
Vadim Vetrov
2025-01-07 23:28:01 +03:00
parent 7b321b5a2d
commit a3bd918484
16 changed files with 302 additions and 588 deletions

2
Kbuild
View File

@@ -1,3 +1,3 @@
obj-m := kyoutubeUnblock.o
kyoutubeUnblock-objs := src/kytunblock.o src/mangle.o src/quic.o src/quic_crypto.o src/utils.o src/kargs.o src/tls.o src/getopt.o src/args.o deps/cyclone/aes.o deps/cyclone/cpu_endian.o deps/cyclone/ecb.o deps/cyclone/gcm.o deps/cyclone/hkdf.o deps/cyclone/hmac.o deps/cyclone/sha256.o
kyoutubeUnblock-objs := src/kytunblock.o src/mangle.o src/quic.o src/quic_crypto.o src/utils.o src/kargs.o src/tls.o src/getopt.o src/inet_ntop.o src/args.o deps/cyclone/aes.o deps/cyclone/cpu_endian.o deps/cyclone/ecb.o deps/cyclone/gcm.o deps/cyclone/hkdf.o deps/cyclone/hmac.o deps/cyclone/sha256.o
ccflags-y := -std=gnu99 -DKERNEL_SPACE -Wno-error -Wno-declaration-after-statement -I$(src)/src -I$(src)/deps/cyclone/include

View File

@@ -196,6 +196,8 @@ Flags that do not scoped to a specific section, used over all the youtubeUnblock
- `--trace` Maximum verbosity for debugging purposes.
- `--instaflush` Used with tracing. Flushes the buffer instantly, without waiting for explicit new line. Highly useful for debugging crushes.
- `--no-gso` Disables support for Google Chrome fat packets which uses GSO. This feature is well tested now, so this flag probably won't fix anything.
- `--no-ipv6` Disables support for ipv6. May be useful if you don't want for ipv6 socket to be opened.

View File

@@ -26,6 +26,14 @@
#include "getopt.h"
#include "raw_replacements.h"
/**
* Logging definitions
*/
char ylgh_buf[LOGGING_BUFSIZE];
size_t ylgh_leftbuf = LOGGING_BUFSIZE;
char *ylgh_curptr = ylgh_buf;
int ylgh_ndnl = 0;
#ifdef KERNEL_SPACE
static int errno = 0;
#define strtol kstrtol
@@ -253,6 +261,7 @@ enum {
OPT_FRAG_SNI_POS,
OPT_FK_WINSIZE,
OPT_TRACE,
OPT_INSTAFLUSH,
OPT_QUIC_DROP,
OPT_SNI_DETECTION,
OPT_NO_IPV6,
@@ -311,6 +320,7 @@ static struct option long_opt[] = {
{"threads", 1, 0, OPT_THREADS},
{"silent", 0, 0, OPT_SILENT},
{"trace", 0, 0, OPT_TRACE},
{"instaflush", 0, 0, OPT_INSTAFLUSH},
{"no-gso", 0, 0, OPT_NO_GSO},
{"no-ipv6", 0, 0, OPT_NO_IPV6},
{"daemonize", 0, 0, OPT_DAEMONIZE},
@@ -374,6 +384,7 @@ void print_usage(const char *argv0) {
printf("\t--connbytes-limit=<pkts>\n");
printf("\t--silent\n");
printf("\t--trace\n");
printf("\t--instaflush\n");
printf("\t--no-gso\n");
printf("\t--no-ipv6\n");
printf("\t--daemonize\n");
@@ -439,10 +450,13 @@ int yparse_args(int argc, char *argv[]) {
break;
#endif
case OPT_TRACE:
rep_config.verbose = 2;
rep_config.verbose = VERBOSE_TRACE;
break;
case OPT_INSTAFLUSH:
rep_config.instaflush = 1;
break;
case OPT_SILENT:
rep_config.verbose = 0;
rep_config.verbose = VERBOSE_INFO;
break;
case OPT_NO_GSO:
rep_config.use_gso = 0;
@@ -1014,6 +1028,9 @@ size_t print_config(char *buffer, size_t buffer_size) {
if (config.verbose == VERBOSE_TRACE) {
print_cnf_buf("--trace");
}
if (config.instaflush) {
print_cnf_buf("--instaflush");
}
if (config.verbose == VERBOSE_INFO) {
print_cnf_buf("--silent");
}

View File

@@ -118,6 +118,7 @@ struct config_t {
// Same as daemon() noclose
int noclose;
int syslog;
int instaflush;
int connbytes_limit;
@@ -275,6 +276,7 @@ enum {
.daemonize = 0, \
.noclose = 0, \
.syslog = 0, \
.instaflush = 0, \
}
#define CONFIG_SET(config) \

View File

@@ -33,7 +33,7 @@ int optind=1, opterr=1, optopt, __optpos, optreset=0;
static void __getopt_msg(const char *b, const char *c, size_t l)
{
lgerr("%s %.*s\n", b, (int)l, c);
lgerr("%s %.*s", b, (int)l, c);
}
int getopt(int argc, char * const argv[], const char *optstring)

78
src/inet_ntop.c Normal file
View File

@@ -0,0 +1,78 @@
/**
musl libc
musl, pronounced like the word "mussel", is an MIT-licensed
implementation of the standard C library targetting the Linux syscall
API, suitable for use in a wide range of deployment environments. musl
offers efficient static and dynamic linking support, lightweight code
and low runtime overhead, strong fail-safe guarantees under correct
usage, and correctness in the sense of standards conformance and
safety. musl is built on the principle that these goals are best
achieved through simple code that is easy to understand and maintain.
The 1.1 release series for musl features coverage for all interfaces
defined in ISO C99 and POSIX 2008 base, along with a number of
non-standardized interfaces for compatibility with Linux, BSD, and
glibc functionality.
For basic installation instructions, see the included INSTALL file.
Information on full musl-targeted compiler toolchains, system
bootstrapping, and Linux distributions built on musl can be found on
the project website:
http://www.musl-libc.org/
*/
#include "types.h"
// #ifndef KERNEL_SPACE
// #error "For user space use glibc inet_ntop"
// #endif
const char *inet_ntop(int af, const void *restrict a0, char *restrict s, socklen_t l)
{
const unsigned char *a = a0;
int i, j, max, best;
char buf[100];
switch (af) {
case AF_INET:
if (snprintf(s, l, "%d.%d.%d.%d", a[0],a[1],a[2],a[3]) < l)
return s;
break;
case AF_INET6:
if (memcmp(a, "\0\0\0\0\0\0\0\0\0\0\377\377", 12))
snprintf(buf, sizeof buf,
"%x:%x:%x:%x:%x:%x:%x:%x",
256*a[0]+a[1],256*a[2]+a[3],
256*a[4]+a[5],256*a[6]+a[7],
256*a[8]+a[9],256*a[10]+a[11],
256*a[12]+a[13],256*a[14]+a[15]);
else
snprintf(buf, sizeof buf,
"%x:%x:%x:%x:%x:%x:%d.%d.%d.%d",
256*a[0]+a[1],256*a[2]+a[3],
256*a[4]+a[5],256*a[6]+a[7],
256*a[8]+a[9],256*a[10]+a[11],
a[12],a[13],a[14],a[15]);
/* Replace longest /(^0|:)[:0]{2,}/ with "::" */
for (i=best=0, max=2; buf[i]; i++) {
if (i && buf[i] != ':') continue;
j = strspn(buf+i, ":0");
if (j>max) best=i, max=j;
}
if (max>3) {
buf[best] = buf[best+1] = ':';
memmove(buf+best+2, buf+best+max, i-best-max+1);
}
if (strlen(buf) < l) {
strcpy(s, buf);
return s;
}
break;
default:
return 0;
}
return 0;
}

View File

@@ -74,511 +74,3 @@ static const struct kernel_param_ops params_ops = {
};
module_param_cb(parameters, &params_ops, NULL, 0664);
//
// static char custom_fake_buf[MAX_FAKE_SIZE];
//
// 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
// };
//
// #define def_section (&config.default_config)
//
// static int unumeric_set(const char *val, const struct kernel_param *kp) {
// int n = 0, ret;
// ret = kstrtoint(val, 10, &n);
// if (ret != 0 || n < 0)
// return -EINVAL;
//
//
// return param_set_int(val, kp);
// }
//
// static int boolean_set(const char *val, const struct kernel_param *kp) {
// int n = 0, ret;
// ret = kstrtoint(val, 10, &n);
// if (ret != 0 || (n != 0 && n != 1))
// return -EINVAL;
//
// return param_set_int(val, kp);
// }
//
// static int inverse_boolean_set(const char *val, const struct kernel_param *kp) {
// int n = 0, ret;
// ret = kstrtoint(val, 10, &n);
// if (ret != 0 || (n != 0 && n != 1))
// return -EINVAL;
//
// n = !n;
// if (kp->arg == NULL)
// return -EINVAL;
//
// *(int *)kp->arg = n;
// return 0;
// }
//
// static int inverse_boolean_get(char *buffer, const struct kernel_param *kp) {
// if (*(int *)kp->arg == 0) {
// buffer[0] = '1';
// } else {
// buffer[0] = '0';
// }
// buffer[1] = '\0';
// return strlen(buffer);
// }
//
// static const struct kernel_param_ops unumeric_parameter_ops = {
// .set = unumeric_set,
// .get = param_get_int
// };
//
// static const struct kernel_param_ops boolean_parameter_ops = {
// .set = boolean_set,
// .get = param_get_int
// };
//
// static const struct kernel_param_ops inverse_boolean_ops = {
// .set = inverse_boolean_set,
// .get = inverse_boolean_get,
// };
//
// module_param_cb(fake_sni, &boolean_parameter_ops, &def_section->fake_sni, 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, &def_section->faking_ttl, 0664);
// module_param_cb(fake_seq_offset, &unumeric_parameter_ops, &def_section->fakeseq_offset, 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, &def_section->frag_sni_faked, 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, &def_section->frag_sni_pos, 0664);
// module_param_cb(fk_winsize, &unumeric_parameter_ops, &def_section->fk_winsize, 0664);
// module_param_cb(synfake, &boolean_parameter_ops, &def_section->synfake, 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(seg2delay, &unumeric_parameter_ops, &def_section->seg2_delay, 0664);
//
// static int sni_domains_set(const char *val, const struct kernel_param *kp) {
// size_t len;
// int ret;
//
// len = strnlen(val, STR_MAXLEN + 1);
// if (len == STR_MAXLEN + 1) {
// pr_err("%s: string parameter too long\n", kp->name);
// return -ENOSPC;
// }
//
// if (len >= 1 && val[len - 1] == '\n') {
// len--;
// }
//
// ret = param_set_charp(val, kp);
//
// if (ret < 0) {
// def_section->domains_strlen = 0;
// } else {
// def_section->domains_strlen = len;
// if (len == 3 && !strncmp(val, "all", len)) {
// def_section->all_domains = 1;
// } else {
// def_section->all_domains = 0;
// }
// }
//
//
// return ret;
// }
//
// static const struct kernel_param_ops sni_domains_ops = {
// .set = sni_domains_set,
// .get = param_get_charp,
// };
//
// 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) {
// size_t len;
// int ret;
//
// len = strnlen(val, STR_MAXLEN + 1);
// if (len == STR_MAXLEN + 1) {
// pr_err("%s: string parameter too long\n", kp->name);
// return -ENOSPC;
// }
//
// ret = param_set_charp(val, kp);
//
// if (ret < 0) {
// def_section->exclude_domains_strlen = 0;
// } else {
// def_section->exclude_domains_strlen = len;
// }
//
// return ret;
// }
//
// static const struct kernel_param_ops exclude_domains_ops = {
// .set = exclude_domains_set,
// .get = param_get_charp,
// };
//
// 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);
//
// static int quic_drop_set(const char *val, const struct kernel_param *kp) {
// int n = 0, ret;
// ret = kstrtoint(val, 10, &n);
// if (ret != 0 || (n != 0 && n != 1))
// return -EINVAL;
//
// if (n) {
// def_section->udp_mode = UDP_MODE_DROP;
// def_section->udp_filter_quic = UDP_FILTER_QUIC_ALL;
// } else {
// def_section->udp_filter_quic = UDP_FILTER_QUIC_DISABLED;
// }
//
// return 0;
// }
//
// static int quic_drop_get(char *buffer, const struct kernel_param *kp) {
// if (def_section->udp_mode == UDP_MODE_DROP &&
// def_section->udp_filter_quic == UDP_FILTER_QUIC_ALL) {
// return sprintf(buffer, "%d\n", 1);
// } else {
// return sprintf(buffer, "%d\n", 0);
// }
// }
//
// static const struct kernel_param_ops quic_drop_ops = {
// .set = quic_drop_set,
// .get = quic_drop_get
// };
//
// module_param_cb(quic_drop, &quic_drop_ops, NULL, 0664);
//
// static int verbosity_set(const char *val, const struct kernel_param *kp) {
// size_t len;
//
// len = strnlen(val, STR_MAXLEN + 1);
// if (len == STR_MAXLEN + 1) {
// pr_err("%s: string parameter too long\n", kp->name);
// return -ENOSPC;
// }
//
// if (len >= 1 && val[len - 1] == '\n') {
// len--;
// }
//
// if (strncmp(val, "trace", len) == 0) {
// *(int *)kp->arg = VERBOSE_TRACE;
// } else if (strncmp(val, "debug", len) == 0) {
// *(int *)kp->arg = VERBOSE_DEBUG;
// } else if (strncmp(val, "silent", len) == 0) {
// *(int *)kp->arg = VERBOSE_INFO;
// } else {
// return -EINVAL;
// }
//
// return 0;
// }
//
//
// static int verbosity_get(char *buffer, const struct kernel_param *kp) {
// switch (*(int *)kp->arg) {
// case VERBOSE_TRACE:
// strcpy(buffer, "trace\n");
// break;
// case VERBOSE_DEBUG:
// strcpy(buffer, "debug\n");
// break;
// case VERBOSE_INFO:
// strcpy(buffer, "silent\n");
// break;
// default:
// strcpy(buffer, "unknown\n");
// }
//
// return strlen(buffer);
// }
//
// static const struct kernel_param_ops verbosity_ops = {
// .set = verbosity_set,
// .get = verbosity_get,
// };
//
// module_param_cb(verbosity, &verbosity_ops, &config.verbose, 0664);
//
// static int frag_strat_set(const char *val, const struct kernel_param *kp) {
// size_t len;
//
// len = strnlen(val, STR_MAXLEN + 1);
// if (len == STR_MAXLEN + 1) {
// pr_err("%s: string parameter too long\n", kp->name);
// return -ENOSPC;
// }
//
// if (len >= 1 && val[len - 1] == '\n') {
// len--;
// }
//
// if (strncmp(val, "tcp", len) == 0) {
// *(int *)kp->arg = FRAG_STRAT_TCP;
// } else if (strncmp(val, "ip", len) == 0) {
// *(int *)kp->arg = FRAG_STRAT_IP;
// } else if (strncmp(val, "none", len) == 0) {
// *(int *)kp->arg = FRAG_STRAT_NONE;
// } else {
// return -EINVAL;
// }
//
// return 0;
// }
//
// static int frag_strat_get(char *buffer, const struct kernel_param *kp) {
// switch (*(int *)kp->arg) {
// case FRAG_STRAT_TCP:
// strcpy(buffer, "tcp\n");
// break;
// case FRAG_STRAT_IP:
// strcpy(buffer, "ip\n");
// break;
// case FRAG_STRAT_NONE:
// strcpy(buffer, "none\n");
// break;
// default:
// strcpy(buffer, "unknown\n");
// }
//
// return strlen(buffer);
// }
//
// static const struct kernel_param_ops frag_strat_ops = {
// .set = frag_strat_set,
// .get = frag_strat_get,
// };
//
// 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) {
// size_t len;
//
// len = strnlen(val, STR_MAXLEN + 1);
// if (len == STR_MAXLEN + 1) {
// pr_err("%s: string parameter too long\n", kp->name);
// return -ENOSPC;
// }
//
// if (len >= 1 && val[len - 1] == '\n') {
// len--;
// }
//
// if (strncmp(val, "randseq", len) == 0) {
// *(int *)kp->arg = FAKE_STRAT_RAND_SEQ;
// } else if (strncmp(val, "ttl", len) == 0) {
// *(int *)kp->arg = FAKE_STRAT_TTL;
// } else if (strncmp(val, "tcp_check", len) == 0) {
// *(int *)kp->arg = FAKE_STRAT_TCP_CHECK;
// } else if (strncmp(val, "pastseq", len) == 0) {
// *(int *)kp->arg = FAKE_STRAT_PAST_SEQ;
// } else if (strncmp(val, "md5sum", len) == 0) {
// *(int *)kp->arg = FAKE_STRAT_TCP_MD5SUM;
// } else {
// return -EINVAL;
// }
//
// return 0;
// }
//
// static int fake_strat_get(char *buffer, const struct kernel_param *kp) {
// switch (*(int *)kp->arg) {
// case FAKE_STRAT_RAND_SEQ:
// strcpy(buffer, "randseq\n");
// break;
// case FAKE_STRAT_TTL:
// strcpy(buffer, "ttl\n");
// break;
// case FAKE_STRAT_TCP_CHECK:
// strcpy(buffer, "tcp_check\n");
// break;
// case FAKE_STRAT_PAST_SEQ:
// strcpy(buffer, "pastseq\n");
// break;
// case FAKE_STRAT_TCP_MD5SUM:
// strcpy(buffer, "md5sum\n");
// break;
// default:
// strcpy(buffer, "unknown\n");
// }
//
// return strlen(buffer);
// }
//
// static const struct kernel_param_ops fake_strat_ops = {
// .set = fake_strat_set,
// .get = fake_strat_get,
// };
//
// 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) {
// size_t len;
//
// len = strnlen(val, STR_MAXLEN + 1);
// if (len == STR_MAXLEN + 1) {
// pr_err("%s: string parameter too long\n", kp->name);
// return -ENOSPC;
// }
//
// if (len >= 1 && val[len - 1] == '\n') {
// len--;
// }
//
// if (strncmp(val, "parse", len) == 0) {
// *(int *)kp->arg = SNI_DETECTION_PARSE;
// } else if (strncmp(val, "brute", len) == 0) {
// *(int *)kp->arg = SNI_DETECTION_BRUTE;
// } else {
// return -EINVAL;
// }
//
// return 0;
// }
//
// static int sni_detection_get(char *buffer, const struct kernel_param *kp) {
// switch (*(int *)kp->arg) {
// case SNI_DETECTION_PARSE:
// strcpy(buffer, "parse\n");
// break;
// case SNI_DETECTION_BRUTE:
// strcpy(buffer, "brute\n");
// break;
// default:
// strcpy(buffer, "unknown\n");
// }
//
// return strlen(buffer);
// }
//
// static const struct kernel_param_ops sni_detection_ops = {
// .set = sni_detection_set,
// .get = sni_detection_get,
// };
//
// 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) {
// size_t len;
//
// len = strnlen(val, STR_MAXLEN + 1);
// if (len == STR_MAXLEN + 1) {
// pr_err("%s: string parameter too long\n", kp->name);
// return -ENOSPC;
// }
//
// if (len >= 1 && val[len - 1] == '\n') {
// len--;
// }
//
// if (strncmp(val, "default", len) == 0) {
// *(int *)kp->arg = FAKE_PAYLOAD_DEFAULT;
// } else if (strncmp(val, "custom", len) == 0) {
// *(int *)kp->arg = FAKE_PAYLOAD_CUSTOM;
// } else if (strncmp(val, "random", len) == 0) {
// *(int *)kp->arg = FAKE_PAYLOAD_RANDOM;
// } else {
// return -EINVAL;
// }
//
// return 0;
// }
//
// static int fake_type_get(char *buffer, const struct kernel_param *kp) {
// switch (*(int *)kp->arg) {
// case FAKE_PAYLOAD_DEFAULT:
// strcpy(buffer, "default\n");
// break;
// case FAKE_PAYLOAD_RANDOM:
// strcpy(buffer, "random\n");
// break;
// case FAKE_PAYLOAD_CUSTOM:
// strcpy(buffer, "custom\n");
// break;
// default:
// strcpy(buffer, "unknown\n");
// }
//
// return strlen(buffer);
// }
//
// static const struct kernel_param_ops fake_type_ops = {
// .set = fake_type_set,
// .get = fake_type_get,
// };
//
// 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) {
// size_t len;
//
// len = strnlen(val, STR_MAXLEN + 1);
// if (len == STR_MAXLEN + 1) {
// pr_err("%s: string parameter too long\n", kp->name);
// return -ENOSPC;
// }
//
// if (len >= 1 && val[len - 1] == '\n') {
// len--;
// }
//
// uint8_t *const custom_buf = (uint8_t *)custom_fake_buf;
// const char *custom_hex_fake = val;
// size_t custom_hlen = len;
//
// if ((custom_hlen & 1) == 1) {
// return -EINVAL;
// }
//
//
// size_t custom_len = custom_hlen >> 1;
// if (custom_len > MAX_FAKE_SIZE) {
// return -EINVAL;
// }
//
// for (int i = 0; i < custom_len; i++) {
// sscanf(custom_hex_fake + (i << 1), "%2hhx", custom_buf + i);
// }
//
// def_section->fake_custom_pkt_sz = custom_len;
// def_section->fake_custom_pkt = (char *)custom_buf;
//
// return 0;
// }
//
// static int fake_custom_pl_get(char *buffer, const struct kernel_param *kp) {
// int cflen = def_section->fake_custom_pkt_sz;
// const uint8_t *cbf_data = def_section->fake_custom_pkt;
// int bflen = def_section->fake_custom_pkt_sz << 1;
//
// for (int i = 0; i < cflen; i++) {
// sprintf(buffer + (i << 1), "%02x", *((unsigned char *)cbf_data + i));
// }
//
// return bflen;
// }
//
// static const struct kernel_param_ops fake_custom_pl_ops = {
// .set = fake_custom_pl_set,
// .get = fake_custom_pl_get,
// };
//
// module_param_cb(fake_custom_payload, &fake_custom_pl_ops, &def_section->fake_custom_pkt, 0664);

View File

@@ -21,8 +21,6 @@
#define LOGGING_H
#include "config.h"
#define LOG_LEVEL (config.verbose)
#ifdef KERNEL_SPACE
#include <linux/kernel.h>
#include <linux/module.h>
@@ -33,26 +31,80 @@
#define LOG_INFO KERN_INFO
#define LOG_WARN KERN_WARNING
#define log_message(level, msg, ...) \
#define print_message(level, msg, ...) \
(printk(level msg, ##__VA_ARGS__))
#define lgerror(ret, msg, ...) \
(log_message(LOG_ERR, msg ": %d\n", ##__VA_ARGS__, ret))
#else
#include <stdio.h> // IWYU pragma: export
#include <errno.h>
#include <syslog.h>
#define log_message(level, msg, ...) \
(config.syslog ? (void)(syslog((level), msg, ##__VA_ARGS__)) : (void)(printf(msg, ##__VA_ARGS__)))
#define print_message(level, msg, ...) \
(config.syslog ? (void)(syslog((level), msg, ##__VA_ARGS__)) : (void)(printf(msg, ##__VA_ARGS__) + fflush(stdout)))
#define lgerror(ret, msg, ...) __extension__ ({ \
errno = -(ret); \
log_message(LOG_ERR, msg ": %s\n", ##__VA_ARGS__, strerror(errno)); \
})
#endif /* PROGRAM_SPACE */
/**
* Defined in args.c
*/
#define LOGGING_BUFSIZE 4096
extern char ylgh_buf[LOGGING_BUFSIZE];
extern size_t ylgh_leftbuf;
extern char *ylgh_curptr;
extern int ylgh_ndnl;
#define LOG_LEVEL (config.verbose)
/**
* For flushing only. Use log_buf_write for writing.
*/
#define log_buf_flush(level) __extension__ ({ \
if (ylgh_leftbuf != LOGGING_BUFSIZE) { \
print_message(level, "%s", ylgh_buf);\
ylgh_curptr = ylgh_buf; \
ylgh_leftbuf = LOGGING_BUFSIZE; \
} \
})
#define log_buf(level, msg, ...) __extension__ ({ \
int lgrtrt; \
lgrtrt=snprintf(ylgh_curptr, ylgh_leftbuf, msg, ##__VA_ARGS__); \
if (lgrtrt < 0 || lgrtrt >= ylgh_leftbuf) { \
ylgh_leftbuf = 0; \
log_buf_flush(level); \
} else { \
ylgh_leftbuf -= lgrtrt; \
ylgh_curptr += lgrtrt; \
} \
})
#define log_buf_write(level) __extension__ ({ \
if (ylgh_ndnl) { \
log_buf(level, "\n"); \
ylgh_ndnl = 0; \
} \
log_buf_flush(level); \
})
#define log_message(level, msg, ...) __extension__ ({ \
if (ylgh_leftbuf != LOGGING_BUFSIZE) { \
log_buf_write(LOG_INFO); \
log_buf(level, "[NOTICE] "); \
} \
log_buf(level, msg, ##__VA_ARGS__); \
ylgh_ndnl = 1; \
log_buf_write(level); \
})
#ifdef KERNEL_SPACE
#define lgerror(code, msg, ...) \
(log_message(LOG_ERR, msg ": %d", ##__VA_ARGS__, code))
#else
#define lgerror(code, msg, ...) \
log_message(LOG_ERR, msg ": %s", ##__VA_ARGS__, strerror(-code));
#endif
#define lgerr(msg, ...) \
(log_message(LOG_ERR, msg, ##__VA_ARGS__))
@@ -63,27 +115,36 @@
#define lginfo(msg, ...) \
(log_message(LOG_INFO, msg, ##__VA_ARGS__))
#define print_message(...) \
(lginfo(__VA_ARGS__))
#define lgdebug(msg, ...) \
(LOG_LEVEL >= VERBOSE_DEBUG ? log_message(LOG_INFO, msg, ##__VA_ARGS__) : (void)0)
#define lgdebugmsg(msg, ...) lgdebug(msg "\n", ##__VA_ARGS__)
#define lgtrace(msg, ...) \
(LOG_LEVEL >= VERBOSE_TRACE ? log_message(LOG_INFO, msg, ##__VA_ARGS__) : (void)0)
#define lgtracemsg(msg, ...) lgtrace(msg "\n", __VA_ARGS__)
#define lgtrace_start() \
lgtrace("---[TRACE PACKET START]---")
#define lgtrace_start(msg, ...) \
(LOG_LEVEL >= VERBOSE_TRACE ? log_message(LOG_INFO, "[TRACE] " msg " ( ", ##__VA_ARGS__) : (void)0)
#define lgtrace_wr(msg, ...) __extension__ ({ \
if (LOG_LEVEL >= VERBOSE_TRACE) { \
ylgh_ndnl = 1; \
log_buf(LOG_INFO, msg, ##__VA_ARGS__); \
if (config.instaflush) { \
log_buf_flush(LOG_INFO); \
} \
} \
})
#define lgtrace_addp(msg, ...) \
(LOG_LEVEL >= VERBOSE_TRACE ? log_message(LOG_INFO, msg", ", ##__VA_ARGS__) : (void)0)
lgtrace_wr(msg ", ", ##__VA_ARGS__)
#define lgtrace_end() \
(LOG_LEVEL >= VERBOSE_TRACE ? log_message(LOG_INFO, ") \n") : (void)0)
#define lgtrace_write() \
(LOG_LEVEL >= VERBOSE_TRACE ? log_buf_write(LOG_INFO) : (void)0)
#define lgtrace_end() __extension__ ({ \
if (LOG_LEVEL >= VERBOSE_TRACE) { \
log_buf_write(LOG_INFO); \
print_message(LOG_INFO, "\n"); \
} \
})
#endif /* LOGGING_H */

View File

@@ -28,6 +28,8 @@
#ifndef KERNEL_SPACE
#include <stdlib.h>
#else
#include "linux/inet.h"
#endif
int process_packet(const uint8_t *raw_payload, size_t raw_payload_len) {
@@ -40,18 +42,20 @@ int process_packet(const uint8_t *raw_payload, size_t raw_payload_len) {
size_t iph_len;
const uint8_t *ip_payload;
size_t ip_payload_len;
const char *bpt;
int transport_proto = -1;
int ipver = netproto_version(raw_payload, raw_payload_len);
int ret;
lgtrace_start();
lgtrace_addp("IPv%d", ipver);
lgtrace_wr("IPv%d ", ipver);
if (ipver == IP4VERSION) {
ret = ip4_payload_split((uint8_t *)raw_payload, raw_payload_len,
(struct iphdr **)&iph, &iph_len,
(uint8_t **)&ip_payload, &ip_payload_len);
(uint8_t **)&ip_payload, &ip_payload_len);
if (ret < 0)
goto accept;
@@ -69,20 +73,83 @@ int process_packet(const uint8_t *raw_payload, size_t raw_payload_len) {
transport_proto = ip6h->ip6_nxt;
} else {
lgtracemsg("Unknown layer 3 protocol version: %d", ipver);
lgtrace("Unknown layer 3 protocol version: %d", ipver);
goto accept;
}
if (LOG_LEVEL >= VERBOSE_TRACE) {
bpt = inet_ntop(
ipver == IP4VERSION ? AF_INET : AF_INET6,
ipver == IP4VERSION ? (void *)(&iph->saddr) :
(void *)(&ip6h->ip6_src),
ylgh_curptr, ylgh_leftbuf);
if (bpt != NULL) {
ret = strnlen(bpt, ylgh_leftbuf);
ylgh_leftbuf -= ret;
ylgh_curptr += ret;
}
lgtrace_wr(" => ");
bpt = inet_ntop(
ipver == IP4VERSION ? AF_INET : AF_INET6,
ipver == IP4VERSION ? (void *)(&iph->daddr) :
(void *)(&ip6h->ip6_dst),
ylgh_curptr, ylgh_leftbuf);
if (bpt != NULL) {
ret = strnlen(bpt, ylgh_leftbuf);
ylgh_leftbuf -= ret;
ylgh_curptr += ret;
}
lgtrace_wr(" ");
const uint8_t *transport_payload = NULL;
size_t transport_payload_len = 0;
int sport = -1, dport = -1;
if (transport_proto == IPPROTO_TCP) {
lgtrace_wr("TCP ");
const struct tcphdr *tcph;
ret = tcp_payload_split((uint8_t *)raw_payload, raw_payload_len,
NULL, NULL,
(struct tcphdr **)&tcph, NULL,
(uint8_t **)&transport_payload, &transport_payload_len);
if (ret == 0) {
sport = ntohs(tcph->source);
dport = ntohs(tcph->dest);
}
} else if (transport_proto == IPPROTO_UDP) {
lgtrace_wr("UDP ");
const struct udphdr *udph = ((const struct udphdr *)ip_payload);
ret = udp_payload_split((uint8_t *)raw_payload, raw_payload_len,
NULL, NULL,
(struct udphdr **)&udph,
(uint8_t **)&transport_payload, &transport_payload_len);
if (ret == 0) {
sport = ntohs(udph->source);
dport = ntohs(udph->dest);
}
}
lgtrace_wr("%d => %d ", sport, dport);
lgtrace_write();
lgtrace_wr("Transport payload: [ ");
for (int i = 0; i < min(16, transport_payload_len); i++) {
lgtrace_wr("%02x ", transport_payload[i]);
}
lgtrace_wr("]");
lgtrace_write();
}
int verdict = PKT_CONTINUE;
if (transport_proto == IPPROTO_TCP)
lgtrace_addp("TCP");
else if (transport_proto == IPPROTO_UDP)
lgtrace_addp("UDP");
ITER_CONFIG_SECTIONS(&config, section) {
lgtrace_addp("Section #%d", CONFIG_SECTION_NUMBER(section));
lgtrace_wr("Section #%d: ", CONFIG_SECTION_NUMBER(section));
switch (transport_proto) {
case IPPROTO_TCP:
@@ -94,10 +161,12 @@ int process_packet(const uint8_t *raw_payload, size_t raw_payload_len) {
}
if (verdict == PKT_CONTINUE) {
lgtrace_addp("continue_flow");
lgtrace_wr("continue_flow");
lgtrace_write();
continue;
}
lgtrace_write();
goto ret_verdict;
}
@@ -108,13 +177,13 @@ ret_verdict:
switch (verdict) {
case PKT_ACCEPT:
lgtrace_addp("accept");
lgtrace_wr("accept");
break;
case PKT_DROP:
lgtrace_addp("drop");
lgtrace_wr("drop");
break;
default:
lgtrace_addp("unknow verdict: %d", verdict);
lgtrace_wr("unknown verdict: %d", verdict);
}
lgtrace_end();
@@ -200,7 +269,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
}
if (vrd.target_sni) {
lgdebugmsg("Target SNI detected: %.*s", vrd.sni_len, vrd.sni_ptr);
lgdebug("Target SNI detected: %.*s", vrd.sni_len, vrd.sni_ptr);
size_t sni_offset = vrd.sni_ptr - data;
size_t target_sni_offset = vrd.target_sni_ptr - data;
@@ -247,7 +316,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
if (dlen > 1480 && config.verbose) {
lgdebugmsg("WARNING! Client Hello packet is too big and may cause issues!");
lgdebug("WARNING! Client Hello packet is too big and may cause issues!");
}
if (section->fake_sni) {
@@ -321,7 +390,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
goto drop_lc;
} else {
lginfo("WARNING: IP fragmentation is supported only for IPv4\n");
lginfo("WARNING: IP fragmentation is supported only for IPv4");
goto default_send;
}
default:
@@ -374,18 +443,6 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk
goto accept;
}
if (dlen > 10 && config.verbose == VERBOSE_TRACE) {
char logging_buf[128];
char *bufpt = logging_buf;
bufpt += sprintf(bufpt, "UDP payload start: [ ");
for (int i = 0; i < 10; i++) {
bufpt += sprintf(bufpt, "%02x ", data[i]);
}
bufpt += sprintf(bufpt, "]");
lgtrace_addp("%s", logging_buf);
}
if (!detect_udp_filtered(section, pkt, pktlen))
goto continue_flow;
@@ -586,6 +643,7 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet
return 0;
} else {
lgtrace_addp("raw send packet of %zu bytes with %zu dvs", pktlen, dvs);
return instance_config.send_raw_packet(
packet, pktlen);
}

View File

@@ -425,8 +425,6 @@ int detect_udp_filtered(const struct section_config_t *section,
(struct udphdr **)&udph,
(uint8_t **)&data, &dlen);
int udp_dport = ntohs(udph->dest);
lgtrace_addp("UDP dport: %d", udp_dport);
if (ret < 0) {
goto skip;
@@ -507,7 +505,7 @@ int detect_udp_filtered(const struct section_config_t *section,
}
if (tlsv.target_sni) {
lgdebugmsg("QUIC target SNI detected: %.*s", tlsv.sni_len, tlsv.sni_ptr);
lgdebug("QUIC target SNI detected: %.*s", tlsv.sni_len, tlsv.sni_ptr);
free(crypto_message);
crypto_message = NULL;
goto approve;

View File

@@ -58,7 +58,7 @@
#define QUIC_0_RTT_TYPE_V2 0b10
#define QUIC_HANDSHAKE_TYPE_V2 0b11
#define QUIC_RETRY_TYPE_V2 0b00
#define quic_convtype_v2(type) (((type) + 1) & 0b11)
#define quic_convtype_v2(type) (((type) + 1) & __extension__ 0b11)
#define QUIC_FRAME_CRYPTO 0x06
#define QUIC_FRAME_PADDING 0x00

View File

@@ -128,7 +128,7 @@ check_domain:
domain_startp,
sne->domain_len)) {
vrd->target_sni = 0;
lgdebugmsg("Excluded SNI: %.*s",
lgdebug("Excluded SNI: %.*s",
vrd->sni_len, vrd->sni_ptr);
}
}

View File

@@ -45,6 +45,7 @@ typedef __s16 int_least16_t; /* integer of >= 16 bits */
#include <stdint.h> // IWYU pragma: export
#include <string.h> // IWYU pragma: export
#include <stdlib.h> // IWYU pragma: export
#include <stdio.h> // IWYU pragma: export
#define _NO_GETRANDOM ((__GLIBC__ <= 2 && __GLIBC_MINOR__ < 25))
@@ -154,12 +155,17 @@ static inline int randint(void) {
int rnd;
#ifdef KERNEL_SPACE
get_random_bytes(&rnd, sizeof(rnd));
get_random_bytes(&rnd, sizeof(rnd));
#else
rnd = random();
rnd = random();
#endif
return rnd;
}
#ifdef KERNEL_SPACE
#define socklen_t size_t
#endif
const char *inet_ntop(int af, const void * a0, char * s, socklen_t l);
#endif /* TYPES_H */

View File

@@ -506,7 +506,7 @@ int tcp_frag(const uint8_t *pkt, size_t buflen, size_t payload_offset,
if (
ntohs(iphdr->frag_off) & IP_MF ||
ntohs(iphdr->frag_off) & IP_OFFMASK) {
lgdebugmsg("tcp_frag: ip4: frag value: %d",
lgdebug("tcp_frag: ip4: frag value: %d",
ntohs(iphdr->frag_off));
lgerror(-EINVAL, "tcp_frag: ip4: ip fragmentation is set");
return -EINVAL;
@@ -634,13 +634,13 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen
if (strategy.strategy == FAKE_STRAT_RAND_SEQ) {
lgtrace("fake seq: %u -> ", ntohl(tcph->seq));
lgtrace_wr("fake seq: %u -> ", ntohl(tcph->seq));
tcph->seq = htonl(ntohl(tcph->seq) - (strategy.randseq_offset + dlen));
lgtrace_addp("%u", ntohl(tcph->seq));
} else if (strategy.strategy == FAKE_STRAT_PAST_SEQ) {
lgtrace("fake seq: %u -> ", ntohl(tcph->seq));
lgtrace_wr("fake seq: %u -> ", ntohl(tcph->seq));
tcph->seq = htonl(ntohl(tcph->seq) - dlen);
lgtrace_addp("%u", ntohl(tcph->seq));

View File

@@ -109,13 +109,13 @@ static int open_raw_socket(void) {
int mark = config.mark;
if (setsockopt(rawsocket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
{
lgerror(-errno, "setsockopt(SO_MARK, %d) failed\n", mark);
lgerror(-errno, "setsockopt(SO_MARK, %d) failed", mark);
return -1;
}
int mst = pthread_mutex_init(&rawsocket_lock, NULL);
if (mst) {
lgerror(-errno, "Mutex err: %d\n", mst);
lgerror(-errno, "Mutex err: %d", mst);
close(rawsocket);
errno = mst;
@@ -161,13 +161,13 @@ static int open_raw6_socket(void) {
int mark = config.mark;
if (setsockopt(raw6socket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
{
lgerror(-errno, "setsockopt(SO_MARK, %d) failed\n", mark);
lgerror(-errno, "setsockopt(SO_MARK, %d) failed", mark);
return -1;
}
int mst = pthread_mutex_init(&raw6socket_lock, NULL);
if (mst) {
lgerror(-errno, "Mutex err: %d\n", mst);
lgerror(-errno, "Mutex err: %d", mst);
close(raw6socket);
return -1;
@@ -274,7 +274,7 @@ static int send_raw_socket(const uint8_t *pkt, size_t pktlen) {
int ret;
if (pktlen > AVAILABLE_MTU) {
lgtrace("Split packet!\n");
lgtrace("Split packet!");
NETBUF_ALLOC(buff1, MNL_SOCKET_BUFFER_SIZE);
if (!NETBUF_CHECK(buff1)) {
@@ -330,7 +330,7 @@ free_buffs:
} else if (ipvx == IP6VERSION) {
ret = send_raw_ipv6(pkt, pktlen);
} else {
lginfo("proto version %d is unsupported\n", ipvx);
lginfo("proto version %d is unsupported", ipvx);
return -EINVAL;
}
@@ -439,7 +439,7 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) {
packet.payload = mnl_attr_get_payload(attr[NFQA_PAYLOAD]);
if (attr[NFQA_CAP_LEN] != NULL && ntohl(mnl_attr_get_u32(attr[NFQA_CAP_LEN])) != packet.payload_len) {
lgerr("The packet was truncated! Skip!\n");
lgerr("The packet was truncated! Skip!");
return fallback_accept_packet(packet.id, *qdata);
}
@@ -567,7 +567,7 @@ int init_queue(int queue_num) {
.queue_num = queue_num
};
lginfo("Queue %d started\n", qdata.queue_num);
lginfo("Queue %d started", qdata.queue_num);
while (1) {
ret = mnl_socket_recvfrom(nl, buf, BUF_SIZE);
@@ -580,9 +580,9 @@ int init_queue(int queue_num) {
if (ret < 0) {
lgerror(ret, "mnl_cb_run");
if (ret == -EPERM) {
lgerr("Probably another instance of youtubeUnblock with the same queue number is running\n");
lgerr("Probably another instance of youtubeUnblock with the same queue number is running");
} else {
lgerr("Make sure the nfnetlink_queue kernel module is loaded\n");
lgerr("Make sure the nfnetlink_queue kernel module is loaded");
}
goto die;
}
@@ -619,7 +619,7 @@ void *init_queue_wrapper(void *qdconf) {
thres->status = init_queue(qconf->queue_num);
lgerror(thres->status, "Thread %d exited with status %d\n", qconf->i, thres->status);
lgerror(thres->status, "Thread %d exited with status %d", qconf->i, thres->status);
return thres;
}
@@ -670,7 +670,7 @@ int main(int argc, char *argv[]) {
qres = init_queue_wrapper(&tconf);
} else {
lginfo("%d threads wil be used\n", config.threads);
lginfo("%d threads wil be used", config.threads);
struct queue_conf thread_confs[MAX_THREADS];
pthread_t threads[MAX_THREADS];

View File

@@ -34,7 +34,7 @@ export CC CCLD LD CFLAGS LDFLAGS LIBNFNETLINK_CFLAGS LIBNFNETLINK_LIBS LIBMNL_CF
APP:=$(BUILD_DIR)/youtubeUnblock
TEST_APP:=$(BUILD_DIR)/testYoutubeUnblock
SRCS := mangle.c args.c utils.c quic.c tls.c getopt.c quic_crypto.c
SRCS := mangle.c args.c utils.c quic.c tls.c getopt.c quic_crypto.c inet_ntop.c
OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
APP_EXEC := youtubeUnblock.c
APP_OBJ := $(APP_EXEC:%.c=$(BUILD_DIR)/%.o)