diff options
author | Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> | 2024-09-24 14:20:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 14:20:31 +0200 |
commit | ddd08f913c80289e13e9c000e11c473a21ec23ca (patch) | |
tree | 4ed5ba0fbaa250b5999c2d3bac91466dd12303ac /src/include | |
parent | 686d0e3839768dbbf1a073db9cb0cef58b6e5da8 (diff) |
Add some heuristics to detect encrypted/obfuscated/proxied TLS flows (#2553)
Based on the paper: "Fingerprinting Obfuscated Proxy Traffic with
Encapsulated TLS Handshakes".
See: https://www.usenix.org/conference/usenixsecurity24/presentation/xue-fingerprinting
Basic idea:
* the packets/bytes distribution of a TLS handshake is quite unique
* this fingerprint is still detectable if the handshake is
encrypted/proxied/obfuscated
All heuristics are disabled by default.
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/ndpi_api.h | 5 | ||||
-rw-r--r-- | src/include/ndpi_private.h | 6 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 15 |
3 files changed, 21 insertions, 5 deletions
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h index ae1540dc6..d2ba9816e 100644 --- a/src/include/ndpi_api.h +++ b/src/include/ndpi_api.h @@ -1853,6 +1853,11 @@ extern "C" { /* ******************************* */ + /* Mahalanobis distance (https://en.wikipedia.org/wiki/Mahalanobis_distance) between a point x and a distribution with mean u and inverted covariant matrix i_s */ + float ndpi_mahalanobis_distance(const u_int32_t *x, u_int32_t size, const float *u, const float *i_s); + + /* ******************************* */ + int ndpi_init_bin(struct ndpi_bin *b, enum ndpi_bin_family f, u_int16_t num_bins); void ndpi_free_bin(struct ndpi_bin *b); struct ndpi_bin* ndpi_clone_bin(struct ndpi_bin *b); diff --git a/src/include/ndpi_private.h b/src/include/ndpi_private.h index be142717b..0bb3af0f1 100644 --- a/src/include/ndpi_private.h +++ b/src/include/ndpi_private.h @@ -121,6 +121,7 @@ struct ndpi_packet_struct { struct ndpi_int_one_line_struct http_origin; struct ndpi_int_one_line_struct server_line; struct ndpi_int_one_line_struct http_method; + struct ndpi_int_one_line_struct upgrade_line; struct ndpi_int_one_line_struct http_response; /* the first "word" in this pointer is the response code in the packet (200, etc) */ @@ -233,6 +234,8 @@ struct ndpi_detection_module_config_struct { int tls_certificate_expire_in_x_days; int tls_app_blocks_tracking_enabled; + int tls_heuristics; + int tls_heuristics_max_packets; int tls_sha1_fingerprint_enabled; int tls_ja3c_fingerprint_enabled; int tls_ja3s_fingerprint_enabled; @@ -642,7 +645,8 @@ void switch_to_tls(struct ndpi_detection_module_struct *ndpi_struct, int is_dtls(const u_int8_t *buf, u_int32_t buf_len, u_int32_t *block_len); void switch_extra_dissection_to_tls(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); - +void switch_extra_dissection_to_tls_obfuscated_heur(struct ndpi_detection_module_struct* ndpi_struct, + struct ndpi_flow_struct* flow); /* HTTP */ void http_process_user_agent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index b095ca221..fc0a2cf16 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -795,6 +795,11 @@ struct ndpi_lru_cache { /* OpenVPN */ #define NDPI_HEURISTICS_OPENVPN_OPCODE 0x01 /* Enable heuristic based on opcode frequency */ +/* TLS */ +#define NDPI_HEURISTICS_TLS_OBFUSCATED_PLAIN 0x01 /* Enable heuristic to detect proxied/obfuscated TLS flows over generic/unknown flows */ +#define NDPI_HEURISTICS_TLS_OBFUSCATED_TLS 0x02 /* Enable heuristic to detect proxied/obfuscated TLS flows over TLS tunnels, i.e. TLS over TLS */ +#define NDPI_HEURISTICS_TLS_OBFUSCATED_HTTP 0x04 /* Enable heuristic to detect proxied/obfuscated TLS flows over HTTP/WebSocket */ + /* ************************************************** */ @@ -1304,6 +1309,7 @@ struct ndpi_flow_struct { struct { ndpi_http_method method; u_int8_t request_version; /* 0=1.0 and 1=1.1. Create an enum for this? */ + u_int8_t websocket:1, _pad:7; u_int16_t response_status_code; /* 200, 404, etc. */ char *url, *content_type /* response */, *request_content_type /* e.g. for POST */, *user_agent, *server; char *detected_os; /* Via HTTP/QUIC User-Agent */ @@ -1330,7 +1336,8 @@ struct ndpi_flow_struct { struct { message_t message[2]; /* Directions */ - u_int8_t certificate_processed:1, _pad:7; + u_int8_t certificate_processed:1, change_cipher_from_client:1, change_cipher_from_server:1, from_opportunistic_tls:1, pad:4; + struct tls_obfuscated_heuristic_state *obfuscated_heur_state; } tls_quic; /* Used also by DTLS and POPS/IMAPS/SMTPS/FTPS */ union { @@ -1549,7 +1556,7 @@ struct ndpi_flow_struct { /* Flow payload */ u_int16_t flow_payload_len; char *flow_payload; - + /* Leave this field below at the end The field below can be used by third @@ -1563,8 +1570,8 @@ struct ndpi_flow_struct { _Static_assert(sizeof(((struct ndpi_flow_struct *)0)->protos) <= 264, "Size of the struct member protocols increased to more than 264 bytes, " "please check if this change is necessary."); -_Static_assert(sizeof(struct ndpi_flow_struct) <= 1152, - "Size of the flow struct increased to more than 1152 bytes, " +_Static_assert(sizeof(struct ndpi_flow_struct) <= 1160, + "Size of the flow struct increased to more than 1160 bytes, " "please check if this change is necessary."); #endif #endif |