aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNardi Ivan <nardi.ivan@gmail.com>2022-07-28 21:01:16 +0200
committerToni <matzeton@googlemail.com>2022-09-04 17:22:19 +0200
commitb9cb3917564404367f35f54eafaaab1e28ce266f (patch)
treedf0f491a2c8401109e5050e54a6518dbcb5175b2
parent7578d02de9f196f73e2de47c457a1edc7f4c248d (diff)
Add support to opportunistic TLS
A lot of protocols provide the feature to upgrade their plain text connections to an encrypted one, via some kind of "STARTTLS" command. Add generic code to support this extension, and allow dissection of the entire TLS handshake. As examples, SMTP, POP, IMAP and FTP dissectors have been updated. Since this feature requires to process more packets per flow, add the possibility to disable it. Fix some log messages. Slight improvement on TCP sequence number tracking. As a side effect, this commit fix also a memory leak found by oss-fuzzer ``` ==108966==ERROR: LeakSanitizer: detected memory leaks Direct leak of 22 byte(s) in 1 object(s) allocated from: #0 0x55f8b367a0be in malloc (/home/ivan/svnrepos/nDPI/fuzz/fuzz_ndpi_reader_with_main+0x5480be) (BuildId: 94debacb4a6784c30420ab748c8bf3cc59621063) #1 0x55f8b36e1345 in ndpi_malloc_wrapper /home/ivan/svnrepos/nDPI/example/reader_util.c:321:10 #2 0x55f8b379c7d2 in ndpi_malloc /home/ivan/svnrepos/nDPI/src/lib/ndpi_main.c:212:25 #3 0x55f8b379cb18 in ndpi_strdup /home/ivan/svnrepos/nDPI/src/lib/ndpi_main.c:279:13 #4 0x55f8b386ce46 in processClientServerHello /home/ivan/svnrepos/nDPI/src/lib/protocols/tls.c:2153:34 #5 0x55f8b385ebf7 in processTLSBlock /home/ivan/svnrepos/nDPI/src/lib/protocols/tls.c:867:5 #6 0x55f8b39e708c in ndpi_extra_search_mail_smtp_tcp /home/ivan/svnrepos/nDPI/src/lib/protocols/mail_smtp.c:422:9 #7 0x55f8b37e636c in ndpi_process_extra_packet /home/ivan/svnrepos/nDPI/src/lib/ndpi_main.c:5884:9 #8 0x55f8b37edc05 in ndpi_detection_process_packet /home/ivan/svnrepos/nDPI/src/lib/ndpi_main.c:6276:5 #9 0x55f8b3701ffc in packet_processing /home/ivan/svnrepos/nDPI/example/reader_util.c:1619:31 #10 0x55f8b36faf14 in ndpi_workflow_process_packet /home/ivan/svnrepos/nDPI/example/reader_util.c:2189:10 #11 0x55f8b36b6a50 in LLVMFuzzerTestOneInput /home/ivan/svnrepos/nDPI/fuzz/fuzz_ndpi_reader.c:107:7 ``` See: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=50765
-rw-r--r--example/reader_util.c1
-rw-r--r--src/include/ndpi_api.h.in5
-rw-r--r--src/include/ndpi_protocol_ids.h1
-rw-r--r--src/include/ndpi_typedefs.h7
-rw-r--r--src/lib/ndpi_main.c71
-rw-r--r--src/lib/protocols/ftp_control.c18
-rw-r--r--src/lib/protocols/mail_imap.c27
-rw-r--r--src/lib/protocols/mail_pop.c24
-rw-r--r--src/lib/protocols/mail_smtp.c55
-rw-r--r--src/lib/protocols/tls.c41
-rw-r--r--tests/pcap/pop3_stls.pcapbin0 -> 12061 bytes
-rw-r--r--tests/pcap/smtp-starttls.pcapbin9003 -> 15960 bytes
-rw-r--r--tests/pcap/tls_multiple_synack_different_seq.pcapngbin0 -> 6984 bytes
-rw-r--r--tests/result/ftp-start-tls.pcap.out17
-rw-r--r--tests/result/imap-starttls.pcap.out17
-rw-r--r--tests/result/pop3_stls.pcap.out29
-rw-r--r--tests/result/smtp-starttls.pcap.out19
-rw-r--r--tests/result/synscan.pcap.out4
-rw-r--r--tests/result/tls_multiple_synack_different_seq.pcapng.out29
19 files changed, 286 insertions, 79 deletions
diff --git a/example/reader_util.c b/example/reader_util.c
index ce639b09a..37e5bf4b4 100644
--- a/example/reader_util.c
+++ b/example/reader_util.c
@@ -1214,6 +1214,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl
|| is_ndpi_proto(flow, NDPI_PROTOCOL_MAIL_SMTPS)
|| is_ndpi_proto(flow, NDPI_PROTOCOL_MAIL_IMAPS)
|| is_ndpi_proto(flow, NDPI_PROTOCOL_MAIL_POPS)
+ || is_ndpi_proto(flow, NDPI_PROTOCOL_FTPS)
|| ((is_quic = is_ndpi_proto(flow, NDPI_PROTOCOL_QUIC)))
) {
flow->ssh_tls.ssl_version = flow->ndpi_flow->protos.tls_quic.ssl_version;
diff --git a/src/include/ndpi_api.h.in b/src/include/ndpi_api.h.in
index 3a81cceb3..0fd177557 100644
--- a/src/include/ndpi_api.h.in
+++ b/src/include/ndpi_api.h.in
@@ -1010,6 +1010,11 @@ extern "C" {
lru_cache_type cache_type,
struct ndpi_lru_cache_stats *stats);
+ int ndpi_set_opportunistic_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t proto, int value);
+ int ndpi_get_opportunistic_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t proto);
+
/**
* Find a protocol id associated with a string automata
*
diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h
index b0ab19ebb..405cc4155 100644
--- a/src/include/ndpi_protocol_ids.h
+++ b/src/include/ndpi_protocol_ids.h
@@ -339,6 +339,7 @@ typedef enum {
NDPI_PROTOCOL_TIVOCONNECT = 308,
NDPI_PROTOCOL_KISMET = 309,
NDPI_PROTOCOL_FASTCGI = 310,
+ NDPI_PROTOCOL_FTPS = 311,
#ifdef CUSTOM_NDPI_PROTOCOLS
#include "../../../nDPI-custom/custom_ndpi_protocol_ids.h"
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 80834005b..b86e66aeb 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -1208,6 +1208,11 @@ struct ndpi_detection_module_struct {
/* *** If you add a new LRU cache, please update lru_cache_type above! *** */
+ int opportunistic_tls_smtp_enabled;
+ int opportunistic_tls_imap_enabled;
+ int opportunistic_tls_pop_enabled;
+ int opportunistic_tls_ftp_enabled;
+
ndpi_proto_defaults_t proto_defaults[NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS];
u_int8_t direction_detect_disable:1, /* disable internal detection of packet direction */ _pad:7;
@@ -1395,7 +1400,7 @@ struct ndpi_flow_struct {
char *esni;
} encrypted_sni;
ndpi_cipher_weakness server_unsafe_cipher;
- } tls_quic; /* Used also by DTLS and POPS/IMAPS/SMTPS */
+ } tls_quic; /* Used also by DTLS and POPS/IMAPS/SMTPS/FTPS */
struct {
char client_signature[48], server_signature[48];
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 58931d567..4d6523856 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -1974,6 +1974,10 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
"FastCGI", NDPI_PROTOCOL_CATEGORY_NETWORK,
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, 0 /* nw proto */, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_FTPS,
+ "FTPS", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
#ifdef CUSTOM_NDPI_PROTOCOLS
#include "../../../nDPI-custom/custom_ndpi_main.c"
@@ -2759,6 +2763,11 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
return(NULL);
}
+ ndpi_str->opportunistic_tls_smtp_enabled = 1;
+ ndpi_str->opportunistic_tls_imap_enabled = 1;
+ ndpi_str->opportunistic_tls_pop_enabled = 1;
+ ndpi_str->opportunistic_tls_ftp_enabled = 1;
+
ndpi_init_protocol_defaults(ndpi_str);
if(ndpi_callback_init(ndpi_str)) {
@@ -4924,7 +4933,8 @@ void ndpi_free_flow_data(struct ndpi_flow_struct* flow) {
flow_is_proto(flow, NDPI_PROTOCOL_DTLS) ||
flow_is_proto(flow, NDPI_PROTOCOL_MAIL_SMTPS) ||
flow_is_proto(flow, NDPI_PROTOCOL_MAIL_POPS) ||
- flow_is_proto(flow, NDPI_PROTOCOL_MAIL_IMAPS)) {
+ flow_is_proto(flow, NDPI_PROTOCOL_MAIL_IMAPS) ||
+ flow_is_proto(flow, NDPI_PROTOCOL_FTPS)) {
if(flow->protos.tls_quic.server_names)
ndpi_free(flow->protos.tls_quic.server_names);
@@ -5193,8 +5203,8 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str,
}
}
- if((flow->next_tcp_seq_nr[0] == 0 && flow->next_tcp_seq_nr[1] == 0) ||
- (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0)) {
+ if(flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0 ||
+ (tcph->syn && flow->packet_counter == 0)) {
/* initialize tcp sequence counters */
/* the ack flag needs to be set to get valid sequence numbers from the other
* direction. Usually it will catch the second packet syn+ack but it works
@@ -5202,6 +5212,8 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str,
*
* if the syn flag is set add one to the sequence number,
* otherwise use the payload length.
+ *
+ * If we receive multiple syn-ack (before any real data), keep the last one
*/
if(tcph->ack != 0) {
flow->next_tcp_seq_nr[packet->packet_direction] =
@@ -6246,9 +6258,8 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
u_int32_t num_calls = 0;
ndpi_protocol ret = { flow->detected_protocol_stack[1], flow->detected_protocol_stack[0], flow->category, NULL };
- if(ndpi_str->ndpi_log_level >= NDPI_LOG_TRACE)
- NDPI_LOG(flow ? flow->detected_protocol_stack[0] : NDPI_PROTOCOL_UNKNOWN, ndpi_str, NDPI_LOG_TRACE,
- "START packet processing\n");
+ NDPI_LOG_DBG(ndpi_str, "[%d/%d] START packet processing\n",
+ flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]);
if(flow == NULL)
return(ret);
@@ -8889,3 +8900,51 @@ int ndpi_seen_flow_beginning(const struct ndpi_flow_struct *flow)
return 0;
return 1;
}
+
+/* ******************************************************************** */
+
+int ndpi_set_opportunistic_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t proto, int value)
+{
+ if(!ndpi_struct || (value != 0 && value != 1))
+ return -1;
+
+ switch(proto) {
+ case NDPI_PROTOCOL_MAIL_SMTP:
+ ndpi_struct->opportunistic_tls_smtp_enabled = value;
+ return 0;
+ case NDPI_PROTOCOL_MAIL_IMAP:
+ ndpi_struct->opportunistic_tls_imap_enabled = value;
+ return 0;
+ case NDPI_PROTOCOL_MAIL_POP:
+ ndpi_struct->opportunistic_tls_pop_enabled = value;
+ return 0;
+ case NDPI_PROTOCOL_FTP_CONTROL:
+ ndpi_struct->opportunistic_tls_ftp_enabled = value;
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/* ******************************************************************** */
+
+int ndpi_get_opportunistic_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t proto)
+{
+ if(!ndpi_struct)
+ return -1;
+
+ switch(proto) {
+ case NDPI_PROTOCOL_MAIL_SMTP:
+ return ndpi_struct->opportunistic_tls_smtp_enabled;
+ case NDPI_PROTOCOL_MAIL_IMAP:
+ return ndpi_struct->opportunistic_tls_imap_enabled;
+ case NDPI_PROTOCOL_MAIL_POP:
+ return ndpi_struct->opportunistic_tls_pop_enabled;
+ case NDPI_PROTOCOL_FTP_CONTROL:
+ return ndpi_struct->opportunistic_tls_ftp_enabled;
+ default:
+ return -1;
+ }
+}
diff --git a/src/lib/protocols/ftp_control.c b/src/lib/protocols/ftp_control.c
index a0bec3864..44911b2d2 100644
--- a/src/lib/protocols/ftp_control.c
+++ b/src/lib/protocols/ftp_control.c
@@ -29,6 +29,9 @@
// #define FTP_DEBUG
+extern void switch_extra_dissection_to_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
+
/* *************************************************************** */
static void ndpi_int_ftp_control_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
@@ -643,10 +646,21 @@ static void ndpi_check_ftp_control(struct ndpi_detection_module_struct *ndpi_str
if(flow->l4.tcp.ftp_imap_pop_smtp.password[0] == '\0' &&
flow->l4.tcp.ftp_imap_pop_smtp.auth_done == 0 &&
- flow->l4.tcp.ftp_imap_pop_smtp.auth_tls == 0) /* TODO: any values on dissecting TLS handshake? */
+ flow->l4.tcp.ftp_imap_pop_smtp.auth_tls == 0) {
flow->ftp_control_stage = 0;
- else
+ } else if (flow->l4.tcp.ftp_imap_pop_smtp.auth_tls == 1 &&
+ ndpi_struct->opportunistic_tls_ftp_enabled) {
+ flow->host_server_name[0] = '\0'; /* Remove any data set by other dissectors (eg. SMTP) */
+ /* Switch classification to FTPS */
+ ndpi_set_detected_protocol(ndpi_struct, flow,
+ NDPI_PROTOCOL_FTPS, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
+ NDPI_LOG_DBG(ndpi_struct, "Switching to [%d/%d]\n",
+ flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]);
+ /* We are done (in FTP dissector): delegating TLS... */
+ switch_extra_dissection_to_tls(ndpi_struct, flow);
+ } else {
ndpi_int_ftp_control_add_connection(ndpi_struct, flow);
+ }
} else {
NDPI_LOG_DBG2(ndpi_struct, "The reply did not seem to belong to FTP_CONTROL, "
"resetting the stage to 0\n");
diff --git a/src/lib/protocols/mail_imap.c b/src/lib/protocols/mail_imap.c
index a6809b454..2ae04f24b 100644
--- a/src/lib/protocols/mail_imap.c
+++ b/src/lib/protocols/mail_imap.c
@@ -30,6 +30,9 @@
/* #define IMAP_DEBUG 1*/
+extern void switch_extra_dissection_to_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
+
static void ndpi_int_mail_imap_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
u_int16_t protocol) {
flow->guessed_protocol_id = NDPI_PROTOCOL_UNKNOWN; /* Avoid IMAPS to be used s sub-protocol */
@@ -51,13 +54,6 @@ void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct,
printf("%s() [%.*s]\n", __FUNCTION__, packet->payload_packet_len, packet->payload);
#endif
- if(flow->l4.tcp.mail_imap_starttls == 2) {
- NDPI_LOG_DBG2(ndpi_struct, "starttls detected\n");
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MAIL_IMAP);
- NDPI_DEL_PROTOCOL_FROM_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TLS);
- return;
- }
-
if(packet->payload_packet_len >= 4 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a) {
// the DONE command appears without a tag
if(packet->payload_packet_len == 6 && ((packet->payload[0] == 'D' || packet->payload[0] == 'd')
@@ -113,8 +109,17 @@ void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct,
&& (packet->payload[command_start + 1] == 'K' || packet->payload[command_start + 1] == 'k')
&& packet->payload[command_start + 2] == ' ') {
flow->l4.tcp.mail_imap_stage += 1;
- if(flow->l4.tcp.mail_imap_starttls == 1)
- flow->l4.tcp.mail_imap_starttls = 2;
+ if(flow->l4.tcp.mail_imap_starttls == 1) {
+ NDPI_LOG_DBG2(ndpi_struct, "starttls detected\n");
+ ndpi_int_mail_imap_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_IMAPS);
+ if(ndpi_struct->opportunistic_tls_imap_enabled) {
+ NDPI_LOG_DBG(ndpi_struct, "Switching to [%d/%d]\n",
+ flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]);
+ /* We are done (in IMAP dissector): delegating TLS... */
+ switch_extra_dissection_to_tls(ndpi_struct, flow);
+ return;
+ }
+ }
saw_command = 1;
} else if((packet->payload[command_start] == 'U' || packet->payload[command_start] == 'u')
&& (packet->payload[command_start + 1] == 'I' || packet->payload[command_start + 1] == 'i')
@@ -126,7 +131,7 @@ void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct,
&& packet->payload[command_start + 2] == ' ') {
flow->l4.tcp.mail_imap_stage += 1;
if(flow->l4.tcp.mail_imap_starttls == 1)
- flow->l4.tcp.mail_imap_starttls = 2;
+ flow->l4.tcp.mail_imap_starttls = 0;
saw_command = 1;
}
}
@@ -156,7 +161,6 @@ void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct,
&& (packet->payload[command_start + 7] == 'S' || packet->payload[command_start + 7] == 's')) {
flow->l4.tcp.mail_imap_stage += 1;
flow->l4.tcp.mail_imap_starttls = 1;
- ndpi_int_mail_imap_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_IMAPS);
saw_command = 1;
}
}
@@ -242,7 +246,6 @@ void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct,
flow->l4.tcp.mail_imap_stage += 1;
/* Authenticate phase may have multiple messages. Ignore them since they are
somehow encrypted anyway. */
- flow->l4.tcp.mail_imap_starttls = 2;
ndpi_int_mail_imap_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_IMAPS);
saw_command = 1;
}
diff --git a/src/lib/protocols/mail_pop.c b/src/lib/protocols/mail_pop.c
index f0a1731b3..1474af1be 100644
--- a/src/lib/protocols/mail_pop.c
+++ b/src/lib/protocols/mail_pop.c
@@ -43,12 +43,16 @@
#define POP_BIT_STLS 0x0400
+extern void switch_extra_dissection_to_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
+
static void ndpi_int_mail_pop_add_connection(struct ndpi_detection_module_struct
- *ndpi_struct, struct ndpi_flow_struct *flow) {
+ *ndpi_struct, struct ndpi_flow_struct *flow,
+ u_int16_t protocol) {
NDPI_LOG_INFO(ndpi_struct, "mail_pop identified\n");
flow->guessed_protocol_id = NDPI_PROTOCOL_UNKNOWN; /* Avoid POP3S to be used s sub-protocol */
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_POP, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
+ ndpi_set_detected_protocol(ndpi_struct, flow, protocol, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
}
/* **************************************** */
@@ -142,6 +146,7 @@ static int ndpi_int_mail_pop_check_for_client_commands(struct ndpi_detection_mod
&& (packet->payload[2] == 'L' || packet->payload[2] == 'l')
&& (packet->payload[3] == 'S' || packet->payload[3] == 's')) {
flow->l4.tcp.pop_command_bitmask |= POP_BIT_STLS;
+ flow->l4.tcp.mail_imap_starttls = 1;
return 1;
}
}
@@ -168,6 +173,19 @@ void ndpi_search_mail_pop_tcp(struct ndpi_detection_module_struct
&& (packet->payload[3] == 'R' || packet->payload[3] == 'r')))) {
// +OK or -ERR seen
flow->l4.tcp.mail_pop_stage += 1;
+ if(packet->payload[0] == '+' && flow->l4.tcp.mail_imap_starttls == 1) {
+ NDPI_LOG_DBG2(ndpi_struct, "starttls detected\n");
+ ndpi_int_mail_pop_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_POPS);
+ if(ndpi_struct->opportunistic_tls_pop_enabled) {
+ NDPI_LOG_DBG(ndpi_struct, "Switching to [%d/%d]\n",
+ flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]);
+ /* We are done (in POP dissector): delegating TLS... */
+ switch_extra_dissection_to_tls(ndpi_struct, flow);
+ return;
+ }
+ }
+ if(packet->payload[0] == '-' && flow->l4.tcp.mail_imap_starttls == 1)
+ flow->l4.tcp.mail_imap_starttls = 0;
} else if(!ndpi_int_mail_pop_check_for_client_commands(ndpi_struct, flow)) {
goto maybe_split_pop;
}
@@ -189,7 +207,7 @@ void ndpi_search_mail_pop_tcp(struct ndpi_detection_module_struct
if((flow->l4.tcp.ftp_imap_pop_smtp.password[0] != '\0')
|| (flow->l4.tcp.mail_pop_stage > 3)) {
- ndpi_int_mail_pop_add_connection(ndpi_struct, flow);
+ ndpi_int_mail_pop_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_POP);
if(flow->l4.tcp.ftp_imap_pop_smtp.password[0] == '\0')
popInitExtraPacketProcessing(flow);
}
diff --git a/src/lib/protocols/mail_smtp.c b/src/lib/protocols/mail_smtp.c
index 31f07c1c0..f6b0af060 100644
--- a/src/lib/protocols/mail_smtp.c
+++ b/src/lib/protocols/mail_smtp.c
@@ -48,8 +48,8 @@
/* #define SMTP_DEBUG 1 */
-extern int processTLSBlock(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow);
+extern void switch_extra_dissection_to_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
static void ndpi_int_mail_smtp_add_connection(struct ndpi_detection_module_struct
*ndpi_struct, struct ndpi_flow_struct *flow) {
@@ -153,6 +153,7 @@ void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct *ndpi_struct,
len = i-4;
/* Copy result for nDPI apps */
ndpi_hostname_sni_set(flow, &packet->line[a].ptr[4], len);
+ NDPI_LOG_DBG(ndpi_struct, "SMTP: hostname [%s]\n", flow->host_server_name);
if (ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_SMTP,
flow->host_server_name,
@@ -406,38 +407,40 @@ int ndpi_extra_search_mail_smtp_tcp(struct ndpi_detection_module_struct *ndpi_st
struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct * const packet = &ndpi_struct->packet;
- int rc = 0;
+ int rc;
- if (flow->l4.tcp.smtp_command_bitmask & SMTP_BIT_STARTTLS &&
- packet->payload_packet_len > 5)
- {
- uint8_t const * const block = &packet->payload[5];
- uint8_t const * const p = &packet->payload[0];
- uint16_t const block_len = packet->payload_packet_len - 5;
- uint16_t const l = packet->payload_packet_len;
+ if(flow->l4.tcp.smtp_command_bitmask & SMTP_BIT_STARTTLS) {
- packet->payload = block;
- packet->payload_packet_len = block_len;
+ /* RFC 3207:
+ "After the client gives the STARTTLS command, the server responds with
+ one of the following reply codes:
+ 220 Ready to start TLS
+ 501 Syntax error (no parameters allowed)
+ 454 TLS not available due to temporary reason"
+ */
- if (processTLSBlock(ndpi_struct, flow) != 0) {
+ if(ndpi_struct->opportunistic_tls_smtp_enabled &&
+ packet->payload_packet_len > 3 && memcmp(packet->payload, "220", 3) == 0) {
rc = 1;
- }
-
- packet->payload = p;
- packet->payload_packet_len = l;
-
- /* STARTTLS may be followed by a 220 - Service ready */
- if (rc == 0 && memcmp(packet->payload, "220", 3) != 0)
- {
- flow->l4.tcp.ftp_imap_pop_smtp.auth_done = 1;
- if (flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) {
- ndpi_set_detected_protocol(ndpi_struct, flow,
- NDPI_PROTOCOL_MAIL_SMTPS, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
+ /* Switch classification to SMTPS, keeping the hostname sub-classification (if any) */
+ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN &&
+ flow->detected_protocol_stack[0] != NDPI_PROTOCOL_MAIL_SMTP) {
+ ndpi_set_detected_protocol(ndpi_struct, flow,
+ flow->detected_protocol_stack[0], NDPI_PROTOCOL_MAIL_SMTPS, NDPI_CONFIDENCE_DPI);
+ /* Now it is safe to write to `flow->protos.tls_quic` union */
+ flow->protos.tls_quic.subprotocol_detected = 1;
} else {
ndpi_set_detected_protocol(ndpi_struct, flow,
- flow->guessed_host_protocol_id, NDPI_PROTOCOL_MAIL_SMTPS, NDPI_CONFIDENCE_DPI);
+ NDPI_PROTOCOL_MAIL_SMTPS, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
}
+ NDPI_LOG_DBG(ndpi_struct, "Switching to [%d/%d]\n",
+ flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]);
+ /* We are done (in SMTP dissector): delegating TLS... */
+ switch_extra_dissection_to_tls(ndpi_struct, flow);
+ } else {
+ rc = 0; /* Something went wrong. Stop extra dissection */
}
+
} else {
ndpi_search_mail_smtp_tcp(ndpi_struct, flow);
rc = ((flow->l4.tcp.ftp_imap_pop_smtp.password[0] == '\0') &&
diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c
index 53245a21e..98a8d8208 100644
--- a/src/lib/protocols/tls.c
+++ b/src/lib/protocols/tls.c
@@ -28,8 +28,6 @@
#include "ndpi_encryption.h"
extern char *strptime(const char *s, const char *format, struct tm *tm);
-extern int processTLSBlock(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow);
extern int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow, uint32_t quic_version);
extern int http_process_user_agent(struct ndpi_detection_module_struct *ndpi_struct,
@@ -221,7 +219,7 @@ void ndpi_search_tls_tcp_memory(struct ndpi_detection_module_struct *ndpi_struct
message->buffer_len,
packet->packet_direction,
ntohl(packet->tcp->seq),
- ntohl(packet->tcp->seq)+packet->payload_packet_len);
+ message->next_seq);
#endif
}
}
@@ -852,8 +850,8 @@ int processCertificate(struct ndpi_detection_module_struct *ndpi_struct,
/* **************************************** */
-int processTLSBlock(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow) {
+static int processTLSBlock(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &ndpi_struct->packet;
int ret;
@@ -924,8 +922,17 @@ static int ndpi_search_tls_tcp(struct ndpi_detection_module_struct *ndpi_struct,
packet->payload_packet_len);
#endif
- if(packet->payload_packet_len == 0)
- return(1); /* Keep working */
+ /* This function is also called by "extra dissection" data path. Unfortunately,
+ generic "extra function" code doesn't honour protocol bitmask.
+ TODO: handle that in ndpi_main.c for all the protocols */
+ if(packet->payload_packet_len == 0 ||
+ packet->tcp_retransmission) {
+#ifdef DEBUG_TLS_MEMORY
+ printf("[TLS Mem] Ack or retransmission %d/%d. Skip\n",
+ packet->payload_packet_len, packet->tcp_retransmission);
+#endif
+ return 1; /* Keep working */
+ }
ndpi_search_tls_tcp_memory(ndpi_struct, flow);
message = &flow->l4.tcp.tls.message[packet->packet_direction];
@@ -1224,6 +1231,26 @@ static void tlsInitExtraPacketProcessing(struct ndpi_detection_module_struct *nd
/* **************************************** */
+void switch_extra_dissection_to_tls(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+#ifdef DEBUG_TLS
+ printf("Switching to TLS extra dissection\n");
+#endif
+
+ /* Reset reassemblers */
+ if(flow->l4.tcp.tls.message[0].buffer)
+ ndpi_free(flow->l4.tcp.tls.message[0].buffer);
+ memset(&flow->l4.tcp.tls.message[0], '\0', sizeof(flow->l4.tcp.tls.message[0]));
+ if(flow->l4.tcp.tls.message[1].buffer)
+ ndpi_free(flow->l4.tcp.tls.message[1].buffer);
+ memset(&flow->l4.tcp.tls.message[1], '\0', sizeof(flow->l4.tcp.tls.message[1]));
+
+ tlsInitExtraPacketProcessing(ndpi_struct, flow);
+}
+
+/* **************************************** */
+
static void tlsCheckUncommonALPN(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow) {
char * alpn_start = flow->protos.tls_quic.alpn;
diff --git a/tests/pcap/pop3_stls.pcap b/tests/pcap/pop3_stls.pcap
new file mode 100644
index 000000000..b56dffac6
--- /dev/null
+++ b/tests/pcap/pop3_stls.pcap
Binary files differ
diff --git a/tests/pcap/smtp-starttls.pcap b/tests/pcap/smtp-starttls.pcap
index 493751539..4a37ecc51 100644
--- a/tests/pcap/smtp-starttls.pcap
+++ b/tests/pcap/smtp-starttls.pcap
Binary files differ
diff --git a/tests/pcap/tls_multiple_synack_different_seq.pcapng b/tests/pcap/tls_multiple_synack_different_seq.pcapng
new file mode 100644
index 000000000..3b9b621e4
--- /dev/null
+++ b/tests/pcap/tls_multiple_synack_different_seq.pcapng
Binary files differ
diff --git a/tests/result/ftp-start-tls.pcap.out b/tests/result/ftp-start-tls.pcap.out
index f671a123d..63b2c093e 100644
--- a/tests/result/ftp-start-tls.pcap.out
+++ b/tests/result/ftp-start-tls.pcap.out
@@ -1,6 +1,6 @@
Guessed flow protos: 0
-DPI Packets (TCP): 10 (10.00 pkts/flow)
+DPI Packets (TCP): 17 (17.00 pkts/flow)
Confidence DPI : 1 (flows)
Num dissector calls: 154 (154.00 diss/flow)
LRU cache ookla: 0/0/0 (insert/search/found)
@@ -10,15 +10,20 @@ 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)
-Automa host: 1/0 (search/found)
-Automa domain: 1/0 (search/found)
-Automa tls cert: 0/0 (search/found)
+Automa host: 2/0 (search/found)
+Automa domain: 2/0 (search/found)
+Automa tls cert: 1/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: 0/0 (search/found)
Patricia protocols: 6/0 (search/found)
-FTP_CONTROL 51 7510 1
+FTPS 51 7510 1
- 1 TCP 10.238.26.36:62092 <-> 10.220.50.76:21 [proto: 1/FTP_CONTROL][ClearText][Confidence: DPI][cat: Download/7][16 pkts/1744 bytes <-> 35 pkts/5766 bytes][Goodput ratio: 49/66][0.33 sec][bytes ratio: -0.536 (Download)][IAT c2s/s2c min/avg/max/stddev: 1/0 13/4 34/34 13/8][Pkt Len c2s/s2c min/avg/max/stddev: 60/60 109/165 384/566 80/152][Risk: ** Unsafe Protocol **][Risk Score: 10][PLAIN TEXT (Authorized users only. All acti)][Plen Bins: 22,25,32,0,2,0,5,0,0,0,2,0,0,0,0,0,10,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]
+JA3 Host Stats:
+ IP Address # JA3C
+ 1 10.238.26.36 1
+
+
+ 1 TCP 10.238.26.36:62092 <-> 10.220.50.76:21 [proto: 311/FTPS][Encrypted][Confidence: DPI][cat: Download/7][16 pkts/1744 bytes <-> 35 pkts/5766 bytes][Goodput ratio: 49/66][0.33 sec][bytes ratio: -0.536 (Download)][IAT c2s/s2c min/avg/max/stddev: 1/0 13/4 34/34 13/8][Pkt Len c2s/s2c min/avg/max/stddev: 60/60 109/165 384/566 80/152][Risk: ** Weak TLS Cipher **** TLS (probably) Not Carrying HTTPS **** Unsafe Protocol **** Missing SNI TLS Extn **][Risk Score: 170][Risk Info: No ALPN / Cipher TLS_RSA_WITH_3DES_EDE_CBC_SHA][TLSv1.2][JA3C: 398076b7fcad56308a762b3c79fe1f44][ServerNames: oss.huawei.com][JA3S: 5cd6efb8d804faf03e1462073b729151 (WEAK)][Issuer: C=CN, O=Huawei, OU=Wireless Network Product Line, CN=Huawei Wireless Network Product CA][Subject: C=CN, O=Huawei, OU=Huawei Network Product Line, CN=OSS Certificate][Certificate SHA-1: 0A:14:3A:AB:E1:3A:5B:1C:A7:BD:C7:82:45:8C:FA:37:D7:87:29:D2][Validity: 2012-03-12 08:54:33 - 2027-03-09 08:54:33][Cipher: TLS_RSA_WITH_3DES_EDE_CBC_SHA][PLAIN TEXT (Authorized users only. All acti)][Plen Bins: 22,25,32,0,2,0,5,0,0,0,2,0,0,0,0,0,10,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]
diff --git a/tests/result/imap-starttls.pcap.out b/tests/result/imap-starttls.pcap.out
index b1897c7eb..3122ddbe6 100644
--- a/tests/result/imap-starttls.pcap.out
+++ b/tests/result/imap-starttls.pcap.out
@@ -1,8 +1,8 @@
Guessed flow protos: 0
-DPI Packets (TCP): 10 (10.00 pkts/flow)
+DPI Packets (TCP): 19 (19.00 pkts/flow)
Confidence DPI : 1 (flows)
-Num dissector calls: 181 (181.00 diss/flow)
+Num dissector calls: 204 (204.00 diss/flow)
LRU cache ookla: 0/0/0 (insert/search/found)
LRU cache bittorrent: 0/0/0 (insert/search/found)
LRU cache zoom: 0/0/0 (insert/search/found)
@@ -10,9 +10,9 @@ 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)
-Automa host: 0/0 (search/found)
-Automa domain: 0/0 (search/found)
-Automa tls cert: 0/0 (search/found)
+Automa host: 2/0 (search/found)
+Automa domain: 2/0 (search/found)
+Automa tls cert: 1/0 (search/found)
Automa risk mask: 0/0 (search/found)
Automa common alpns: 0/0 (search/found)
Patricia risk mask: 2/0 (search/found)
@@ -21,4 +21,9 @@ Patricia protocols: 6/0 (search/found)
IMAPS 32 7975 1
- 1 TCP 192.168.17.53:49640 <-> 212.227.17.186:143 [proto: 51/IMAPS][Encrypted][Confidence: DPI][cat: Email/3][18 pkts/1536 bytes <-> 14 pkts/6439 bytes][Goodput ratio: 35/88][3.02 sec][bytes ratio: -0.615 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 188/251 1486/1677 371/512][Pkt Len c2s/s2c min/avg/max/stddev: 54/60 85/460 372/1514 76/571][Risk: ** Known Proto on Non Std Port **][Risk Score: 50][Risk Info: Expected on port 993][PLAIN TEXT (CAPABILITY IMAP)][Plen Bins: 25,18,6,6,0,0,0,6,6,6,0,0,0,0,0,0,0,0,6,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,18,0,0]
+JA3 Host Stats:
+ IP Address # JA3C
+ 1 192.168.17.53 1
+
+
+ 1 TCP 192.168.17.53:49640 <-> 212.227.17.186:143 [proto: 51/IMAPS][Encrypted][Confidence: DPI][cat: Email/3][18 pkts/1536 bytes <-> 14 pkts/6439 bytes][Goodput ratio: 35/88][3.02 sec][bytes ratio: -0.615 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 188/251 1486/1677 371/512][Pkt Len c2s/s2c min/avg/max/stddev: 54/60 85/460 372/1514 76/571][Risk: ** Known Proto on Non Std Port **** TLS (probably) Not Carrying HTTPS **** Missing SNI TLS Extn **][Risk Score: 110][Risk Info: Expected on port 993 / No ALPN][TLSv1.2][JA3C: c369db2c355ad05c76f5660af3179b01][ServerNames: imap.gmx.net,imap.gmx.de][JA3S: 0debd3853f330c574b05e0b6d882dc27][Issuer: C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=NRW, L=Netphen, CN=TeleSec ServerPass DE-1][Subject: C=DE, O=1&1 Mail & Media GmbH, ST=Rhineland-Palatinate, L=Montabaur, CN=imap.gmx.net][Certificate SHA-1: 0F:E8:EA:E2:48:87:DF:8E:FE:F2:84:59:FE:D0:FC:1C:46:24:85:F5][Firefox][Validity: 2013-11-12 10:17:31 - 2016-11-17 23:59:59][Cipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384][PLAIN TEXT (CAPABILITY IMAP)][Plen Bins: 25,18,6,6,0,0,0,6,6,6,0,0,0,0,0,0,0,0,6,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,18,0,0]
diff --git a/tests/result/pop3_stls.pcap.out b/tests/result/pop3_stls.pcap.out
new file mode 100644
index 000000000..4009a9757
--- /dev/null
+++ b/tests/result/pop3_stls.pcap.out
@@ -0,0 +1,29 @@
+Guessed flow protos: 0
+
+DPI Packets (TCP): 18 (18.00 pkts/flow)
+Confidence DPI : 1 (flows)
+Num dissector calls: 232 (232.00 diss/flow)
+LRU cache ookla: 0/0/0 (insert/search/found)
+LRU cache bittorrent: 0/0/0 (insert/search/found)
+LRU cache zoom: 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)
+Automa host: 4/0 (search/found)
+Automa domain: 3/0 (search/found)
+Automa tls cert: 1/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: 0/0 (search/found)
+Patricia protocols: 4/0 (search/found)
+
+POPS 53 11189 1
+
+JA3 Host Stats:
+ IP Address # JA3C
+ 1 192.168.20.18 1
+
+
+ 1 TCP 192.168.20.18:50583 <-> 72.249.41.52:110 [proto: 23/POPS][Encrypted][Confidence: DPI][cat: Email/3][23 pkts/2059 bytes <-> 30 pkts/9130 bytes][Goodput ratio: 39/82][5.43 sec][Hostname/SNI: pop.lavabit.com][bytes ratio: -0.632 (Download)][IAT c2s/s2c min/avg/max/stddev: 6/0 273/202 2072/2002 508/432][Pkt Len c2s/s2c min/avg/max/stddev: 54/60 90/304 368/1514 69/480][Risk: ** Known Proto on Non Std Port **** Obsolete TLS (v1.1 or older) **][Risk Score: 150][Risk Info: Expected on port 995 / TLSv1][TLSv1][JA3C: 207409c2b30e670ca50e1eac016a4831][ServerNames: *.lavabit.com,lavabit.com][JA3S: 6b96cf9c27b0223177b0e9f135fe4899 (INSECURE)][Issuer: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., OU=http://certificates.godaddy.com/repository, CN=Go Daddy Secure Certification Authority][Subject: O=*.lavabit.com, OU=Domain Control Validated, CN=*.lavabit.com][Certificate SHA-1: 1D:14:60:3D:5E:0F:A2:EB:61:C5:27:F8:A4:26:80:B3:E5:BB:A2:B2][Validity: 2012-02-17 04:07:46 - 2017-02-17 04:07:46][Cipher: TLS_RSA_WITH_RC4_128_SHA][PLAIN TEXT (ERR Unrecognized command.)][Plen Bins: 34,37,2,2,2,5,0,2,0,2,0,2,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,10,0,0]
diff --git a/tests/result/smtp-starttls.pcap.out b/tests/result/smtp-starttls.pcap.out
index 4cacda8e0..b5f55902c 100644
--- a/tests/result/smtp-starttls.pcap.out
+++ b/tests/result/smtp-starttls.pcap.out
@@ -1,8 +1,8 @@
Guessed flow protos: 0
-DPI Packets (TCP): 11 (11.00 pkts/flow)
-Confidence DPI : 1 (flows)
-Num dissector calls: 1 (1.00 diss/flow)
+DPI Packets (TCP): 26 (13.00 pkts/flow)
+Confidence DPI : 2 (flows)
+Num dissector calls: 152 (76.00 diss/flow)
LRU cache ookla: 0/0/0 (insert/search/found)
LRU cache bittorrent: 0/0/0 (insert/search/found)
LRU cache zoom: 0/0/0 (insert/search/found)
@@ -10,20 +10,23 @@ 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)
-Automa host: 1/1 (search/found)
-Automa domain: 1/0 (search/found)
-Automa tls cert: 0/0 (search/found)
-Automa risk mask: 1/0 (search/found)
+Automa host: 4/1 (search/found)
+Automa domain: 3/0 (search/found)
+Automa tls cert: 1/0 (search/found)
+Automa risk mask: 2/0 (search/found)
Automa common alpns: 0/0 (search/found)
Patricia risk mask: 2/0 (search/found)
Patricia risk: 0/0 (search/found)
Patricia protocols: 2/2 (search/found)
+SMTPS 33 6429 1
Google 36 8403 1
JA3 Host Stats:
IP Address # JA3C
1 10.0.0.1 1
+ 2 2003:de:2016:125:fc36:8317:4e86:cb72 1
- 1 TCP 10.0.0.1:57406 <-> 173.194.68.26:25 [proto: 29.126/SMTPS.Google][Encrypted][Confidence: DPI][cat: Email/3][17 pkts/2514 bytes <-> 19 pkts/5889 bytes][Goodput ratio: 55/79][0.48 sec][Hostname/SNI: mx.google.com][bytes ratio: -0.402 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 30/24 156/103 42/26][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 148/310 752/1484 168/444][Risk: ** Obsolete TLS (v1.1 or older) **][Risk Score: 100][Risk Info: TLSv1][TLSv1][JA3C: fab507fe132c544e8a0eb7c394affeae][PLAIN TEXT (x.google.com ESMTP s4)][Plen Bins: 23,18,13,9,4,4,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0]
+ 1 TCP 10.0.0.1:57406 <-> 173.194.68.26:25 [proto: 29.126/SMTPS.Google][Encrypted][Confidence: DPI][cat: Email/3][17 pkts/2514 bytes <-> 19 pkts/5889 bytes][Goodput ratio: 55/79][0.48 sec][Hostname/SNI: mx.google.com][bytes ratio: -0.402 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 30/24 156/103 42/26][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 148/310 752/1484 168/444][Risk: ** Obsolete TLS (v1.1 or older) **][Risk Score: 100][Risk Info: TLSv1][TLSv1][JA3C: fab507fe132c544e8a0eb7c394affeae][ServerNames: aspmx.l.google.com,alt1.aspmx.l.google.com,alt2.aspmx.l.google.com,alt3.aspmx.l.google.com,alt4.aspmx.l.google.com,gmail-smtp-in.l.google.com,alt1.gmail-smtp-in.l.google.com,alt2.gmail-smtp-in.l.google.com,alt3.gmail-smtp-in.l.google.com,alt4.gmail-smtp-in.l.google.com,gmr-smtp-in.l.google.com,alt1.gmr-smtp-in.l.google.com,alt2.gmr-smtp-in.l.google.com,alt3.gmr-smtp-in.l.google.com,alt4.gmr-smtp-in.l.google.com,mx.google.com,aspmx2.googlemail.com,aspmx3.googlemail.com,aspmx4.googlemail.com,aspmx5.googlemail.com][JA3S: 6b96cf9c27b0223177b0e9f135fe4899 (INSECURE)][Issuer: C=US, O=Google Inc, CN=Google Internet Authority G2][Subject: C=US, ST=California, L=Mountain View, O=Google Inc, CN=mx.google.com][Certificate SHA-1: 45:15:6A:E7:49:63:40:94:F9:AB:09:1E:F5:A7:33:6D:F3:7B:28:FC][Validity: 2013-09-09 11:32:35 - 2014-09-09 11:32:35][Cipher: TLS_RSA_WITH_RC4_128_SHA][PLAIN TEXT (x.google.com ESMTP s4)][Plen Bins: 23,18,13,9,4,4,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0]
+ 2 TCP [2003:de:2016:125:fc36:8317:4e86:cb72]:7562 <-> [2003:de:2016:120::a08:53]:25 [VLAN: 125][proto: 29/SMTPS][Encrypted][Confidence: DPI][cat: Email/3][16 pkts/2994 bytes <-> 17 pkts/3435 bytes][Goodput ratio: 58/61][0.30 sec][Hostname/SNI: dovecot.weberlab.de][bytes ratio: -0.069 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 0/0 22/23 202/202 55/54][Pkt Len c2s/s2c min/avg/max/stddev: 78/78 187/202 1112/1218 244/263][Risk: ** Self-signed Cert **** TLS (probably) Not Carrying HTTPS **** TLS Suspicious Extn **][Risk Score: 210][Risk Info: Extn id 65283 / No ALPN / CN=jw-vm08-int-dns][TLSv1.2][JA3C: 7b38238e17474b8f6d113523bb5a8dd9][JA3S: ccc514751b175866924439bdbb5bba34][Issuer: CN=jw-vm08-int-dns][Subject: CN=jw-vm08-int-dns][Certificate SHA-1: AD:1B:57:6C:AC:BE:46:54:65:F6:1D:6D:85:2A:38:16:07:7D:31:17][Firefox][Validity: 2016-08-16 09:33:19 - 2026-08-14 09:33:19][Cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256][PLAIN TEXT (dns.webernetz.net ESMTP Postfix)][Plen Bins: 17,35,17,4,4,8,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0]
diff --git a/tests/result/synscan.pcap.out b/tests/result/synscan.pcap.out
index 832c90858..917778735 100644
--- a/tests/result/synscan.pcap.out
+++ b/tests/result/synscan.pcap.out
@@ -121,7 +121,7 @@ iSCSI 2 116 2
44 TCP 172.16.0.8:36050 -> 64.13.134.52:2605 [proto: 13/BGP][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
45 TCP 172.16.0.8:36050 -> 64.13.134.52:3000 [proto: 26/ntop][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
46 TCP 172.16.0.8:36050 -> 64.13.134.52:3128 [proto: 131/HTTP_Proxy][ClearText][Confidence: Match by port][cat: Web/5][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
- 47 TCP 172.16.0.8:36050 -> 64.13.134.52:3260 [proto: 311/iSCSI][ClearText][Confidence: Match by port][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
+ 47 TCP 172.16.0.8:36050 -> 64.13.134.52:3260 [proto: 312/iSCSI][ClearText][Confidence: Match by port][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
48 TCP 172.16.0.8:36050 -> 64.13.134.52:3306 [proto: 20/MySQL][ClearText][Confidence: Match by port][cat: Database/11][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
49 TCP 172.16.0.8:36050 -> 64.13.134.52:3389 [proto: 88/RDP][ClearText][Confidence: Match by port][cat: RemoteAccess/12][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Desktop/File Sharing **** Unidirectional Traffic **][Risk Score: 20][Risk Info: No server to client traffic / Found RDP][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,0,0,0]
50 TCP 172.16.0.8:36050 -> 64.13.134.52:4343 [proto: 170/Whois-DAS][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
@@ -183,7 +183,7 @@ iSCSI 2 116 2
106 TCP 172.16.0.8:36051 -> 64.13.134.52:2605 [proto: 13/BGP][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
107 TCP 172.16.0.8:36051 -> 64.13.134.52:3000 [proto: 26/ntop][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
108 TCP 172.16.0.8:36051 -> 64.13.134.52:3128 [proto: 131/HTTP_Proxy][ClearText][Confidence: Match by port][cat: Web/5][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
- 109 TCP 172.16.0.8:36051 -> 64.13.134.52:3260 [proto: 311/iSCSI][ClearText][Confidence: Match by port][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
+ 109 TCP 172.16.0.8:36051 -> 64.13.134.52:3260 [proto: 312/iSCSI][ClearText][Confidence: Match by port][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
110 TCP 172.16.0.8:36051 -> 64.13.134.52:3306 [proto: 20/MySQL][ClearText][Confidence: Match by port][cat: Database/11][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
111 TCP 172.16.0.8:36051 -> 64.13.134.52:3389 [proto: 88/RDP][ClearText][Confidence: Match by port][cat: RemoteAccess/12][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Desktop/File Sharing **** Unidirectional Traffic **][Risk Score: 20][Risk Info: No server to client traffic / Found RDP][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,0,0,0]
112 TCP 172.16.0.8:36051 -> 64.13.134.52:4343 [proto: 170/Whois-DAS][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No server to client traffic][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,0,0,0]
diff --git a/tests/result/tls_multiple_synack_different_seq.pcapng.out b/tests/result/tls_multiple_synack_different_seq.pcapng.out
new file mode 100644
index 000000000..a1c3dea4e
--- /dev/null
+++ b/tests/result/tls_multiple_synack_different_seq.pcapng.out
@@ -0,0 +1,29 @@
+Guessed flow protos: 0
+
+DPI Packets (TCP): 10 (10.00 pkts/flow)
+Confidence DPI : 1 (flows)
+Num dissector calls: 1 (1.00 diss/flow)
+LRU cache ookla: 0/0/0 (insert/search/found)
+LRU cache bittorrent: 0/0/0 (insert/search/found)
+LRU cache zoom: 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)
+Automa host: 1/1 (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: 0/0 (search/found)
+Patricia protocols: 4/0 (search/found)
+
+AmazonAWS 10 6532 1
+
+JA3 Host Stats:
+ IP Address # JA3C
+ 1 10.10.10.1 1
+
+
+ 1 TCP 10.10.10.1:443 <-> 192.168.0.1:59927 [proto: 91.265/TLS.AmazonAWS][Encrypted][Confidence: DPI][cat: Cloud/13][9 pkts/5961 bytes <-> 1 pkts/571 bytes][Goodput ratio: 91/90][29.38 sec][Hostname/SNI: bolt-prod-s3-eu-west-1.s3.eu-west-1.amazonaws.com][ALPN: h2;http/1.1][TLS Supported Versions: GREASE;TLSv1.3;TLSv1.2;TLSv1.1;TLSv1][bytes ratio: 0.825 (Upload)][IAT c2s/s2c min/avg/max/stddev: 0/0 3672/0 15063/0 5728/0][Pkt Len c2s/s2c min/avg/max/stddev: 66/571 662/571 1414/571 649/0][TLSv1.2][JA3C: b32309a26951912be7dba376398abc3b][ServerNames: s3-eu-west-1.amazonaws.com,*.s3-eu-west-1.amazonaws.com,s3.eu-west-1.amazonaws.com,*.s3.eu-west-1.amazonaws.com,s3.dualstack.eu-west-1.amazonaws.com,*.s3.dualstack.eu-west-1.amazonaws.com,*.s3.amazonaws.com,*.s3-control.eu-west-1.amazonaws.com,s3-control.eu-west-1.amazonaws.com,*.s3-control.dualstack.eu-west-1.amazonaws.com,s3-control.dualstack.eu-west-1.amazonaws.com,*.s3-accesspoint.eu-west-1.amazonaws.com,*.s3-accesspoint.dualstack.eu-west-1.amazonaws.com,*.s3.eu-west-1.vpce.amazonaws.com][JA3S: 704239182a9091e4453fdbfe0fd17586][Issuer: C=US, O=Amazon, OU=Server CA 1B, CN=Amazon][Subject: CN=*.s3-eu-west-1.amazonaws.com][Certificate SHA-1: 5A:47:18:0A:2F:90:02:C9:30:5C:B1:BE:D6:0D:5A:42:24:C8:81:76][Chrome][Validity: 2021-03-26 00:00:00 - 2022-03-08 23:59:59][Cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256][PLAIN TEXT (Starfield Technologies)][Plen Bins: 0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,51,0,0,0,0,0]