aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_typedefs.h19
-rw-r--r--src/lib/Makefile.in6
-rw-r--r--src/lib/ndpi_main.c2
-rw-r--r--src/lib/ndpi_utils.c39
-rw-r--r--src/lib/protocols/stun.c146
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) {