aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorIvan Nardi <12729895+IvanNardi@users.noreply.github.com>2024-09-24 14:20:31 +0200
committerGitHub <noreply@github.com>2024-09-24 14:20:31 +0200
commitddd08f913c80289e13e9c000e11c473a21ec23ca (patch)
tree4ed5ba0fbaa250b5999c2d3bac91466dd12303ac /src/include
parent686d0e3839768dbbf1a073db9cb0cef58b6e5da8 (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.h5
-rw-r--r--src/include/ndpi_private.h6
-rw-r--r--src/include/ndpi_typedefs.h15
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