Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add enable/disable guessing using client IP/port #2569

Merged
merged 3 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -301,6 +301,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 @@ -200,6 +200,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;
IvanNardi marked this conversation as resolved.
Show resolved Hide resolved

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 @@ -7422,6 +7424,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;
IvanNardi marked this conversation as resolved.
Show resolved Hide resolved

if(packet->iph) {
struct in_addr addr;
Expand All @@ -7430,7 +7433,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 @@ -7441,7 +7444,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 @@ -11503,6 +11506,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/1kxun.pcap
Loading
Loading