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..bb35f61 100644 --- a/src/quic.c +++ b/src/quic.c @@ -426,6 +426,35 @@ 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); + + return (left_len == message_length); +} + int detect_udp_filtered(const struct section_config_t *section, const uint8_t *payload, size_t plen) { const void *iph; @@ -544,6 +573,11 @@ match_port: } } + if (section->udp_stun_filter && is_stun_message(data, dlen)) { + lgtrace_addp("STUN protocol detected"); + goto approve; + } + skip: return 0; approve: