Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/include/ndpi_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ int search_into_bittorrent_cache(struct ndpi_detection_module_struct *ndpi_struc
int is_stun(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int16_t *app_proto);
void switch_extra_dissection_to_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
void switch_extra_dissection_to_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, int std_callback);

/* TPKT */
int tpkt_verify_hdr(const struct ndpi_packet_struct * const packet);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/protocols/rtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
78 changes: 72 additions & 6 deletions src/lib/protocols/stun.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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]));
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/lib/protocols/telegram.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
Loading
Loading