diff options
author | Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> | 2024-04-08 10:24:51 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-08 10:24:51 +0200 |
commit | 1b3ef7d7b2dde9d58cb217d3d7fb6b14d6281153 (patch) | |
tree | 868ce2beb4ba9dbfbe40dd05c9a1b200e367439c /src | |
parent | f5905a62c7fc1922d0b49e9399d56e8cfee69516 (diff) |
STUN: improve extraction of Mapped-Address metadata (#2370)
Enable parsing of Mapped-Address attribute for all STUN flows: that
means that STUN classification might require more packets.
Add a configuration knob to enable/disable this feature.
Note that we can have (any) STUN metadata also for flows *not*
classified as STUN (because of DTLS).
Add support for ipv6.
Restore the correct extra dissection logic for Telegram flows.
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_private.h | 1 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 10 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 1 | ||||
-rw-r--r-- | src/lib/protocols/stun.c | 67 |
4 files changed, 55 insertions, 24 deletions
diff --git a/src/include/ndpi_private.h b/src/include/ndpi_private.h index b26803a3c..92afa1d24 100644 --- a/src/include/ndpi_private.h +++ b/src/include/ndpi_private.h @@ -249,6 +249,7 @@ struct ndpi_detection_module_config_struct { int stun_opportunistic_tls_enabled; int stun_max_packets_extra_dissection; + int stun_mapped_address_enabled; int dns_subclassification_enabled; int dns_parse_response_enabled; diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 58c9d7df5..4f1935776 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1287,8 +1287,12 @@ struct ndpi_flow_struct { struct { u_int8_t maybe_dtls : 1, is_turn : 1, pad : 6; struct { - u_int32_t ipv4; + union { + u_int32_t v4; + u_int8_t v6[16]; + } address; /* Network-order */ u_int16_t port; + u_int16_t is_ipv6: 1, _pad: 15; } mapped_address; } stun; @@ -1513,8 +1517,8 @@ struct ndpi_flow_struct { _Static_assert(sizeof(((struct ndpi_flow_struct *)0)->protos) <= 256, "Size of the struct member protocols increased to more than 256 bytes, " "please check if this change is necessary."); -_Static_assert(sizeof(struct ndpi_flow_struct) <= 1024, - "Size of the flow struct increased to more than 1024 bytes, " +_Static_assert(sizeof(struct ndpi_flow_struct) <= 1032, + "Size of the flow struct increased to more than 1032 bytes, " "please check if this change is necessary."); #endif #endif diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index e0150fe6c..c2583accc 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -11216,6 +11216,7 @@ static const struct cfg_param { { "stun", "tls_dissection", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(stun_opportunistic_tls_enabled), NULL }, { "stun", "max_packets_extra_dissection", "4", "0", "255", CFG_PARAM_INT, __OFF(stun_max_packets_extra_dissection), NULL }, + { "stun", "metadata.attribute.mapped_address", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(stun_mapped_address_enabled), NULL }, { "dns", "subclassification", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(dns_subclassification_enabled), NULL }, { "dns", "process_response", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(dns_parse_response_enabled), NULL }, diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c index 4e77cc532..cb0b3f001 100644 --- a/src/lib/protocols/stun.c +++ b/src/lib/protocols/stun.c @@ -402,9 +402,7 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, case 0x4007: /* These are the only messages apparently whatsapp voice can use */ *app_proto = NDPI_PROTOCOL_WHATSAPP_CALL; - flow->max_extra_packets_to_check = ndpi_struct->cfg.stun_max_packets_extra_dissection; - flow->extra_packets_func = stun_search_again; - return 1; + break; case 0x0014: /* Realm */ if(flow->host_server_name[0] == '\0') { @@ -442,7 +440,7 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, case 0x8070: /* MS Implementation Version */ case 0x8055: /* MS Service Quality */ *app_proto = NDPI_PROTOCOL_SKYPE_TEAMS_CALL; - return 1; + break; case 0xFF03: *app_proto = NDPI_PROTOCOL_GOOGLE_CALL; @@ -466,7 +464,8 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, break; case 0x0020: /* XOR-MAPPED-ADDRESS */ - if(real_len <= payload_length - off - 12) { + if(ndpi_struct->cfg.stun_mapped_address_enabled && + real_len <= payload_length - off - 12) { u_int8_t protocol_family = payload[off+5]; if(protocol_family == 0x01 /* IPv4 */) { @@ -475,8 +474,22 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t port_xor = (magic_cookie >> 16) & 0xFFFF; flow->stun.mapped_address.port = xored_port ^ port_xor; - flow->stun.mapped_address.ipv4 = xored_ip ^ magic_cookie; - flow->extra_packets_func = NULL; /* We're good now */ + flow->stun.mapped_address.address.v4 = htonl(xored_ip ^ magic_cookie); + flow->stun.mapped_address.is_ipv6 = 0; + } else if(protocol_family == 0x02 /* IPv6 */ && + real_len <= payload_length - off - 24) { + u_int32_t ip[4]; + u_int16_t port; + + port = ntohs(*((u_int16_t *)&payload[off + 6])) ^ (magic_cookie >> 16); + ip[0] = *((u_int32_t *)&payload[off + 8]) ^ htonl(magic_cookie); + ip[1] = *((u_int32_t *)&payload[off + 12]) ^ htonl(transaction_id[0]); + ip[2] = *((u_int32_t *)&payload[off + 16]) ^ htonl(transaction_id[1]); + ip[3] = *((u_int32_t *)&payload[off + 20]) ^ htonl(transaction_id[2]); + + flow->stun.mapped_address.port = port; + memcpy(&flow->stun.mapped_address.address, &ip, 16); + flow->stun.mapped_address.is_ipv6 = 1; } } break; @@ -492,16 +505,25 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, return 1; } -static int keep_extra_dissection(struct ndpi_flow_struct *flow) +static int keep_extra_dissection(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow) { if(!is_subclassification_real(flow)) return 1; - /* Looking for XOR-PEER-ADDRESS metadata; TODO: other protocols? */ - if((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_TELEGRAM_VOIP) - || (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_WHATSAPP_CALL)) + /* See the comment at the end of ndpi_int_stun_add_connection() + where we set the extra dissection */ + + if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_TELEGRAM_VOIP) return 1; - return 0; + + if(ndpi_struct->cfg.stun_mapped_address_enabled && + flow->stun.mapped_address.port) + return 0; + if(!ndpi_struct->cfg.stun_mapped_address_enabled) + return 0; + + return 1; } static u_int32_t __get_master(struct ndpi_flow_struct *flow) { @@ -694,7 +716,7 @@ static int stun_search_again(struct ndpi_detection_module_struct *ndpi_struct, } else { NDPI_LOG_DBG(ndpi_struct, "QUIC range. Unexpected\n"); } - return keep_extra_dissection(flow); + return keep_extra_dissection(ndpi_struct, flow); } /* ************************************************************ */ @@ -822,16 +844,19 @@ static void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *nd /* We want extra dissection for: * sub-classification - * metadata extraction or looking for RTP - The latter is enabled only without sub-classification or for Telegram - (to find all XOR-PEER-ADDRESS attributes) + * metadata extraction (XOR-PEER-ADDRESS/XOR-MAPPED-ADDRESS) or looking for RTP + At the moment: + * it seems ZOOM doens't have any meaningful attributes + * we want XOR-MAPPED-ADDRESS only for Telegram -> we can stop after (the first) + XOR-MAPPED-ADDRESS for all the other sub-protocols */ if(!flow->extra_packets_func) { - if(!is_subclassification_real(flow) || - flow->detected_protocol_stack[0] == NDPI_PROTOCOL_TELEGRAM_VOIP /* Metadata. TODO: other protocols? */) { - NDPI_LOG_DBG(ndpi_struct, "Enabling extra dissection\n"); - flow->max_extra_packets_to_check = ndpi_struct->cfg.stun_max_packets_extra_dissection; - flow->extra_packets_func = stun_search_again; + if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_ZOOM) { + if(keep_extra_dissection(ndpi_struct, flow)) { + NDPI_LOG_DBG(ndpi_struct, "Enabling extra dissection\n"); + flow->max_extra_packets_to_check = ndpi_struct->cfg.stun_max_packets_extra_dissection; + flow->extra_packets_func = stun_search_again; + } } } } |