Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Kbuild
Original file line number Diff line number Diff line change
@@ -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/tls.o src/getopt.o src/inet_ntop.o src/args.o src/trie.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/dpi.o src/mangle.o src/quic.o src/quic_crypto.o src/utils.o src/tls.o src/getopt.o src/inet_ntop.o src/args.o src/trie.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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
USPACE_TARGETS := default all install uninstall dev run_dev
KMAKE_TARGETS := kmake kload kunload kreload xmod xtclean

PKG_VERSION := 1.2.0
PKG_VERSION := 1.3.0
PKG_RELEASE := 1

PKG_FULLVERSION := $(PKG_VERSION)-$(PKG_RELEASE)
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- [Check it](#check-it)
- [Flags](#flags)
- [UDP/QUIC](#udpquic)
- [Cloudflare](#cloudflare)
- [Troubleshooting](#troubleshooting)
- [TV](#tv)
- [Troubleshooting EPERMS (Operation not permitted)](#troubleshooting-eperms-operation-not-permitted)
Expand Down Expand Up @@ -243,6 +244,10 @@ Flags that do not scoped to a specific section, used over all the youtubeUnblock

- `--tls={enabled|disabled}` Set it if you want not to process TLS traffic in current section. May be used if you want to set only UDP-based section. (Here section is a unit between `--fbegin` and `--fend` flags).

- `--tcp-dport-filter=<5,6,200-500>` Filter the TCP destination ports. Defaults to no ports. Specifie the ports you want to be handled by youtubeUnblock. By default, youtubeUnblock will filter only 443 TLS port. This may disabled by `--no-dport-filter`.

- `--tcp-match-connpackets` Use this with `--use-conntrack` set. Instead of matching by TLS domains will match packets by OS conntrack connpackets variable (e. g. number of packets sent while connection is alive (SYN is included in the connpackets counter, but anyways will be skipped by youtubeUnblock). You should not set too high number for matching. I recommend something like 4 or 5. If matching happens, youtubeUnblock will send fake and fragement the packet according to fragmentation and faking settings.

- `--fake-sni={0|1}` This flag enables fake-sni which forces **youtubeUnblock** to send at least three packets instead of one with TLS *ClientHello*: Fake *ClientHello*, 1st part of original *ClientHello*, 2nd part of original *ClientHello*. This flag may be related to some Operation not permitted error messages, so before open an issue refer to [Troubleshooting for EPERMS](#troubleshooting-eperms-operation-not-permitted). Defaults to **1**.

- `--fake-sni-seq-len=<length>` This flag specifies **youtubeUnblock** to build a complicated construction of fake client hello packets. length determines how much fakes will be sent. Defaults to **1**.
Expand Down Expand Up @@ -327,6 +332,29 @@ QUIC is enabled with `--udp-filter-quic` flag. The flag supports two modes: `all

For **other UDP protocols** I recommend to configure UDP support in the separate section from TCP, like `--fbegin --udp-dport-filter=50000-50099 --tls=disabled`. **You should not pass `--quic-drop` here unless you are sure what you are doing**

## Cloudflare

In Russia, Cloudflare technologies takes special care by RKN.
This was caused primarily by ECH technology which allows to easily bypass the TSPU. RKN blocks ECH but alongside with it blocks a lot of harmless network protocols. Currently, the only TLS (and may be HTTP) protocols are allowed on the Cloudflare network. If TSPU could not determine the protocol and Server Name (SNI for TLS), it will drop the connection after 16 KB transferred. This affects not only 443 or 80 ports, but every port on Cloudflare network.

Because of this, ECH and tons of protocols are unavailable. Tons of various custom servers/utilites/games are down, since custom protocols are being blocked.

An example: Hypixel Minecraft server relies on Cloudflare and works up on custom Minecraft protocol on port 25565. TSPU can't determine this protocol, so it blocks the connection after 16 KB transferred, so server does not work.

Note, that the faking here is a key to bypass the TSPU.

An example of the solution:
```sh
sudo ./build/youtubeUnblock --use-conntrack --tls=disabled --tcp-match-connpackets=4 --tcp-dport-filter=25565 --frag-sni-pos=1 --fake-sni=1 --faking-strategy=tcp_check,timestamp
```

Also do not forget to add the iptables rule on the custom port:

```sh
sudo iptables -t mangle -A YOUTUBEUNBLOCK -p tcp --dport 25565 -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:19 -j NFQUEUE --queue-num 537 --queue-bypass
```


## Troubleshooting

Check up [this issue](https://github.com/Waujito/youtubeUnblock/issues/148) for useful configs.
Expand Down
73 changes: 59 additions & 14 deletions src/args.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ static int parse_faking_strategy(char *optarg, int *faking_strategy) {
return 0;
}

static int parse_udp_dport_range(char *str, struct udp_dport_range **udpr, int *udpr_len) {
static int parse_dport_range(char *str, struct dport_range **udpr, int *udpr_len) {
int seclen = 1;
const char *p = str;
while (*p != '\0') {
Expand All @@ -225,14 +225,14 @@ static int parse_udp_dport_range(char *str, struct udp_dport_range **udpr, int *
}

#ifdef KERNEL_SPACE
struct udp_dport_range *udp_dport_ranges = kmalloc(
seclen * sizeof(struct udp_dport_range), GFP_KERNEL);
struct dport_range *dport_ranges = kmalloc(
seclen * sizeof(struct dport_range), GFP_KERNEL);

#else
struct udp_dport_range *udp_dport_ranges = malloc(
seclen * sizeof(struct udp_dport_range));
struct dport_range *dport_ranges = malloc(
seclen * sizeof(struct dport_range));
#endif
if (udp_dport_ranges == NULL) {
if (dport_ranges == NULL) {
return -ENOMEM;
}

Expand Down Expand Up @@ -279,7 +279,7 @@ static int parse_udp_dport_range(char *str, struct udp_dport_range **udpr, int *
)
goto erret;

udp_dport_ranges[i] = (struct udp_dport_range){
dport_ranges[i] = (struct dport_range){
.start = num1,
.end = num2
};
Expand All @@ -297,15 +297,15 @@ static int parse_udp_dport_range(char *str, struct udp_dport_range **udpr, int *
}

if (i == 0) {
free(udp_dport_ranges);
free(dport_ranges);
}

*udpr = udp_dport_ranges;
*udpr = dport_ranges;
*udpr_len = i;
return 0;

erret:
free(udp_dport_ranges);
free(dport_ranges);

return -1;
}
Expand Down Expand Up @@ -350,6 +350,7 @@ enum {
OPT_EXCLUDE_DOMAINS,
OPT_SNI_DOMAINS_FILE,
OPT_EXCLUDE_DOMAINS_FILE,
OPT_TCP_DPORT_FILTER,
OPT_FAKE_SNI,
OPT_FAKING_TTL,
OPT_FAKING_STRATEGY,
Expand Down Expand Up @@ -397,6 +398,7 @@ enum {
OPT_HELP,
OPT_VERSION,
OPT_CONNBYTES_LIMIT,
OPT_TCP_M_CONNPKTS,
};

static struct option long_opt[] = {
Expand All @@ -410,6 +412,7 @@ static struct option long_opt[] = {
{"synfake", 1, 0, OPT_SYNFAKE},
{"synfake-len", 1, 0, OPT_SYNFAKE_LEN},
{"tls", 1, 0, OPT_TLS_ENABLED},
{"tcp-dport-filter", 1, 0, OPT_TCP_DPORT_FILTER},
{"fake-sni-seq-len", 1, 0, OPT_FAKE_SNI_SEQ_LEN},
{"fake-sni-type", 1, 0, OPT_FAKE_SNI_TYPE},
{"fake-custom-payload", 1, 0, OPT_FAKE_CUSTOM_PAYLOAD},
Expand All @@ -435,6 +438,7 @@ static struct option long_opt[] = {
{"udp-stun-filter", 0, 0, OPT_UDP_STUN_FILTER},
{"udp-filter-quic", 1, 0, OPT_UDP_FILTER_QUIC},
{"no-dport-filter", 0, 0, OPT_NO_DPORT_FILTER},
{"tcp-match-connpackets", 1, 0, OPT_TCP_M_CONNPKTS},
{"threads", 1, 0, OPT_THREADS},
{"silent", 0, 0, OPT_SILENT},
{"trace", 0, 0, OPT_TRACE},
Expand Down Expand Up @@ -476,6 +480,7 @@ void print_usage(const char *argv0) {
printf("\t--sni-domains-file=<file contains comma or new-line separated list>\n");
printf("\t--exclude-domains-file=<file contains comma or new-line separated list>\n");
printf("\t--tls={enabled|disabled}\n");
printf("\t--tcp-dport-filter=<5,6,200-500>\n");
printf("\t--fake-sni={1|0}\n");
printf("\t--fake-sni-seq-len=<length>\n");
printf("\t--fake-sni-type={default|random|custom}\n");
Expand Down Expand Up @@ -507,6 +512,7 @@ void print_usage(const char *argv0) {
printf("\t--threads=<threads number>\n");
printf("\t--packet-mark=<mark>\n");
printf("\t--connbytes-limit=<pkts>\n");
printf("\t--tcp-match-connpackets=<n of packets in connection>\n");
printf("\t--silent\n");
printf("\t--trace\n");
printf("\t--instaflush\n");
Expand Down Expand Up @@ -788,6 +794,23 @@ int yparse_args(struct config_t *config, int argc, char *argv[]) {

sect_config->frag_sni_pos = num;
break;
case OPT_TCP_DPORT_FILTER:
{
SFREE(sect_config->tcp_dport_range);
if (parse_dport_range(optarg, &sect_config->tcp_dport_range, &sect_config->tcp_dport_range_len) < 0) {
goto invalid_opt;
}
break;
}
case OPT_TCP_M_CONNPKTS:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0) {
goto invalid_opt;
}

sect_config->tcp_match_connpkts = num;
break;

case OPT_FAKING_STRATEGY:
if (parse_faking_strategy(
optarg, &sect_config->faking_strategy) < 0) {
Expand Down Expand Up @@ -982,7 +1005,7 @@ int yparse_args(struct config_t *config, int argc, char *argv[]) {
case OPT_UDP_DPORT_FILTER:
{
SFREE(sect_config->udp_dport_range);
if (parse_udp_dport_range(optarg, &sect_config->udp_dport_range, &sect_config->udp_dport_range_len) < 0) {
if (parse_dport_range(optarg, &sect_config->udp_dport_range, &sect_config->udp_dport_range_len) < 0) {
goto invalid_opt;
}
break;
Expand Down Expand Up @@ -1055,8 +1078,26 @@ static size_t print_config_section(const struct section_config_t *section, char
size_t buf_sz = buffer_size;
size_t sz;

if (section->tls_enabled) {
print_cnf_buf("--tls=enabled");
if (section->tcp_dport_range_len != 0) {
print_cnf_raw("--tcp-dport-filter=");
for (int i = 0; i < section->tcp_dport_range_len; i++) {
struct dport_range range = section->tcp_dport_range[i];
print_cnf_raw("%d-%d,", range.start, range.end);
}
print_cnf_raw(" ");

}

if (section->tcp_match_connpkts) {
print_cnf_buf("--tcp-match-connpackets=%d",
section->tcp_match_connpkts);
}

if (section->tls_enabled || section->tcp_dport_range_len != 0) {
if (section->tls_enabled) {
print_cnf_buf("--tls=enabled");
}


switch(section->fragmentation_strategy) {
case FRAG_STRAT_IP:
Expand Down Expand Up @@ -1205,7 +1246,7 @@ static size_t print_config_section(const struct section_config_t *section, char

print_cnf_raw("--udp-dport-filter=");
for (int i = 0; i < section->udp_dport_range_len; i++) {
struct udp_dport_range range = section->udp_dport_range[i];
struct dport_range range = section->udp_dport_range[i];
print_cnf_raw("%d-%d,", range.start, range.end);
}
print_cnf_raw(" ");
Expand Down Expand Up @@ -1364,6 +1405,10 @@ void free_config_section(struct section_config_t *section) {
SFREE(section->udp_dport_range);
}

if (section->tcp_dport_range_len != 0) {
SFREE(section->tcp_dport_range);
}

free_sni_domains(&section->sni_domains);
free_sni_domains(&section->exclude_sni_domains);

Expand Down
12 changes: 10 additions & 2 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct logging_config_t {
};
extern struct logging_config_t logging_conf;

struct udp_dport_range {
struct dport_range {
uint16_t start;
uint16_t end;
};
Expand All @@ -64,6 +64,11 @@ struct section_config_t {

int tls_enabled;

struct dport_range *tcp_dport_range;
int tcp_dport_range_len;

int tcp_match_connpkts;

int fragmentation_strategy;
int frag_sni_reverse;
int frag_sni_faked;
Expand Down Expand Up @@ -106,7 +111,7 @@ struct section_config_t {
unsigned int udp_fake_len;
int udp_faking_strategy;

struct udp_dport_range *udp_dport_range;
struct dport_range *udp_dport_range;
int udp_dport_range_len;
int udp_stun_filter;
int udp_filter_quic;
Expand Down Expand Up @@ -238,6 +243,9 @@ enum {
.sni_domains = {0}, \
.exclude_sni_domains = {0}, \
.all_domains = 0, \
.tcp_dport_range = NULL, \
.tcp_dport_range_len = 0, \
.tcp_match_connpkts = 0, \
.tls_enabled = 1, \
.frag_sni_reverse = 1, \
.frag_sni_faked = 0, \
Expand Down
Loading