diff --git a/doc/configuration_parameters.rst b/doc/configuration_parameters.rst index f0105e50f26..59f79c2f96a 100644 --- a/doc/configuration_parameters.rst +++ b/doc/configuration_parameters.rst @@ -186,6 +186,8 @@ List of the supported configuration options: | "dns" | "max_packets_extra_dissection" | 5 | 0 | 255 | After a flow has been classified has DNS, nDPI might analyse more packets to look for a sub-classification or for metadata. This parameter set the upper limit | | | | | | | on the number of these packets. Useful if interested in handling big DNS messages (i.e. AXFR transfers) | +--------------+---------------------------------------------------------------+-----------------+------------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| "dns" | "custom_port" | 0 | 0 | 65535 | Enable DNS detection on one additional user-selected TCP or UDP port. The default value 0 disables this option. Standard DNS, mDNS, and LLMNR port behavior is unchanged. | ++--------------+---------------------------------------------------------------+-----------------+------------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | "http" | "process_response" | enable | NULL | NULL | Enable/disable processing of HTTP responses. By default, HTTP flows are usually fully classified after the first request/response pair. If this parameter is | | | | | | | disabled, the flows are fully classified after the first request (or after the first response, if the request is missing); in that case, some flow risks are not | | | | | | | checked and some metadata are not exported | diff --git a/src/include/ndpi_private.h b/src/include/ndpi_private.h index 20208ab575a..63b1e9d42c3 100644 --- a/src/include/ndpi_private.h +++ b/src/include/ndpi_private.h @@ -344,6 +344,7 @@ struct ndpi_detection_module_config_struct { int dns_subclassification_enabled; int dns_parse_response_enabled; int dns_max_packets_extra_dissection; + int dns_custom_port; int http_parse_response_enabled; int http_subclassification_enabled; diff --git a/src/lib/ndpi_config.c b/src/lib/ndpi_config.c index 286824a9cee..0410f1da501 100644 --- a/src/lib/ndpi_config.c +++ b/src/lib/ndpi_config.c @@ -177,6 +177,7 @@ const struct cfg_param cfg_params[] = { { "dns", "subclassification", "disable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(dns_subclassification_enabled), NULL }, { "dns", "process_response", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(dns_parse_response_enabled), NULL }, { "dns", "max_packets_extra_dissection", "5", "0", "255", CFG_PARAM_INT, __OFF(dns_max_packets_extra_dissection), NULL }, + { "dns", "custom_port", "0", "0", "65535", CFG_PARAM_INT, __OFF(dns_custom_port), NULL }, { "http", "process_response", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(http_parse_response_enabled), NULL }, { "http", "subclassification", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(http_subclassification_enabled), NULL }, diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index 38be95b7fd4..7e01ed7a8e0 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -136,13 +136,19 @@ static int isLLMNRMulticastAddress(struct ndpi_packet_struct *const packet) /* *********************************************** */ -static u_int16_t checkDNSSubprotocol(u_int16_t sport, u_int16_t dport) { +static u_int16_t checkDNSSubprotocol(struct ndpi_detection_module_struct *ndpi_struct, + u_int16_t sport, u_int16_t dport) { u_int16_t rc = checkPort(sport); if(rc == 0) - return(checkPort(dport)); - else - return(rc); + rc = checkPort(dport); + + if(rc == 0 && ndpi_struct->cfg.dns_custom_port != 0 && + (sport == (u_int16_t)ndpi_struct->cfg.dns_custom_port || + dport == (u_int16_t)ndpi_struct->cfg.dns_custom_port)) + return NDPI_PROTOCOL_DNS; + + return rc; } /* *********************************************** */ @@ -665,7 +671,7 @@ static int is_valid_dns(struct ndpi_detection_module_struct *ndpi_struct, } } else { if(((dns_header->num_queries > 0 && dns_header->num_queries <= NDPI_MAX_DNS_REQUESTS) || /* Don't assume that num_queries must be zero */ - (checkDNSSubprotocol(ntohs(flow->c_port), ntohs(flow->s_port)) == NDPI_PROTOCOL_MDNS && dns_header->num_queries == 0)) && + (checkDNSSubprotocol(ndpi_struct, ntohs(flow->c_port), ntohs(flow->s_port)) == NDPI_PROTOCOL_MDNS && dns_header->num_queries == 0)) && ((dns_header->num_answers > 0 && dns_header->num_answers <= NDPI_MAX_DNS_REQUESTS) || (dns_header->authority_rrs > 0 && dns_header->authority_rrs <= NDPI_MAX_DNS_REQUESTS) || (dns_header->additional_rrs > 0 && dns_header->additional_rrs <= NDPI_MAX_DNS_REQUESTS) || @@ -943,7 +949,7 @@ static int process_hostname(struct ndpi_detection_module_struct *ndpi_struct, char _hostname[256]; u_int8_t hostname_is_valid; - proto->master_protocol = checkDNSSubprotocol(ntohs(flow->c_port), ntohs(flow->s_port)); + proto->master_protocol = checkDNSSubprotocol(ndpi_struct, ntohs(flow->c_port), ntohs(flow->s_port)); proto->app_protocol = flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN ? flow->detected_protocol_stack[0] : NDPI_PROTOCOL_UNKNOWN; /* We try to get hostname only from "standard" query/answer */ @@ -1195,10 +1201,13 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd d_port = ntohs(packet->tcp->dest); } - /* We are able to detect DNS/MDNS/LLMNR only on standard ports (see #1788) */ + /* DNS on nonstandard ports is opt-in to avoid false positives. */ if(!(s_port == DNS_PORT || d_port == DNS_PORT || s_port == MDNS_PORT || d_port == MDNS_PORT || - d_port == LLMNR_PORT)) { + d_port == LLMNR_PORT || + (ndpi_struct->cfg.dns_custom_port != 0 && + (s_port == (u_int16_t)ndpi_struct->cfg.dns_custom_port || + d_port == (u_int16_t)ndpi_struct->cfg.dns_custom_port)))) { NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow); return; } diff --git a/tests/cfgs/dns_custom_port/config.txt b/tests/cfgs/dns_custom_port/config.txt new file mode 100644 index 00000000000..a2c8572b01a --- /dev/null +++ b/tests/cfgs/dns_custom_port/config.txt @@ -0,0 +1 @@ +--cfg=dns,custom_port,80 diff --git a/tests/cfgs/dns_custom_port/pcap/dns_on_port_80.pcapng b/tests/cfgs/dns_custom_port/pcap/dns_on_port_80.pcapng new file mode 100644 index 00000000000..e42199960e2 Binary files /dev/null and b/tests/cfgs/dns_custom_port/pcap/dns_on_port_80.pcapng differ diff --git a/tests/cfgs/dns_custom_port/result/dns_on_port_80.pcapng.out b/tests/cfgs/dns_custom_port/result/dns_on_port_80.pcapng.out new file mode 100644 index 00000000000..db907103a95 --- /dev/null +++ b/tests/cfgs/dns_custom_port/result/dns_on_port_80.pcapng.out @@ -0,0 +1,8 @@ +DPI Packets (UDP): 2 (2.00 pkts/flow) +Confidence DPI : 1 (flows) + +DNS 2 164 1 + +Acceptable 2 164 1 + +Network 2 164 1