Skip to content

Commit

Permalink
Add enable/disable guessing using client IP/port (#2569)
Browse files Browse the repository at this point in the history
Add configurable options for whether to include client port or client IP
in the flow's protocol guesses. This defaults to include both client
port/IP if the protocol is not guessed with the server IP/port.

This is intended for when flow direction detection is enabled, so we
know that sport = client port, dport = server port.
  • Loading branch information
liwilson1 authored Sep 27, 2024
1 parent 288c1f5 commit cdda369
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 3 deletions.
2 changes: 2 additions & 0 deletions doc/configuration_parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ TODO
| NULL | "packets_limit_per_flow" | 32 | 0 | 255 | The upper limit on the number of packets per flow that will be subject to DPI, after which classification will be considered complete (0 = no limit) |
| NULL | "flow.direction_detection" | enable | NULL | NULL | Enable/disable internal detection of packet direction (client to server or server to client) |
| NULL | "flow.track_payload" | disable | NULL | NULL | Enable/disable tracking/export of flow payload (i.e. L5/7 data): if enabled, the library exports the first 1024 bytes of payload for each flow |
| NULL | "flow.use_client_ip_in_guess" | enable | NULL | NULL | Use client IP in guesses of flow protocol IDs by IP. |
| NULL | "flow.use_client_port_in_guess" | enable | NULL | NULL | Use client port in guesses of flow protocol IDs. |
| NULL | "tcp_ack_payload_heuristic" | disable | NULL | NULL | In some networks, there are some anomalous TCP flows where the smallest ACK packets have some kind of zero padding. It looks like the IP and TCP headers in those frames wrongly consider the 0x00 Ethernet padding bytes as part of the TCP payload. While this kind of packets is perfectly valid per-se, in some conditions they might be treated by the TCP reassembler logic as (partial) overlaps, deceiving the classification engine. This parameter enable/disable an heuristic to detect these packets and to ignore them, allowing correct detection/classification. See #1946 for other details |
| NULL | "fully_encrypted_heuristic" | enable | NULL | NULL | Enable/disable an heuristic to detect fully encrypted sessions, i.e. flows where every bytes of the payload is encrypted in an attempt to “look like nothing”. This heuristic only analyzes the first packet of the flow. See: https://www.usenix.org/system/files/sec23fall-prepub-234-wu-mingshi.pdf |
| NULL | "libgcrypt.init" | 1 | NULL | NULL | Enable/disable initialization of libgcrypt. When using the external libgcrypt (instead of the internal crypto code) the libgcrypt runtime must be initialized. If, for whatever reasons, the application alread does it, nDPI must be told to skip it. Note that, by default, nDPI uses the crypto code and not libgcrypt: in that case this parameter is ignored |
Expand Down
10 changes: 10 additions & 0 deletions fuzz/fuzz_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
snprintf(cfg_value, sizeof(cfg_value), "%d", value);
ndpi_set_config(ndpi_info_mod, NULL, "flow.track_payload", cfg_value);
}
if(fuzzed_data.ConsumeBool()) {
value = fuzzed_data.ConsumeIntegralInRange(0, 1 + 1);
snprintf(cfg_value, sizeof(cfg_value), "%d", value);
ndpi_set_config(ndpi_info_mod, NULL, "flow.use_client_ip_in_guess", cfg_value);
}
if(fuzzed_data.ConsumeBool()) {
value = fuzzed_data.ConsumeIntegralInRange(0, 1 + 1);
snprintf(cfg_value, sizeof(cfg_value), "%d", value);
ndpi_set_config(ndpi_info_mod, NULL, "flow.use_client_port_in_guess", cfg_value);
}
if(fuzzed_data.ConsumeBool()) {
value = fuzzed_data.ConsumeIntegralInRange(0, 1 + 1);
snprintf(cfg_value, sizeof(cfg_value), "%d", value);
Expand Down
2 changes: 2 additions & 0 deletions src/include/ndpi_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ struct ndpi_detection_module_config_struct {
int compute_entropy;
int fpc_enabled;
int guess_ip_before_port;
int use_client_ip_in_guess;
int use_client_port_in_guess;

char filename_config[CFG_MAX_LEN];

Expand Down
11 changes: 8 additions & 3 deletions src/lib/ndpi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4394,6 +4394,8 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) {
static default_ports_tree_node_t *ndpi_get_guessed_protocol_id(struct ndpi_detection_module_struct *ndpi_str,
u_int8_t proto, u_int16_t sport, u_int16_t dport) {
default_ports_tree_node_t node;
/* Set use_sport to config value if direction detection is enabled */
int use_sport = ndpi_str->cfg.direction_detect_enabled ? ndpi_str->cfg.use_client_port_in_guess : 1;

if(sport && dport) {
const void *ret;
Expand All @@ -4402,7 +4404,7 @@ static default_ports_tree_node_t *ndpi_get_guessed_protocol_id(struct ndpi_detec
ret = ndpi_tfind(&node, (proto == IPPROTO_TCP) ? (void *) &ndpi_str->tcpRoot : (void *) &ndpi_str->udpRoot,
default_ports_tree_node_t_cmp);

if(ret == NULL) {
if(ret == NULL && use_sport) {
node.default_port = sport;
ret = ndpi_tfind(&node, (proto == IPPROTO_TCP) ? (void *) &ndpi_str->tcpRoot : (void *) &ndpi_str->udpRoot,
default_ports_tree_node_t_cmp);
Expand Down Expand Up @@ -7425,6 +7427,7 @@ u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_
struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &ndpi_str->packet;
u_int16_t ret = NDPI_PROTOCOL_UNKNOWN;
int use_client = ndpi_str->cfg.use_client_ip_in_guess;

if(packet->iph) {
struct in_addr addr;
Expand All @@ -7433,7 +7436,7 @@ u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_
addr.s_addr = flow->s_address.v4;
ret = ndpi_network_port_ptree_match(ndpi_str, &addr, flow->s_port);

if(ret == NDPI_PROTOCOL_UNKNOWN) {
if(ret == NDPI_PROTOCOL_UNKNOWN && use_client) {
addr.s_addr = flow->c_address.v4;
ret = ndpi_network_port_ptree_match(ndpi_str, &addr, flow->c_port);
}
Expand All @@ -7444,7 +7447,7 @@ u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_
addr = *(struct in6_addr *)&flow->s_address.v6;
ret = ndpi_network_port_ptree6_match(ndpi_str, &addr, flow->s_port);

if(ret == NDPI_PROTOCOL_UNKNOWN) {
if(ret == NDPI_PROTOCOL_UNKNOWN && use_client) {
addr = *(struct in6_addr *)&flow->c_address.v6;
ret = ndpi_network_port_ptree6_match(ndpi_str, &addr, flow->c_port);
}
Expand Down Expand Up @@ -11510,6 +11513,8 @@ static const struct cfg_param {
{ NULL, "packets_limit_per_flow", "32", "0", "255", CFG_PARAM_INT, __OFF(max_packets_to_process), NULL },
{ NULL, "flow.direction_detection", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(direction_detect_enabled), NULL },
{ NULL, "flow.track_payload", "disable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(track_payload_enabled), NULL },
{ NULL, "flow.use_client_ip_in_guess", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(use_client_ip_in_guess), NULL},
{ NULL, "flow.use_client_port_in_guess", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(use_client_port_in_guess), NULL},
{ NULL, "tcp_ack_payload_heuristic", "disable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tcp_ack_paylod_heuristic), NULL },
{ NULL, "fully_encrypted_heuristic", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(fully_encrypted_heuristic), NULL },
{ NULL, "libgcrypt.init", "1", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(libgcrypt_init), NULL },
Expand Down
1 change: 1 addition & 0 deletions tests/cfgs/disable_use_client_ip/config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--cfg=flow.use_client_ip_in_guess,0
1 change: 1 addition & 0 deletions tests/cfgs/disable_use_client_ip/pcap/bot.pcap
27 changes: 27 additions & 0 deletions tests/cfgs/disable_use_client_ip/result/bot.pcap.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
DPI Packets (TCP): 6 (6.00 pkts/flow)
Confidence DPI : 1 (flows)
Num dissector calls: 15 (15.00 diss/flow)
LRU cache ookla: 0/0/0 (insert/search/found)
LRU cache bittorrent: 0/0/0 (insert/search/found)
LRU cache stun: 0/0/0 (insert/search/found)
LRU cache tls_cert: 0/0/0 (insert/search/found)
LRU cache mining: 0/0/0 (insert/search/found)
LRU cache msteams: 0/0/0 (insert/search/found)
LRU cache fpc_dns: 0/1/0 (insert/search/found)
Automa host: 1/0 (search/found)
Automa domain: 1/0 (search/found)
Automa tls cert: 0/0 (search/found)
Automa risk mask: 0/0 (search/found)
Automa common alpns: 0/0 (search/found)
Patricia risk mask: 2/0 (search/found)
Patricia risk mask IPv6: 0/0 (search/found)
Patricia risk: 1/1 (search/found)
Patricia risk IPv6: 0/0 (search/found)
Patricia protocols: 1/0 (search/found)
Patricia protocols IPv6: 0/0 (search/found)

HTTP 402 431124 1

Acceptable 402 431124 1

1 TCP 40.77.167.36:64768 <-> 89.31.72.220:80 [VLAN: 77][proto: 7/HTTP][IP: 0/Unknown][ClearText][Confidence: DPI][FPC: 0/Unknown, Confidence: Unknown][DPI packets: 6][cat: Web/5][115 pkts/7672 bytes <-> 287 pkts/423452 bytes][Goodput ratio: 4/96][5.66 sec][Hostname/SNI: atlanteditorino.it][bytes ratio: -0.964 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 58/3 4532/106 489/16][Pkt Len c2s/s2c min/avg/max/stddev: 64/64 67/1475 374/1498 29/171][URL: atlanteditorino.it/quartieri/img/S.Donato_M.Vittoria1930_B.jpg][StatusCode: 200][Content-Type: image/jpeg][Server: Apache][User-Agent: Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)][Risk: ** Crawler/Bot **][Risk Score: 10][Risk Info: UA Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/b][PLAIN TEXT (GET /quartieri/im)][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0]
1 change: 1 addition & 0 deletions tests/cfgs/disable_use_client_port/config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--cfg=flow.use_client_port_in_guess,0
1 change: 1 addition & 0 deletions tests/cfgs/disable_use_client_port/pcap/iphone.pcap
Loading

0 comments on commit cdda369

Please sign in to comment.