Show HTTPS, IMAPS and SMTPS instead of TLS

Such names are more user-friendly. Combine ALPN-based detection with
guesses
This commit is contained in:
emanuele-f 2022-04-11 16:51:35 +02:00
parent 00c4d08deb
commit 0845f4896a
5 changed files with 62 additions and 8 deletions

View File

@ -5,7 +5,7 @@ add_library(capture SHARED
capture_vpn.c
capture_root.c
ip_lru.c
ndpi_master_protos.c
ndpi_config.c
crc32.c
blacklist.c
pcap_utils.c

View File

@ -159,7 +159,7 @@ static jobject getConnUpdate(pcapdroid_t *pd, const conn_and_tuple_t *conn) {
if(data->update_type & CONN_UPDATE_INFO) {
jobject info = (*env)->NewStringUTF(env, data->info ? data->info : "");
jobject url = (*env)->NewStringUTF(env, data->url ? data->url : "");
jobject l7proto = (*env)->NewStringUTF(env, pd_get_proto_name(pd, data->l7proto,
jobject l7proto = (*env)->NewStringUTF(env, pd_get_proto_name(pd, data->l7proto, data->alpn,
conn->tuple.ipproto));
int flags = data->encrypted_l7;

View File

@ -20,8 +20,10 @@
#include "ndpi_api.h"
#include "ndpi_protocol_ids.h"
/* ******************************************************* */
// protocols which are not application protocols
void init_protocols_bitmask(ndpi_protocol_bitmask_struct_t *b) {
void init_ndpi_protocols_bitmask(ndpi_protocol_bitmask_struct_t *b) {
NDPI_ZERO(b);
// https://github.com/ntop/nDPI/blob/dev/src/include/ndpi_protocol_ids.h

View File

@ -215,7 +215,7 @@ struct ndpi_detection_module_struct* init_ndpi() {
return(NULL);
// needed by pd_get_proto_name
init_protocols_bitmask(&masterProtos);
init_ndpi_protocols_bitmask(&masterProtos);
#ifndef FUZZING
// enable all the protocols
@ -231,6 +231,7 @@ struct ndpi_detection_module_struct* init_ndpi() {
#endif
ndpi_set_protocol_detection_bitmask2(ndpi, &protocols);
ndpi_finalize_initialization(ndpi);
#ifdef FUZZING
@ -242,12 +243,26 @@ struct ndpi_detection_module_struct* init_ndpi() {
/* ******************************************************* */
const char* pd_get_proto_name(pcapdroid_t *pd, uint16_t proto, int ipproto) {
const char* pd_get_proto_name(pcapdroid_t *pd, uint16_t proto, uint16_t alpn, int ipproto) {
if(proto == NDPI_PROTOCOL_UNKNOWN) {
// Return the L3 protocol
return zdtun_proto2str(ipproto);
}
if(proto == NDPI_PROTOCOL_TLS) {
switch (alpn) {
case NDPI_PROTOCOL_HTTP:
return "HTTPS";
case NDPI_PROTOCOL_MAIL_IMAP:
return "IMAPS";
case NDPI_PROTOCOL_MAIL_SMTP:
return "SMTPS";
default:
// go on
break;
}
}
return ndpi_get_proto_name(pd->ndpi, proto);
}
@ -438,6 +453,23 @@ static void process_ndpi_data(pcapdroid_t *pd, const zdtun_5tuple_t *tuple, pd_c
switch(data->l7proto) {
case NDPI_PROTOCOL_TLS:
// ALPN extension in client hello (https://datatracker.ietf.org/doc/html/rfc7301)
if(!data->alpn && data->ndpi_flow->protos.tls_quic.alpn) {
if(strstr(data->ndpi_flow->protos.tls_quic.alpn, "http/")) {
data->alpn = NDPI_PROTOCOL_HTTP;
data->update_type |= CONN_UPDATE_INFO;
} else if(strstr(data->ndpi_flow->protos.tls_quic.alpn, "imap")) {
data->alpn = NDPI_PROTOCOL_MAIL_IMAP;
data->update_type |= CONN_UPDATE_INFO;
} else if(strstr(data->ndpi_flow->protos.tls_quic.alpn, "stmp")) {
data->alpn = NDPI_PROTOCOL_MAIL_SMTP;
data->update_type |= CONN_UPDATE_INFO;
} else {
log_d("Unknown ALPN: %s", data->ndpi_flow->protos.tls_quic.alpn);
data->alpn = NDPI_PROTOCOL_TLS; // mark to avoid port-based guessing
}
}
/* fallthrough */
case NDPI_PROTOCOL_DNS:
if(data->ndpi_flow->host_server_name[0])
found_info = (char*)data->ndpi_flow->host_server_name;
@ -481,7 +513,8 @@ void pd_giveup_dpi(pcapdroid_t *pd, pd_conn_t *data, const zdtun_5tuple_t *tuple
data->encrypted_l7 = is_encrypted_l7(pd->ndpi, data->l7proto);
}
log_d("nDPI completed[ipver=%d, proto=%d] -> l7proto: %d",
log_d("nDPI completed[pkts=%d, ipver=%d, proto=%d] -> l7proto: %d",
data->sent_pkts + data->rcvd_pkts,
tuple->ipver, tuple->ipproto, data->l7proto);
process_ndpi_data(pd, tuple, data);
@ -639,6 +672,23 @@ static void perform_dpi(pcapdroid_t *pd, pkt_context_t *pctx) {
}
netd_resolve_waiting++;
}
if(!data->ndpi_flow) {
// nDPI detection complete
if((data->l7proto == NDPI_PROTOCOL_TLS) && (!data->alpn)) {
if(ntohs(pctx->tuple->dst_port) == 443)
data->alpn = NDPI_PROTOCOL_HTTP; // assume HTTPS
else if(data->info && !strncmp(data->info, "imap.", 5))
data->alpn = NDPI_PROTOCOL_MAIL_IMAP; // assume IMAPS
else if(data->info && !strncmp(data->info, "smtp.", 5))
data->alpn = NDPI_PROTOCOL_MAIL_SMTP; // assume SMTPS
if(data->alpn) {
data->update_type |= CONN_UPDATE_INFO;
pd_notify_connection_update(pd, pctx->tuple, data);
}
}
}
}
/* ******************************************************* */

View File

@ -73,6 +73,7 @@ typedef struct {
struct ndpi_flow_struct *ndpi_flow;
struct ndpi_id_struct *src_id, *dst_id;
uint16_t l7proto;
uint16_t alpn;
union {
struct {
@ -359,7 +360,7 @@ pd_conn_t* pd_new_connection(pcapdroid_t *pd, const zdtun_5tuple_t *tuple, int u
void pd_purge_connection(pcapdroid_t *pd, pd_conn_t *data);
void pd_notify_connection_update(pcapdroid_t *pd, const zdtun_5tuple_t *tuple, pd_conn_t *data);
void pd_giveup_dpi(pcapdroid_t *pd, pd_conn_t *data, const zdtun_5tuple_t *tuple);
const char* pd_get_proto_name(pcapdroid_t *pd, uint16_t proto, int ipproto);
const char* pd_get_proto_name(pcapdroid_t *pd, uint16_t proto, uint16_t alpn, int ipproto);
// Utility
const char* get_cache_path(pcapdroid_t *pd, const char *subpath);
@ -381,7 +382,8 @@ void getApplicationByUid(pcapdroid_t *pd, jint uid, char *buf, int bufsize);
// Internals
struct pcapdroid_trailer;
void fill_custom_data(struct pcapdroid_trailer *cdata, pcapdroid_t *pd, pd_conn_t *conn);
void init_protocols_bitmask(ndpi_protocol_bitmask_struct_t *b);
void init_ndpi_protocols_bitmask(ndpi_protocol_bitmask_struct_t *b);
void load_ndpi_hosts(struct ndpi_detection_module_struct *ndpi);
uint32_t crc32(u_char *buf, size_t len, uint32_t crc);
#endif //__PCAPDROID_H__