diff options
author | Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> | 2021-11-24 10:46:48 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-24 10:46:48 +0100 |
commit | a8ffcd8bb0273d59600c6310a80b81206096c113 (patch) | |
tree | 2a62911824363509ea5e7c69afa189e98556e495 /src/lib/protocols/dns.c | |
parent | fd02e1b3043eecc5711eb8254aadaa3f43ca7503 (diff) |
Rework how hostname/SNI info is saved (#1330)
Looking at `struct ndpi_flow_struct` the two bigger fields are
`host_server_name[240]` (mainly for HTTP hostnames and DNS domains) and
`protos.tls_quic.client_requested_server_name[256]`
(for TLS/QUIC SNIs).
This commit aims to reduce `struct ndpi_flow_struct` size, according to
two simple observations:
1) maximum one of these two fields is used for each flow. So it seems safe
to merge them;
2) even if hostnames/SNIs might be very long, in practice they are rarely
longer than a fews tens of bytes. So, using a (single) large buffer is a
waste of memory for all kinds of flows. If we need to truncate the name,
we keep the *last* characters, easing domain matching.
Analyzing some real traffic, it seems safe to assume that the vast
majority of hostnames/SNIs is shorter than 80 bytes.
Hostnames/SNIs are always converted to lowercase.
Attention was given so as to be sure that unit-tests outputs are not
affected by this change.
Because of a bug, TLS/QUIC SNI were always truncated to 64 bytes (the
*first* 64 ones): as a consequence, there were some "Suspicious DGA
domain name" and "TLS Certificate Mismatch" false positives.
Diffstat (limited to 'src/lib/protocols/dns.c')
-rw-r--r-- | src/lib/protocols/dns.c | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index 98c6bf142..eb5af5a34 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -368,6 +368,7 @@ static void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, st int invalid = search_valid_dns(ndpi_struct, flow, &dns_header, payload_offset, &is_query); ndpi_protocol ret; u_int num_queries, idx; + char _hostname[256]; ret.master_protocol = NDPI_PROTOCOL_UNKNOWN; ret.app_protocol = (d_port == LLMNR_PORT) ? NDPI_PROTOCOL_LLMNR : ((d_port == MDNS_PORT) ? NDPI_PROTOCOL_MDNS : NDPI_PROTOCOL_DNS); @@ -378,7 +379,6 @@ static void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, st } /* extract host name server */ - max_len = sizeof(flow->host_server_name)-1; off = sizeof(struct ndpi_dns_packet_header) + payload_offset; /* Before continuing let's dissect the following queries to see if they are valid */ @@ -434,6 +434,7 @@ static void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, st } /* for */ u_int8_t hostname_is_valid = 1; + max_len = sizeof(_hostname)-1; while((j < max_len) && (off < packet->payload_packet_len) && (packet->payload[off] != '\0')) { uint8_t c, cl = packet->payload[off++]; @@ -443,40 +444,43 @@ static void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, st break; } - if(j && (j < max_len)) flow->host_server_name[j++] = '.'; - - while((j < max_len) && (cl != 0)) { - u_int32_t shift; - - c = packet->payload[off++]; - shift = ((u_int32_t) 1) << (c & 0x1f); - if ((dns_validchar[c >> 5] & shift)) { - flow->host_server_name[j++] = tolower(c); - } else { - if (isprint(c) == 0) { - hostname_is_valid = 0; - flow->host_server_name[j++] = '?'; - } else { - flow->host_server_name[j++] = '_'; - } - } - cl--; - } + if(j && (j < max_len)) _hostname[j++] = '.'; + + while((j < max_len) && (cl != 0)) { + u_int32_t shift; + + c = packet->payload[off++]; + shift = ((u_int32_t) 1) << (c & 0x1f); + if((dns_validchar[c >> 5] & shift)) { + _hostname[j++] = tolower(c); + } else { + if (isprint(c) == 0) { + hostname_is_valid = 0; + _hostname[j++] = '?'; + } else { + _hostname[j++] = '_'; + } + } + cl--; + } } + + _hostname[j] = '\0'; + + ndpi_hostname_sni_set(flow, (const u_int8_t *)_hostname, j); + if (hostname_is_valid == 0) { ndpi_set_risk(ndpi_struct, flow, NDPI_INVALID_CHARACTERS); } - flow->host_server_name[j] = '\0'; - if(j > 0) { ndpi_protocol_match_result ret_match; - ndpi_check_dga_name(ndpi_struct, flow, (char*)flow->host_server_name, 1); + ndpi_check_dga_name(ndpi_struct, flow, flow->host_server_name, 1); ret.app_protocol = ndpi_match_host_subprotocol(ndpi_struct, flow, - (char *)flow->host_server_name, - strlen((const char*)flow->host_server_name), + flow->host_server_name, + strlen(flow->host_server_name), &ret_match, NDPI_PROTOCOL_DNS); |