diff options
author | Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> | 2024-06-05 13:49:34 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-05 13:49:34 +0200 |
commit | b6beeef62352f0537e5f546f1061e92215597b97 (patch) | |
tree | 8460c39abf3bd538b47a7a0b3fa43293d0bf215c /src | |
parent | 6a9d4b1ab64d85d6070205f7bc00c1d14b88de11 (diff) |
TLS: add support for DTLS (over STUN) over TCP (#2463)
TODO: TCP reassembler on top of UDP reassembler
See: #2414
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/protocols/stun.c | 99 | ||||
-rw-r--r-- | src/lib/protocols/tls.c | 17 |
2 files changed, 57 insertions, 59 deletions
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c index 877379abc..60986f232 100644 --- a/src/lib/protocols/stun.c +++ b/src/lib/protocols/stun.c @@ -698,65 +698,60 @@ static int stun_search_again(struct ndpi_detection_module_struct *ndpi_struct, positives. In that case, the TLS dissector doesn't set the master protocol, so we need to rollback to the current state */ - if(packet->tcp) { - /* TODO: TLS code assumes that DTLS is only over UDP */ - NDPI_LOG_DBG(ndpi_struct, "Ignoring DTLS over TCP\n"); + if(flow->tls_quic.certificate_processed == 1) { + NDPI_LOG_DBG(ndpi_struct, "Interesting DTLS stuff already processed. Ignoring\n"); } else { - if(flow->tls_quic.certificate_processed == 1) { - NDPI_LOG_DBG(ndpi_struct, "Interesting DTLS stuff already processed. Ignoring\n"); - } else { - NDPI_LOG_DBG(ndpi_struct, "Switch to DTLS (%d/%d)\n", - flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]); - - if(flow->stun.maybe_dtls == 0) { - /* First DTLS packet of the flow */ - first_dtls_pkt = 1; - - /* We might need to rollback this change... */ - old_proto_stack[0] = flow->detected_protocol_stack[0]; - old_proto_stack[1] = flow->detected_protocol_stack[1]; - - /* TODO: right way? It is a bit scary... do we need to reset something else too? */ - reset_detected_protocol(flow); - /* We keep the category related to STUN traffic */ - /* STUN often triggers this risk; clear it. TODO: clear other risks? */ - ndpi_unset_risk(flow, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); - - /* Give room for DTLS handshake, where we might have - retransmissions and fragments */ - flow->max_extra_packets_to_check = ndpi_min(255, (int)flow->max_extra_packets_to_check + 10); - flow->stun.maybe_dtls = 1; - } - - switch_to_tls(ndpi_struct, flow, first_dtls_pkt); + NDPI_LOG_DBG(ndpi_struct, "Switch to DTLS (%d/%d)\n", + flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]); + + if(flow->stun.maybe_dtls == 0) { + /* First DTLS packet of the flow */ + first_dtls_pkt = 1; + + /* We might need to rollback this change... */ + old_proto_stack[0] = flow->detected_protocol_stack[0]; + old_proto_stack[1] = flow->detected_protocol_stack[1]; + + /* TODO: right way? It is a bit scary... do we need to reset something else too? */ + reset_detected_protocol(flow); + /* We keep the category related to STUN traffic */ + /* STUN often triggers this risk; clear it. TODO: clear other risks? */ + ndpi_unset_risk(flow, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); + + /* Give room for DTLS handshake, where we might have + retransmissions and fragments */ + flow->max_extra_packets_to_check = ndpi_min(255, (int)flow->max_extra_packets_to_check + 10); + flow->stun.maybe_dtls = 1; + } - if(first_dtls_pkt && - flow->detected_protocol_stack[0] == NDPI_PROTOCOL_DTLS && - flow->detected_protocol_stack[1] == NDPI_PROTOCOL_UNKNOWN && - old_proto_stack[0] != NDPI_PROTOCOL_UNKNOWN && - old_proto_stack[0] != NDPI_PROTOCOL_STUN) { - NDPI_LOG_DBG(ndpi_struct, "Keeping old subclassification %d\n", old_proto_stack[0]); - ndpi_int_stun_add_connection(ndpi_struct, flow, - old_proto_stack[0] == NDPI_PROTOCOL_RTP ? NDPI_PROTOCOL_SRTP : old_proto_stack[0], - __get_master(flow)); - } + switch_to_tls(ndpi_struct, flow, first_dtls_pkt); - /* If this is not a real DTLS packet, we need to restore the old state */ - if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN && - first_dtls_pkt) { - NDPI_LOG_DBG(ndpi_struct, "Switch to TLS failed. Rollback to old classification\n"); + if(first_dtls_pkt && + flow->detected_protocol_stack[0] == NDPI_PROTOCOL_DTLS && + flow->detected_protocol_stack[1] == NDPI_PROTOCOL_UNKNOWN && + old_proto_stack[0] != NDPI_PROTOCOL_UNKNOWN && + old_proto_stack[0] != NDPI_PROTOCOL_STUN) { + NDPI_LOG_DBG(ndpi_struct, "Keeping old subclassification %d\n", old_proto_stack[0]); + ndpi_int_stun_add_connection(ndpi_struct, flow, + old_proto_stack[0] == NDPI_PROTOCOL_RTP ? NDPI_PROTOCOL_SRTP : old_proto_stack[0], + __get_master(flow)); + } - ndpi_set_detected_protocol(ndpi_struct, flow, - old_proto_stack[0], old_proto_stack[1], - NDPI_CONFIDENCE_DPI); + /* If this is not a real DTLS packet, we need to restore the old state */ + if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN && + first_dtls_pkt) { + NDPI_LOG_DBG(ndpi_struct, "Switch to TLS failed. Rollback to old classification\n"); - flow->stun.maybe_dtls = 0; - flow->max_extra_packets_to_check -= 10; - } + ndpi_set_detected_protocol(ndpi_struct, flow, + old_proto_stack[0], old_proto_stack[1], + NDPI_CONFIDENCE_DPI); - NDPI_LOG_DBG(ndpi_struct, "(%d/%d)\n", - flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]); + flow->stun.maybe_dtls = 0; + flow->max_extra_packets_to_check -= 10; } + + NDPI_LOG_DBG(ndpi_struct, "(%d/%d)\n", + flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]); } } } else if(first_byte <= 79) { diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c index f6b3f3663..ca23da4f8 100644 --- a/src/lib/protocols/tls.c +++ b/src/lib/protocols/tls.c @@ -119,7 +119,9 @@ static u_int32_t ndpi_tls_refine_master_protocol(struct ndpi_detection_module_st u_int16_t sport = ntohs(packet->tcp->source); u_int16_t dport = ntohs(packet->tcp->dest); - if((sport == 465) || (dport == 465) || (sport == 587) || (dport == 587)) + if(flow->stun.maybe_dtls) + protocol = NDPI_PROTOCOL_DTLS; + else if((sport == 465) || (dport == 465) || (sport == 587) || (dport == 587)) protocol = NDPI_PROTOCOL_MAIL_SMTPS; else if((sport == 993) || (dport == 993) || (flow->l4.tcp.mail_imap_starttls)) protocol = NDPI_PROTOCOL_MAIL_IMAPS; @@ -770,7 +772,7 @@ void processCertificateElements(struct ndpi_detection_module_struct *ndpi_struct int processCertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &ndpi_struct->packet; - int is_dtls = packet->udp ? 1 : 0; + int is_dtls = packet->udp || flow->stun.maybe_dtls; /* No certificate with QUIC */ u_int32_t certificates_length, length = (packet->payload[1] << 16) + (packet->payload[2] << 8) + packet->payload[3]; u_int32_t certificates_offset = 7 + (is_dtls ? 8 : 0); u_int8_t num_certificates_found = 0; @@ -899,6 +901,7 @@ 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; + int is_dtls = packet->udp || flow->stun.maybe_dtls; #ifdef DEBUG_TLS printf("[TLS] Processing block %u\n", packet->payload[0]); @@ -918,11 +921,11 @@ static int processTLSBlock(struct ndpi_detection_module_struct *ndpi_struct, (packet->payload[0] == 0x01) ? "Client" : "Server"); #endif - if((packet->tcp && flow->protos.tls_quic.ssl_version >= 0x0304 /* TLS 1.3 */) + if((!is_dtls && flow->protos.tls_quic.ssl_version >= 0x0304 /* TLS 1.3 */) && (packet->payload[0] == 0x02 /* Server Hello */)) { flow->tls_quic.certificate_processed = 1; /* No Certificate with TLS 1.3+ */ } - if((packet->udp && flow->protos.tls_quic.ssl_version == 0xFEFC /* DTLS 1.3 */) + if((is_dtls && flow->protos.tls_quic.ssl_version == 0xFEFC /* DTLS 1.3 */) && (packet->payload[0] == 0x02 /* Server Hello */)) { flow->tls_quic.certificate_processed = 1; /* No Certificate with DTLS 1.3+ */ } @@ -1655,7 +1658,7 @@ static void ndpi_compute_ja4(struct ndpi_flow_struct *flow, u_int16_t tls_handshake_version = ja->client.tls_handshake_version; char * const ja_str = &flow->protos.tls_quic.ja4_client[0]; const u_int16_t ja_max_len = sizeof(flow->protos.tls_quic.ja4_client); - bool is_dtls = (flow->l4_proto == IPPROTO_UDP) && (quic_version == 0); + bool is_dtls = ((flow->l4_proto == IPPROTO_UDP) && (quic_version == 0)) || flow->stun.maybe_dtls; /* Compute JA4 TLS/QUIC client @@ -1815,7 +1818,7 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t total_len; u_int8_t handshake_type; bool is_quic = (quic_version != 0); - bool is_dtls = packet->udp && (!is_quic); + bool is_dtls = (packet->udp && !is_quic) || flow->stun.maybe_dtls; #ifdef DEBUG_TLS printf("TLS %s() called\n", __FUNCTION__); @@ -2964,7 +2967,7 @@ static void ndpi_search_tls_wrapper(struct ndpi_detection_module_struct *ndpi_st flow->protos.tls_quic.ssl_version); #endif - if(packet->udp != NULL) + if(packet->udp != NULL || flow->stun.maybe_dtls) ndpi_search_tls_udp(ndpi_struct, flow); else ndpi_search_tls_tcp(ndpi_struct, flow); |