diff options
Diffstat (limited to 'src/lib/protocols')
-rw-r--r-- | src/lib/protocols/rtp.c | 2 | ||||
-rw-r--r-- | src/lib/protocols/stun.c | 78 | ||||
-rw-r--r-- | src/lib/protocols/telegram.c | 8 |
3 files changed, 81 insertions, 7 deletions
diff --git a/src/lib/protocols/rtp.c b/src/lib/protocols/rtp.c index 5a27d887b..f859aba4e 100644 --- a/src/lib/protocols/rtp.c +++ b/src/lib/protocols/rtp.c @@ -269,7 +269,7 @@ static void ndpi_int_rtp_add_connection(struct ndpi_detection_module_struct *ndp from the beginning */ if(!(flow->l4_proto == IPPROTO_TCP && ndpi_seen_flow_beginning(flow))) { NDPI_LOG_DBG(ndpi_struct, "Enabling (STUN) extra dissection\n"); - switch_extra_dissection_to_stun(ndpi_struct, flow); + switch_extra_dissection_to_stun(ndpi_struct, flow, 1); } } } diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c index 515a4ba8c..4ffb5568c 100644 --- a/src/lib/protocols/stun.c +++ b/src/lib/protocols/stun.c @@ -61,7 +61,8 @@ static int stun_search_again(struct ndpi_detection_module_struct *ndpi_struct, /* Valid classifications: - * STUN, DTLS, STUN/RTP, DTLS/SRTP, RTP or RTCP (the last two, only from RTP dissector) + * STUN, DTLS, STUN/RTP, DTLS/SRTP, RTP or RTCP (only from RTP dissector) + and TELEGRAM (only from Telegram dissector, note that TELEGRAM != TELEGRAM_VOIP!!) * STUN/APP, DTLS/APP, SRTP/APP ["real" sub-classification] The idea is: * the specific "real" application (WA/FB/Signal/...), if present, should @@ -79,7 +80,8 @@ static int is_subclassification_real_by_proto(u_int16_t proto) proto == NDPI_PROTOCOL_RTP || proto == NDPI_PROTOCOL_RTCP || proto == NDPI_PROTOCOL_SRTP || - proto == NDPI_PROTOCOL_DTLS) + proto == NDPI_PROTOCOL_DTLS || + proto == NDPI_PROTOCOL_TELEGRAM) return 0; return 1; } @@ -493,6 +495,9 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct, *app_proto = NDPI_PROTOCOL_SIGNAL_VOIP; } + if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_TELEGRAM) + *app_proto = NDPI_PROTOCOL_TELEGRAM_VOIP; + off = STUN_HDR_LEN; while(off + 4 < payload_length) { u_int16_t attribute = ntohs(*((u_int16_t *)&payload[off])); @@ -783,7 +788,8 @@ static u_int32_t __get_master(struct ndpi_flow_struct *flow) { if(flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN) return flow->detected_protocol_stack[1]; - if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) + if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN && + flow->detected_protocol_stack[0] != NDPI_PROTOCOL_TELEGRAM) return flow->detected_protocol_stack[0]; return NDPI_PROTOCOL_STUN; } @@ -1039,6 +1045,62 @@ static int stun_search_again(struct ndpi_detection_module_struct *ndpi_struct, /* ************************************************************ */ +static int stun_telegram_search_again(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow) +{ + struct ndpi_packet_struct *packet = &ndpi_struct->packet; + const u_int8_t *orig_payload; + u_int16_t orig_payload_length; + char pattern[12] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + u_int16_t length; + + NDPI_LOG_DBG2(ndpi_struct, "[T] Packet counter %d protos %d/%d Monitoring? %d\n", + flow->packet_counter, + flow->detected_protocol_stack[0], flow->detected_protocol_stack[1], + flow->monitoring); + + /* For SOME of its STUN flows, Telegram uses a custom encapsulation + There is no documentation. It seems: + * some unknown packets (especially at the beginning/end of the flow) have a bunch of 0xFF + * the other packets encapsulate standard STUN/DTLS/RTP payload at offset 24 + (with a previous field containing the payload length) + */ + + if(packet->payload_packet_len <= 28) { + NDPI_LOG_DBG(ndpi_struct, "Malformed custom Telegram packet (too short)\n"); + return keep_extra_dissection(ndpi_struct, flow); + } + + if(memcmp(&packet->payload[16], pattern, sizeof(pattern)) == 0) { + NDPI_LOG_DBG(ndpi_struct, "Custom/Unknown Telegram packet\n"); + return keep_extra_dissection(ndpi_struct, flow); + } + + /* It should be STUN/DTLS/RTP */ + + length = ntohs(*(u_int16_t *)&packet->payload[22]); + if(24 + length > packet->payload_packet_len) { + NDPI_LOG_DBG(ndpi_struct, "Malformed custom Telegram packet (too long: %d %d)\n", + length, packet->payload_packet_len); + return keep_extra_dissection(ndpi_struct, flow); + } + + orig_payload = packet->payload; + orig_payload_length = packet->payload_packet_len ; + packet->payload = packet->payload + 24; + packet->payload_packet_len = length; + + stun_search_again(ndpi_struct, flow); + + packet->payload = orig_payload; + packet->payload_packet_len = orig_payload_length; + + return keep_extra_dissection(ndpi_struct, flow); +} + +/* ************************************************************ */ + static u_int64_t get_stun_lru_key(struct ndpi_flow_struct *flow, u_int8_t rev) { if(rev) { if(flow->is_ipv6) @@ -1150,19 +1212,23 @@ static void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *nd } } - switch_extra_dissection_to_stun(ndpi_struct, flow); + switch_extra_dissection_to_stun(ndpi_struct, flow, 1); } /* ************************************************************ */ void switch_extra_dissection_to_stun(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_flow_struct *flow) + struct ndpi_flow_struct *flow, + int std_callback) { if(!flow->extra_packets_func) { if(keep_extra_dissection(ndpi_struct, flow)) { NDPI_LOG_DBG(ndpi_struct, "Enabling extra dissection\n"); flow->max_extra_packets_to_check = ndpi_struct->cfg.stun_max_packets_extra_dissection; - flow->extra_packets_func = stun_search_again; + if(std_callback) + flow->extra_packets_func = stun_search_again; + else + flow->extra_packets_func = stun_telegram_search_again; } } } diff --git a/src/lib/protocols/telegram.c b/src/lib/protocols/telegram.c index 23f7cca51..affeede36 100644 --- a/src/lib/protocols/telegram.c +++ b/src/lib/protocols/telegram.c @@ -93,6 +93,14 @@ static void ndpi_search_telegram(struct ndpi_detection_module_struct *ndpi_struc if(found == 12) { ndpi_int_telegram_add_connection(ndpi_struct, flow, NDPI_CONFIDENCE_DPI); + /* It seems this kind of traffic is used: + * for "normal" stuff (at least years ago... and now? TODO) + * for calls, as a custom encapsulation of STUN/DTLS/RTP packets + Since we are not able to tell the former from the latter, always + switch to STUN dissection. If we find STUN/DTLS/RTP stuff we will + update the classification to something like STUN/Telegram_voip, + otherwise it will remain Telegram */ + switch_extra_dissection_to_stun(ndpi_struct, flow, 0); return; } } |