diff --git a/README.md b/README.md index ef1172b..e577b9e 100644 --- a/README.md +++ b/README.md @@ -293,13 +293,15 @@ Flags that do not scoped to a specific section, used over all the youtubeUnblock - `--udp-fake-len=` Size of udp fake payload (typically payload is zeroes). Defaults to 64. -- `--udp-dport-filter=<5,6,200-500>` Filter the UDP destination ports. Defaults to no ports. Specifie the ports you want to be handled by youtubeUnblock. +- `--udp-dport-filter=<5,6,200-500>` Filter the UDP destination ports. Defaults to no ports. Specifie the ports you want to be handled by youtubeUnblock. Please note, it may conflict with `--quic-drop` since `--quic-drop` setts `--udp-mode` to drop globally. So, make sure to handle it in a different config section. + +- `--udp-stun-filter` Filter all the UDP STUN request packets. Very useful for voice chats. Please note, it may conflict with `--quic-drop` since `--quic-drop` setts `--udp-mode` to drop globally. So, make sure to handle it in a different config section. - `--udp-faking-strategy={checksum|ttl|none}` Faking strategy for udp. `checksum` will fake UDP checksum, `ttl` won't fake but will make UDP content relatively small, `none` is no faking. Defaults to none. - `--udp-filter-quic={disabled|all|parse}` Enables QUIC filtering for UDP handler. If disabled, quic won't be processed, if all, all quic initial packets will be handled. `parse` will decrypt and parse QUIC initial message and match it with `--sni-domains`. Defaults to disabled. -- `--quic-drop` Drop all QUIC packets which goes to youtubeUnblock. Won't affect any other UDP packets. Just an alias for `--udp-filter-quic=all --udp-mode=drop`. +- `--quic-drop` Drop all QUIC packets which goes to youtubeUnblock. Won't affect any other UDP packets. Just an alias for `--udp-filter-quic=all --udp-mode=drop`. Please note, because of `--udp-mode=drop` it may conflict with other filter options. Make sure to use multiple sections. - `--no-dport-filter` By default, youtubeUnblock will filter for TLS and QUIC 443. If you want to disable it, pass this flag. (this does not affect `--udp-dport-filter`) @@ -315,7 +317,7 @@ QUIC is enabled with `--udp-filter-quic` flag. The flag supports two modes: `all **I recommend to use** `--udp-mode=drop --udp-filter-quic=parse`. -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`. +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** ## Troubleshooting diff --git a/src/args.c b/src/args.c index af63e3a..294ec3d 100644 --- a/src/args.c +++ b/src/args.c @@ -333,6 +333,7 @@ enum { OPT_UDP_FAKE_PAYLOAD_LEN, OPT_UDP_FAKING_STRATEGY, OPT_UDP_DPORT_FILTER, + OPT_UDP_STUN_FILTER, OPT_UDP_FILTER_QUIC, OPT_TLS_ENABLED, OPT_CLS, @@ -373,6 +374,7 @@ static struct option long_opt[] = { {"udp-fake-len", 1, 0, OPT_UDP_FAKE_PAYLOAD_LEN}, {"udp-faking-strategy", 1, 0, OPT_UDP_FAKING_STRATEGY}, {"udp-dport-filter", 1, 0, OPT_UDP_DPORT_FILTER}, + {"udp-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}, {"threads", 1, 0, OPT_THREADS}, @@ -440,6 +442,7 @@ void print_usage(const char *argv0) { printf("\t--udp-fake-len=\n"); printf("\t--udp-faking-strategy={checksum|ttl|none}\n"); printf("\t--udp-dport-filter=<5,6,200-500>\n"); + printf("\t--udp-stun-filter\n"); printf("\t--udp-filter-quic={disabled|all|parse}\n"); printf("\t--no-dport-filter\n"); printf("\t--threads=\n"); @@ -927,6 +930,9 @@ int yparse_args(struct config_t *config, int argc, char *argv[]) { } break; } + case OPT_UDP_STUN_FILTER: + sect_config->udp_stun_filter = 1; + break; case OPT_UDP_FILTER_QUIC: if (strcmp(optarg, "disabled") == 0) { sect_config->udp_filter_quic = UDP_FILTER_QUIC_DISABLED; @@ -1099,6 +1105,10 @@ static size_t print_config_section(const struct section_config_t *section, char break; } + if (section->udp_stun_filter) { + print_cnf_buf("--udp-stun-filter"); + } + if (section->udp_dport_range_len != 0) { print_cnf_raw("--udp-dport-filter="); diff --git a/src/config.h b/src/config.h index dee0b03..ab96a47 100644 --- a/src/config.h +++ b/src/config.h @@ -107,6 +107,7 @@ struct section_config_t { struct udp_dport_range *udp_dport_range; int udp_dport_range_len; + int udp_stun_filter; int udp_filter_quic; }; diff --git a/src/quic.c b/src/quic.c index 3112bf5..651a01e 100644 --- a/src/quic.c +++ b/src/quic.c @@ -426,6 +426,48 @@ out: return 0; } +int is_stun_message(const uint8_t *data, size_t dlen) { + size_t left_len = dlen; + const uint8_t *data_ptr = data; + uint16_t message_type; + uint16_t message_length; + + if (left_len < 2 + 2 + 4 + 12) { + return 0; + } + + message_type = *(uint16_t *)data_ptr; + data_ptr += 2; + left_len -= 2; + + message_length = *(uint16_t *)data_ptr; + data_ptr += 2; + left_len -= 2; + + data_ptr += 4; + left_len -= 4; + data_ptr += 12; + left_len -= 12; + + message_type = ntohs(message_type); + message_length = ntohs(message_length); + + if (left_len != message_length) { + return 0; + } + + if ((message_type & (1 << 15)) || (message_type & (1 << 14))) { + return 0; + } + + // Filter request only + if ((message_type & (1 << 4)) || (message_type & (1 << 8))) { + return 0; + } + + return 1; +} + int detect_udp_filtered(const struct section_config_t *section, const uint8_t *payload, size_t plen) { const void *iph; @@ -544,6 +586,11 @@ match_port: } } + if (section->udp_stun_filter && is_stun_message(data, dlen)) { + lgtrace_addp("STUN protocol detected"); + goto approve; + } + skip: return 0; approve: