aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_api.h5
-rw-r--r--src/include/ndpi_typedefs.h17
-rw-r--r--src/lib/ndpi_main.c56
-rw-r--r--src/lib/protocols/http.c60
-rw-r--r--src/lib/protocols/ookla.c167
-rw-r--r--src/lib/protocols/tls.c25
6 files changed, 178 insertions, 152 deletions
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index d1875b5d8..d3b02a4d5 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -1031,6 +1031,11 @@ extern "C" {
int ndpi_get_opportunistic_tls(struct ndpi_detection_module_struct *ndpi_struct,
u_int16_t proto);
+ int ndpi_set_protocol_aggressiveness(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t proto, u_int32_t value);
+ u_int32_t ndpi_get_protocol_aggressiveness(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t proto);
+
/**
* Find a protocol id associated with a string automata
*
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 6d560ef36..a5b1175bc 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -659,6 +659,14 @@ struct ndpi_lru_cache {
struct ndpi_lru_cache_entry *entries;
};
+
+/* Aggressiveness values */
+
+#define NDPI_AGGRESSIVENESS_DISABLED 0x00 /* For all protocols */
+
+/* Ookla */
+#define NDPI_AGGRESSIVENESS_OOKLA_TLS 0x01 /* Enable detection over TLS (using ookla cache) */
+
/* ************************************************** */
struct ndpi_flow_tcp_struct {
@@ -920,7 +928,8 @@ typedef enum {
NDPI_CONFIDENCE_DPI_CACHE, /* Classification results based on some LRU cache (i.e. correlation among sessions) */
NDPI_CONFIDENCE_DPI, /* Deep packet inspection */
NDPI_CONFIDENCE_MATCH_BY_IP, /* Classification obtained looking only at the IP addresses */
-
+ NDPI_CONFIDENCE_DPI_AGGRESSIVE, /* Aggressive DPI: it might be a false positive */
+
/*
IMPORTANT
@@ -1229,6 +1238,8 @@ struct ndpi_detection_module_struct {
int opportunistic_tls_pop_enabled;
int opportunistic_tls_ftp_enabled;
+ u_int32_t aggressiveness_ookla;
+
u_int16_t ndpi_to_user_proto_id[NDPI_MAX_NUM_CUSTOM_PROTOCOLS]; /* custom protocolId mapping */
ndpi_proto_defaults_t proto_defaults[NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS];
@@ -1563,6 +1574,10 @@ struct ndpi_flow_struct {
/* NDPI_PROTOCOL_Z3950 */
u_int8_t z3950_stage : 2; // 0-3
+ /* NDPI_PROTOCOL_OOKLA */
+ u_int8_t ookla_stage : 1;
+
+
/* NDPI_PROTOCOL_OPENVPN */
u_int8_t ovpn_session_id[8];
u_int8_t ovpn_counter;
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index f4266d87d..dc5834549 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -198,6 +198,10 @@ extern void ndpi_unset_risk(struct ndpi_detection_module_struct *ndpi_str,
struct ndpi_flow_struct *flow, ndpi_risk_enum r);
extern u_int32_t make_mining_key(struct ndpi_flow_struct *flow);
extern int stun_search_into_zoom_cache(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+extern void ookla_add_to_cache(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
+extern int ookla_search_into_cache(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
/* Forward */
static int addDefaultPort(struct ndpi_detection_module_struct *ndpi_str,
@@ -2932,7 +2936,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
ndpi_str->msteams_cache_num_entries = 1024;
ndpi_str->stun_zoom_cache_num_entries = 1024;
- ndpi_str->ookla_cache_ttl = 0;
+ ndpi_str->ookla_cache_ttl = 120; /* sec */
ndpi_str->bittorrent_cache_ttl = 0;
ndpi_str->zoom_cache_ttl = 0;
ndpi_str->stun_cache_ttl = 0;
@@ -2946,6 +2950,8 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
ndpi_str->opportunistic_tls_pop_enabled = 1;
ndpi_str->opportunistic_tls_ftp_enabled = 1;
+ ndpi_str->aggressiveness_ookla = NDPI_AGGRESSIVENESS_OOKLA_TLS;
+
for(i = 0; i < NUM_CUSTOM_CATEGORIES; i++)
ndpi_snprintf(ndpi_str->custom_category_labels[i], CUSTOM_CATEGORY_LABEL_LEN, "User custom category %u",
(unsigned int) (i + 1));
@@ -6254,6 +6260,13 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
ret.app_protocol = flow->detected_protocol_stack[0];
}
+ /* Does it looks like Ookla? */
+ if(ret.app_protocol == NDPI_PROTOCOL_UNKNOWN &&
+ ntohs(flow->s_port) == 8080 && ookla_search_into_cache(ndpi_str, flow)) {
+ ndpi_set_detected_protocol(ndpi_str, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI_PARTIAL_CACHE);
+ ret.app_protocol = flow->detected_protocol_stack[0];
+ }
+
/* Classification by-port is the last resort */
if(enable_guess && ret.app_protocol == NDPI_PROTOCOL_UNKNOWN) {
@@ -8052,6 +8065,9 @@ const char *ndpi_confidence_get_name(ndpi_confidence_t confidence)
case NDPI_CONFIDENCE_MATCH_BY_IP:
return "Match by IP";
+ case NDPI_CONFIDENCE_DPI_AGGRESSIVE:
+ return "DPI (aggressive)";
+
default:
return NULL;
}
@@ -8572,6 +8588,11 @@ int ndpi_match_hostname_protocol(struct ndpi_detection_module_struct *ndpi_struc
ndpi_set_detected_protocol(ndpi_struct, flow, subproto, master_protocol, NDPI_CONFIDENCE_DPI);
if(!category_depends_on_master(master_protocol))
ndpi_int_change_category(ndpi_struct, flow, ret_match.protocol_category);
+
+ if(subproto == NDPI_PROTOCOL_OOKLA) {
+ ookla_add_to_cache(ndpi_struct, flow);
+ }
+
return(1);
} else
return(0);
@@ -9643,3 +9664,36 @@ int ndpi_get_opportunistic_tls(struct ndpi_detection_module_struct *ndpi_struct,
return -1;
}
}
+
+/* ******************************************************************** */
+
+int ndpi_set_protocol_aggressiveness(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t proto, u_int32_t value)
+{
+ if(!ndpi_struct)
+ return -1;
+
+ switch(proto) {
+ case NDPI_PROTOCOL_OOKLA:
+ ndpi_struct->aggressiveness_ookla = value;
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/* ******************************************************************** */
+
+u_int32_t ndpi_get_protocol_aggressiveness(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t proto)
+{
+ if(!ndpi_struct)
+ return -1;
+
+ switch(proto) {
+ case NDPI_PROTOCOL_OOKLA:
+ return ndpi_struct->aggressiveness_ookla;
+ default:
+ return -1;
+ }
+}
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
index e0f56c4e8..4f139b8d3 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -46,6 +46,9 @@ static const char* binary_file_ext[] = {
NULL
};
+extern void ookla_add_to_cache(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
+
static void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow);
@@ -436,6 +439,7 @@ static void ndpi_http_parse_subprotocol(struct ndpi_detection_module_struct *ndp
|| (strstr(flow->http.url, ":8080/upload?n=0.") != NULL))) {
/* This looks like Ookla speedtest */
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, master_protocol, NDPI_CONFIDENCE_DPI);
+ ookla_add_to_cache(ndpi_struct, flow);
}
}
@@ -1217,30 +1221,6 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
return;
}
- if((packet->payload_packet_len == 3) && memcmp(packet->payload, "HI\n", 3) == 0) {
- /* This looks like Ookla: we don't give up with HTTP yet */
- flow->l4.tcp.http_stage = 1;
- return;
- }
-
- if((packet->payload_packet_len == 40) && (flow->l4.tcp.http_stage == 0)) {
- /*
- -> QR O06L0072-6L91-4O43-857J-K8OO172L6L51
- <- QNUUX 2.5 2017-08-15.1314.4jn12m5
- -> MXFWUXJM 31625365
- */
-
- if((packet->payload[2] == ' ')
- && (packet->payload[11] == '-')
- && (packet->payload[16] == '-')
- && (packet->payload[21] == '-')
- && (packet->payload[26] == '-')
- && (packet->payload[39] == 0x0A)
- )
- flow->l4.tcp.http_stage = 1;
- return;
- }
-
if((packet->payload_packet_len == 23) && (memcmp(packet->payload, "<policy-file-request/>", 23) == 0)) {
/*
<policy-file-request/>
@@ -1251,25 +1231,7 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
*/
ookla_found:
ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_CATEGORY_WEB);
-
- if(ndpi_struct->ookla_cache != NULL) {
- if(packet->iph != NULL) {
- if(packet->tcp->source == htons(8080))
- ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->saddr, 1 /* dummy */, ndpi_get_current_time(flow));
- else
- ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->daddr, 1 /* dummy */, ndpi_get_current_time(flow));
- } else if(packet->iphv6 != NULL) {
- u_int32_t h;
-
- if(packet->tcp->source == htons(8080))
- h = ndpi_quick_hash((unsigned char *)&packet->iphv6->ip6_src, sizeof(packet->iphv6->ip6_src));
- else
- h = ndpi_quick_hash((unsigned char *)&packet->iphv6->ip6_dst, sizeof(packet->iphv6->ip6_dst));
-
- ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, h, 1 /* dummy */, ndpi_get_current_time(flow));
- }
- }
-
+ ookla_add_to_cache(ndpi_struct, flow);
return;
}
@@ -1389,18 +1351,6 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
} else if((flow->l4.tcp.http_stage == 1) || (flow->l4.tcp.http_stage == 2)) {
NDPI_LOG_DBG2(ndpi_struct, "HTTP stage %u: \n", flow->l4.tcp.http_stage);
- if((packet->payload_packet_len == 34) && (flow->l4.tcp.http_stage == 1)) {
- if((packet->payload[5] == ' ') && (packet->payload[9] == ' ')) {
- goto ookla_found;
- }
- }
-
- if((packet->payload_packet_len > 6) && memcmp(packet->payload, "HELLO ", 6) == 0) {
- /* This looks like Ookla */
- goto ookla_found;
- } else
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_OOKLA);
-
/**
At first check, if this is for sure a response packet
(in another direction. If not, if HTTP is detected do nothing now and return,
diff --git a/src/lib/protocols/ookla.c b/src/lib/protocols/ookla.c
index 0da42212c..d7764e630 100644
--- a/src/lib/protocols/ookla.c
+++ b/src/lib/protocols/ookla.c
@@ -23,111 +23,92 @@
#include "ndpi_api.h"
+/* #define DEBUG_OOKLA_LRU */
+
const u_int16_t ookla_port = 8080;
/* ************************************************************* */
-static void ndpi_search_ookla(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) {
- struct ndpi_packet_struct* packet = &ndpi_struct->packet;
- u_int32_t addr = 0;
- u_int16_t sport, dport;
-
- NDPI_LOG_DBG(ndpi_struct, "Ookla detection\n");
-
- if(packet->tcp)
- sport = ntohs(packet->tcp->source), dport = htons(packet->tcp->dest);
+static u_int32_t get_ookla_key(struct ndpi_flow_struct *flow)
+{
+ if(flow->is_ipv6)
+ return ndpi_quick_hash(flow->c_address.v6, 16);
else
- sport = ntohs(packet->udp->source), dport = htons(packet->udp->dest);
+ return ntohl(flow->c_address.v4);
+}
- if((sport != ookla_port) && (dport != ookla_port)) {
-#ifdef OOKLA_DEBUG
- printf("=>>>>>>>> [OOKLA IPv6] Skipping flow [%u -> %u]\n", sport, dport);
-#endif
- goto ookla_exclude;
- }
-
- if(packet->iphv6 != NULL) {
- if((dport == ookla_port) && (packet->payload_packet_len >= 3)) {
- u_int32_t h;
-
- if((packet->payload_packet_len == 3)
- && (packet->payload[0] == 0x48) /* HI\n */
- && (packet->payload[1] == 0x49)
- && (packet->payload[2] == 0x0A)) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
-
- if(ndpi_struct->ookla_cache != NULL) {
- /* In order to avoid creating an IPv6 LRU we hash the IPv6 address */
- h = ndpi_quick_hash((unsigned char *)&packet->iphv6->ip6_dst, sizeof(packet->iphv6->ip6_dst));
-
-#ifdef OOKLA_DEBUG
- printf("=>>>>>>>> [OOKLA IPv6] Adding %u\n", h);
-#endif
- ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, h, 1 /* dummy */, ndpi_get_current_time(flow));
- }
- return;
- } else {
- if(sport == ookla_port)
- h = ndpi_quick_hash((unsigned char *)&packet->iphv6->ip6_src, sizeof(packet->iphv6->ip6_src));
- else
- h = ndpi_quick_hash((unsigned char *)&packet->iphv6->ip6_dst, sizeof(packet->iphv6->ip6_dst));
-
- if(ndpi_struct->ookla_cache != NULL) {
- u_int16_t dummy;
-
-#ifdef OOKLA_DEBUG
- printf("=>>>>>>>> [OOKLA IPv6] Searching %u\n", h);
-#endif
-
- if(ndpi_lru_find_cache(ndpi_struct->ookla_cache, h, &dummy, 0 /* Don't remove it as it can be used for other connections */,
- ndpi_get_current_time(flow))) {
- NDPI_LOG_INFO(ndpi_struct, "found ookla tcp connection\n");
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI_CACHE);
-#ifdef OOKLA_DEBUG
- printf("=>>>>> Found %u\n", h);
-#endif
- return;
- } else {
-#ifdef OOKLA_DEBUG
- printf("=>>>>> NOT Found %u\n", h);
-#endif
- }
- }
- }
- } else {
+/* ************************************************************* */
- goto ookla_exclude;
- }
- } else {
- if(sport == ookla_port)
- addr = packet->iph->saddr;
- else
- addr = packet->iph->daddr;
-
-#ifdef OOKLA_DEBUG
- printf("=>>>>>>>> [OOKLA IPv4] Searching %u\n", addr);
-#endif
-
- if(ndpi_struct->ookla_cache != NULL) {
- u_int16_t dummy;
-
- if(ndpi_lru_find_cache(ndpi_struct->ookla_cache, addr, &dummy, 0 /* Don't remove it as it can be used for other connections */,
- ndpi_get_current_time(flow))) {
- NDPI_LOG_INFO(ndpi_struct, "found ookla tcp connection\n");
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI_CACHE);
-#ifdef OOKLA_DEBUG
- printf("=>>>>> Found %u\n", addr);
+int ookla_search_into_cache(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ u_int32_t key;
+ u_int16_t dummy;
+
+ if(ndpi_struct->ookla_cache) {
+ key = get_ookla_key(flow);
+#ifdef DEBUG_OOKLA_LRU
+ printf("[LRU OOKLA] Search %u\n", key);
#endif
- return;
- } else {
-#ifdef OOKLA_DEBUG
- printf("=>>>>> NOT Found %u\n", addr);
+
+ if(ndpi_lru_find_cache(ndpi_struct->ookla_cache, key,
+ &dummy, 0 /* Don't remove it as it can be used for other connections */,
+ ndpi_get_current_time(flow))) {
+#ifdef DEBUG_OOKLA_LRU
+ printf("[LRU OOKLA] Found\n");
#endif
- }
+ return 1;
}
}
+ return 0;
+}
+
+/* ************************************************************* */
+
+void ookla_add_to_cache(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ u_int32_t key;
+
+ if(ndpi_struct->ookla_cache) {
+ key = get_ookla_key(flow);
+#ifdef DEBUG_OOKLA_LRU
+ printf("[LRU OOKLA] ADDING %u\n", key);
+#endif
+ ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, key, 1 /* dummy */,
+ ndpi_get_current_time(flow));
+ }
+
+}
+
+/* ************************************************************* */
+
+void ndpi_search_ookla(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) {
+ struct ndpi_packet_struct *packet = &ndpi_struct->packet;
+
+ NDPI_LOG_DBG(ndpi_struct, "Ookla detection\n");
+
+ if(ntohs(flow->s_port) != ookla_port && ntohs(flow->c_port) != ookla_port) {
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ return;
+ }
+
+ if(flow->packet_counter == 1 &&
+ packet->payload_packet_len >= NDPI_STATICSTRING_LEN("HI") &&
+ memcmp(packet->payload, "HI", NDPI_STATICSTRING_LEN("HI")) == 0) {
+ flow->ookla_stage = 1;
+ return;
+ }
+ if(flow->packet_counter == 2 &&
+ flow->ookla_stage == 1 &&
+ packet->payload_packet_len >= NDPI_STATICSTRING_LEN("HELLO") &&
+ memcmp(packet->payload, "HELLO", NDPI_STATICSTRING_LEN("HELLO")) == 0) {
+ NDPI_LOG_INFO(ndpi_struct, "found ookla (Hi + Hello)\n");
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
+ ookla_add_to_cache(ndpi_struct, flow);
+ return;
+ }
- ookla_exclude:
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
}
diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c
index 8e3fbedb8..58b19d0d5 100644
--- a/src/lib/protocols/tls.c
+++ b/src/lib/protocols/tls.c
@@ -33,6 +33,8 @@ extern int processClientServerHello(struct ndpi_detection_module_struct *ndpi_st
extern int http_process_user_agent(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
const u_int8_t *ua_ptr, u_int16_t ua_ptr_len);
+extern int ookla_search_into_cache(struct ndpi_detection_module_struct* ndpi_struct,
+ struct ndpi_flow_struct* flow);
/* QUIC/GQUIC stuff */
extern int quic_len(const uint8_t *buf, uint64_t *value);
extern int quic_len_buffer_still_required(uint8_t value);
@@ -1153,8 +1155,27 @@ static int ndpi_search_tls_tcp(struct ndpi_detection_module_struct *ndpi_struct,
#ifdef DEBUG_TLS_BLOCKS
printf("*** [TLS Block] No more blocks\n");
#endif
- flow->extra_packets_func = NULL;
- return(0); /* That's all */
+ /* An ookla flow? */
+ if((ndpi_struct->aggressiveness_ookla & NDPI_AGGRESSIVENESS_OOKLA_TLS) && /* Feature enabled */
+ (!something_went_wrong &&
+ flow->tls_quic.certificate_processed == 1 &&
+ flow->protos.tls_quic.hello_processed == 1) && /* TLS handshake found without errors */
+ flow->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS && /* No IMAPS/FTPS/... */
+ flow->detected_protocol_stack[1] == NDPI_PROTOCOL_UNKNOWN && /* No sub-classification */
+ ntohs(flow->s_port) == 8080 && /* Ookla port */
+ ookla_search_into_cache(ndpi_struct, flow)) {
+ NDPI_LOG_INFO(ndpi_struct, "found ookla (cache over TLS)\n");
+ /* Even if a LRU cache is involved, NDPI_CONFIDENCE_DPI_AGGRESSIVE seems more
+ suited than NDPI_CONFIDENCE_DPI_CACHE */
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_TLS, NDPI_CONFIDENCE_DPI_AGGRESSIVE);
+ /* TLS over port 8080 usually triggers that risk; clear it */
+ ndpi_unset_risk(ndpi_struct, flow, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
+ flow->extra_packets_func = NULL;
+ return(0); /* That's all */
+ } else {
+ flow->extra_packets_func = NULL;
+ return(0); /* That's all */
+ }
} else
return(1);
}