aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Nardi <12729895+IvanNardi@users.noreply.github.com>2021-03-06 05:48:36 +0100
committerGitHub <noreply@github.com>2021-03-06 05:48:36 +0100
commitc50a8d4808bbe3f41cbe5e681e84a1eb52129cb1 (patch)
tree804fe8ad8b7a16437fff526095d952d027f017c2 /src
parent73e434857037898ca13c763dcb6d0deb18150042 (diff)
Add support for Snapchat voip calls (#1147)
* Add support for Snapchat voip calls Snapchat multiplexes some of its audio/video real time traffic with QUIC sessions. The peculiarity of these sessions is that they are Q046 and don't have any SNI. * Fix tests with libgcrypt disabled
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_protocol_ids.h1
-rw-r--r--src/lib/ndpi_main.c9
-rw-r--r--src/lib/protocols/quic.c68
3 files changed, 78 insertions, 0 deletions
diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h
index 58467770f..cbcde77af 100644
--- a/src/include/ndpi_protocol_ids.h
+++ b/src/include/ndpi_protocol_ids.h
@@ -283,6 +283,7 @@ typedef enum {
NDPI_PROTOCOL_ANYDESK = 252, /* Toni Uhlig <matzeton@googlemail.com> */
NDPI_PROTOCOL_SOAP = 253, /* Toni Uhlig <matzeton@googlemail.com> */
NDPI_PROTOCOL_APPLE_SIRI = 254, /* Zied Aouini <aouinizied@gmail.com> */
+ NDPI_PROTOCOL_SNAPCHAT_CALL = 255,
#ifdef CUSTOM_NDPI_PROTOCOLS
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index daf02f76a..a9c3c9665 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -1576,6 +1576,10 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
1 /* can_have_a_subprotocol */, no_master, no_master, "AppleSiri",
NDPI_PROTOCOL_CATEGORY_VIRTUAL_ASSISTANT, 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, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SNAPCHAT_CALL,
+ 0 /* can_have_a_subprotocol */, no_master, no_master, "SnapchatCall",
+ NDPI_PROTOCOL_CATEGORY_VOIP, 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"
@@ -7069,6 +7073,11 @@ uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str,
if(flow->extra_packets_func)
return(1);
break;
+
+ case NDPI_PROTOCOL_QUIC:
+ if(flow->extra_packets_func)
+ return(1);
+ break;
}
return(0);
diff --git a/src/lib/protocols/quic.c b/src/lib/protocols/quic.c
index dd3493064..437968df4 100644
--- a/src/lib/protocols/quic.c
+++ b/src/lib/protocols/quic.c
@@ -1382,6 +1382,65 @@ static int may_be_initial_pkt(struct ndpi_detection_module_struct *ndpi_struct,
/* ***************************************************************** */
+static int eval_extra_processing(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, u_int32_t version)
+{
+ /* For the time being we need extra processing only to detect Snapchat calls,
+ i.e. RTP/RTCP multiplxed with QUIC.
+ We noticed that Snapchat uses Q046, without any SNI */
+
+ if(version == V_Q046 &&
+ flow->protos.tls_quic_stun.tls_quic.client_requested_server_name[0] == '\0') {
+ NDPI_LOG_DBG2(ndpi_struct, "We have further work to do\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int is_valid_rtp_payload_type(uint8_t type)
+{
+ /* https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */
+ return type <= 34 || (type >= 96 && type <= 127);
+}
+
+static int ndpi_search_quic_extra(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* We are elaborating a packet following the initial CHLO/ClientHello.
+ Mutiplexing QUIC with RTP/RTCP should be quite generic, but
+ for the time being, we known only NDPI_PROTOCOL_SNAPCHAT_CALL having such behaviour */
+
+ NDPI_LOG_DBG(ndpi_struct, "search QUIC extra func\n");
+
+ /* If this packet is still a Q046 one we need to keep going */
+ if(packet->payload[0] & 0x40) {
+ NDPI_LOG_DBG(ndpi_struct, "Still QUIC\n");
+ return 1; /* Keep going */
+ }
+
+ NDPI_LOG_DBG2(ndpi_struct, "No more QUIC: nothing to do on QUIC side\n");
+ flow->extra_packets_func = NULL;
+
+ /* This might be a RTP/RTCP stream: let's check it */
+ /* TODO: the cleanest solution should be triggering the rtp/rtcp dissector, but
+ I have not been able to that that so I reimplemented a basic RTP/RTCP detection.*/
+ if((packet->payload[0] >> 6) == 2 && /* Version 2 */
+ packet->payload_packet_len > 1 &&
+ (packet->payload[1] == 201 || /* RTCP, Receiver Report */
+ packet->payload[1] == 200 || /* RTCP, Sender Report */
+ is_valid_rtp_payload_type(packet->payload[1] & 0x7F)) /* RTP */) {
+ NDPI_LOG_DBG(ndpi_struct, "Found RTP/RTCP over QUIC\n");
+ ndpi_int_change_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SNAPCHAT_CALL, NDPI_PROTOCOL_QUIC);
+ } else {
+ /* Unexpected traffic pattern: we should investigate it... */
+ NDPI_LOG_INFO(ndpi_struct, "To investigate...\n");
+ }
+
+ return 0;
+}
+
void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow)
{
@@ -1465,6 +1524,15 @@ void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct,
if(is_version_with_encrypted_header(version)) {
ndpi_free(clear_payload);
}
+
+ /*
+ * 7) We need to process other packets than ClientHello/CHLO?
+ */
+ if(eval_extra_processing(ndpi_struct, flow, version)) {
+ flow->check_extra_packets = 1;
+ flow->max_extra_packets_to_check = 24; /* TODO */
+ flow->extra_packets_func = ndpi_search_quic_extra;
+ }
}
/* ***************************************************************** */