diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_typedefs.h | 19 | ||||
-rw-r--r-- | src/lib/Makefile.in | 6 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 2 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 39 | ||||
-rw-r--r-- | src/lib/protocols/stun.c | 146 |
5 files changed, 175 insertions, 37 deletions
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 9721829dc..2c9a4ccc6 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1178,6 +1178,16 @@ typedef enum { #define MAX_NUM_TLS_SIGNATURE_ALGORITHMS 16 +typedef struct { + 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; +} ndpi_address_port; + struct tls_heuristics { /* TLS heuristics for detecting browsers usage @@ -1286,14 +1296,7 @@ struct ndpi_flow_struct { struct { u_int8_t maybe_dtls : 1, is_turn : 1, pad : 6; - struct { - 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; + ndpi_address_port mapped_address, peer_address, relayed_address, response_origin, other_address; } stun; struct { diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in index 4643136e2..b446ba212 100644 --- a/src/lib/Makefile.in +++ b/src/lib/Makefile.in @@ -15,6 +15,9 @@ PREFIX = @prefix@ libdir = @libdir@ includedir = @includedir@/ndpi ifneq ($(OS),Windows_NT) +OS := $(shell uname) +endif +ifneq ($(OS),Windows_NT) CFLAGS += -fPIC -DPIC endif CFLAGS += -I. -I../include -Ithird_party/include -DNDPI_LIB_COMPILATION @NDPI_CFLAGS@ @GPROF_CFLAGS@ @CUSTOM_NDPI@ @ADDITIONAL_INCS@ @@ -40,9 +43,6 @@ TMP_OBJS := $(OBJECTS) OBJECTS = $(filter-out third_party/src/gcrypt_light.o,$(TMP_OBJS)) endif -ifneq ($(OS),Windows_NT) -OS := $(shell uname) -endif BUILD_MINGW = @BUILD_MINGW@ ifeq ($(OS),Darwin) diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 54276f7b0..53e2efb66 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -11240,7 +11240,7 @@ static const struct cfg_param { { "ftp", "tls_dissection", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(ftp_opportunistic_tls_enabled), NULL }, { "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", "max_packets_extra_dissection", "6", "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 }, diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index b36007b98..7795f59d5 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -1242,6 +1242,24 @@ static void ndpi_tls2json(ndpi_serializer *serializer, struct ndpi_flow_struct * } } +/* ********************************** */ + +static char* print_ndpi_address_port(ndpi_address_port *ap, char *buf, u_int buf_len) { + char ipbuf[INET6_ADDRSTRLEN]; + + if(ap->is_ipv6) { + inet_ntop(AF_INET6, &ap->address, ipbuf, sizeof(ipbuf)); + } else { + inet_ntop(AF_INET, &ap->address, ipbuf, sizeof(ipbuf)); + } + + snprintf(buf, buf_len, "%s:%u", ipbuf, ap->port); + + return(buf); +} + +/* ********************************** */ + /* NOTE: serializer must have been already initialized */ int ndpi_dpi2json(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, @@ -1499,6 +1517,27 @@ int ndpi_dpi2json(struct ndpi_detection_module_struct *ndpi_struct, ndpi_serialize_end_of_block(serializer); break; + case NDPI_PROTOCOL_STUN: + ndpi_serialize_start_of_block(serializer, "stun"); + + if(flow->stun.mapped_address.port) + ndpi_serialize_string_string(serializer, "mapped_address", print_ndpi_address_port(&flow->stun.mapped_address, buf, sizeof(buf))); + + if(flow->stun.peer_address.port) + ndpi_serialize_string_string(serializer, "peer_address", print_ndpi_address_port(&flow->stun.peer_address, buf, sizeof(buf))); + + if(flow->stun.relayed_address.port) + ndpi_serialize_string_string(serializer, "relayed_address", print_ndpi_address_port(&flow->stun.relayed_address, buf, sizeof(buf))); + + if(flow->stun.response_origin.port) + ndpi_serialize_string_string(serializer, "response_origin", print_ndpi_address_port(&flow->stun.response_origin, buf, sizeof(buf))); + + if(flow->stun.other_address.port) + ndpi_serialize_string_string(serializer, "other_address", print_ndpi_address_port(&flow->stun.other_address, buf, sizeof(buf))); + + ndpi_serialize_end_of_block(serializer); + break; + case NDPI_PROTOCOL_TLS: case NDPI_PROTOCOL_DTLS: ndpi_tls2json(serializer, flow); diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c index 7b0cce3cd..37e301a47 100644 --- a/src/lib/protocols/stun.c +++ b/src/lib/protocols/stun.c @@ -352,6 +352,44 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, } break; + case 0x802b: /* RESPONSE-ORIGIN */ + if(ndpi_struct->cfg.stun_mapped_address_enabled && + real_len <= payload_length - off - 5) { + u_int8_t protocol_family = payload[off+5]; + + if(protocol_family == 0x01 /* IPv4 */) { + u_int16_t port = ntohs(*((u_int16_t*)&payload[off+6])); + u_int32_t ip = ntohl(*((u_int32_t*)&payload[off+8])); + + flow->stun.response_origin.port = port; + flow->stun.response_origin.address.v4 = htonl(ip); + flow->stun.response_origin.is_ipv6 = 0; + } else if(protocol_family == 0x02 /* IPv6 */ && + real_len <= payload_length - off - 24) { + /* TODO */ + } + } + break; + + case 0x802c: /* OTHER-ADDRESS */ + if(ndpi_struct->cfg.stun_mapped_address_enabled && + real_len <= payload_length - off - 5) { + u_int8_t protocol_family = payload[off+5]; + + if(protocol_family == 0x01 /* IPv4 */) { + u_int16_t port = ntohs(*((u_int16_t*)&payload[off+6])); + u_int32_t ip = ntohl(*((u_int32_t*)&payload[off+8])); + + flow->stun.other_address.port = port; + flow->stun.other_address.address.v4 = htonl(ip); + flow->stun.other_address.is_ipv6 = 0; + } else if(protocol_family == 0x02 /* IPv6 */ && + real_len <= payload_length - off - 24) { + /* TODO */ + } + } + break; + case 0x0012: /* XOR-PEER-ADDRESS */ if(off + 12 < payload_length ) { u_int16_t port; @@ -359,11 +397,16 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, char buf[128]; #endif - if(len == 8 && payload[off + 5] == 0x01) { /* ipv4 */ + if(len == 8 && payload[off + 5] == 0x01) { + /* ipv4 */ u_int32_t ip; port = ntohs(*((u_int16_t *)&payload[off + 6])) ^ (magic_cookie >> 16); ip = *((u_int32_t *)&payload[off + 8]) ^ htonl(magic_cookie); + + flow->stun.peer_address.port = port; + flow->stun.peer_address.address.v4 = htonl(ip); + flow->stun.peer_address.is_ipv6 = 0; NDPI_LOG_DBG(ndpi_struct, "Peer %s:%d [proto %d]\n", inet_ntop(AF_INET, &ip, buf, sizeof(buf)), port, @@ -380,7 +423,8 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, printf("[LRU] Add peer 0x%llx %d\n", (long long unsigned int)key, flow->detected_protocol_stack[0]); #endif } - } else if(len == 20 && payload[off + 5] == 0x02 && off + 24 < payload_length) { /* ipv6 */ + } else if(len == 20 && payload[off + 5] == 0x02 && off + 24 < payload_length) { + /* ipv6 */ u_int32_t ip[4]; port = ntohs(*((u_int16_t *)&payload[off + 6])) ^ (magic_cookie >> 16); @@ -393,6 +437,9 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, inet_ntop(AF_INET6, &ip, buf, sizeof(buf)), port, flow->detected_protocol_stack[0]); + flow->stun.peer_address.port = port; + memcpy(&flow->stun.peer_address.address, &ip, 16); + if(ndpi_struct->stun_cache && is_subclassification_real(flow)) { u_int64_t key = get_stun_lru_key_raw6((u_int8_t *)ip, port); @@ -425,26 +472,40 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, case 0x0014: /* Realm */ if(flow->host_server_name[0] == '\0') { + int i; + bool valid = true; + ndpi_hostname_sni_set(flow, payload + off + 4, ndpi_min(len, payload_length - off - 4), NDPI_HOSTNAME_NORM_ALL); NDPI_LOG_DBG(ndpi_struct, "Realm [%s]\n", flow->host_server_name); - if(strstr(flow->host_server_name, "google.com") != NULL) { - *app_proto = NDPI_PROTOCOL_GOOGLE_CALL; - return 1; - } else if(strstr(flow->host_server_name, "whispersystems.org") != NULL || - strstr(flow->host_server_name, "signal.org") != NULL) { - *app_proto = NDPI_PROTOCOL_SIGNAL_VOIP; - return 1; - } else if(strstr(flow->host_server_name, "facebook") != NULL) { - *app_proto = NDPI_PROTOCOL_FACEBOOK_VOIP; - return 1; - } else if(strstr(flow->host_server_name, "stripcdn.com") != NULL) { - *app_proto = NDPI_PROTOCOL_ADULT_CONTENT; - return 1; - } else if(strstr(flow->host_server_name, "telegram") != NULL) { - *app_proto = NDPI_PROTOCOL_TELEGRAM_VOIP; - return 1; - } + /* Some Realm contain junk, so let's validate it */ + for(i=0; flow->host_server_name[i] != '\0'; i++) { + if(flow->host_server_name[i] == '?') { + valid = false; + break; + } + } + + if(valid) { + if(strstr(flow->host_server_name, "google.com") != NULL) { + *app_proto = NDPI_PROTOCOL_GOOGLE_CALL; + return 1; + } else if(strstr(flow->host_server_name, "whispersystems.org") != NULL || + strstr(flow->host_server_name, "signal.org") != NULL) { + *app_proto = NDPI_PROTOCOL_SIGNAL_VOIP; + return 1; + } else if(strstr(flow->host_server_name, "facebook") != NULL) { + *app_proto = NDPI_PROTOCOL_FACEBOOK_VOIP; + return 1; + } else if(strstr(flow->host_server_name, "stripcdn.com") != NULL) { + *app_proto = NDPI_PROTOCOL_ADULT_CONTENT; + return 1; + } else if(strstr(flow->host_server_name, "telegram") != NULL) { + *app_proto = NDPI_PROTOCOL_TELEGRAM_VOIP; + return 1; + } + } else + flow->host_server_name[0] = '\0'; } break; @@ -513,6 +574,37 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, } break; + case 0x0016: /* XOR-RELAYED-ADDRESS */ + if(ndpi_struct->cfg.stun_mapped_address_enabled && + real_len <= payload_length - off - 4) { + u_int8_t protocol_family = payload[off+5]; + + if(protocol_family == 0x01 /* IPv4 */) { + u_int16_t xored_port = ntohs(*((u_int16_t*)&payload[off+6])); + u_int32_t xored_ip = ntohl(*((u_int32_t*)&payload[off+8])); + u_int16_t port_xor = (magic_cookie >> 16) & 0xFFFF; + + flow->stun.relayed_address.port = xored_port ^ port_xor; + flow->stun.relayed_address.address.v4 = htonl(xored_ip ^ magic_cookie); + flow->stun.relayed_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.relayed_address.port = port; + memcpy(&flow->stun.relayed_address.address, &ip, 16); + flow->stun.relayed_address.is_ipv6 = 1; + } + } + break; + default: NDPI_LOG_DBG2(ndpi_struct, "Unknown attribute %04X\n", attribute); break; @@ -536,13 +628,17 @@ static int keep_extra_dissection(struct ndpi_detection_module_struct *ndpi_struc if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_TELEGRAM_VOIP) return 1; - if(ndpi_struct->cfg.stun_mapped_address_enabled && - flow->stun.mapped_address.port) + if(ndpi_struct->cfg.stun_mapped_address_enabled == 0) return 0; - if(!ndpi_struct->cfg.stun_mapped_address_enabled) - return 0; - - return 1; + + if(!flow->stun.mapped_address.port + || !flow->stun.peer_address.port + || !flow->stun.relayed_address.port + || !flow->stun.response_origin.port + || !flow->stun.other_address.port) + return 1; + + return 0; } static u_int32_t __get_master(struct ndpi_flow_struct *flow) { |