diff options
author | Luca <deri@ntop.org> | 2019-07-29 16:28:56 +0200 |
---|---|---|
committer | Luca <deri@ntop.org> | 2019-07-29 16:28:56 +0200 |
commit | a0be9ea63951978b6add9172d575bbdec3d11c9e (patch) | |
tree | 908aba63cccabdcb5223f4dbe72a71348c30cbc4 | |
parent | fbe87ed6407830403173e177142d4858c583be3b (diff) |
Fixed wrong detection of RTP as WhatsApp voice
-rw-r--r-- | src/lib/protocols/rtp.c | 107 | ||||
-rw-r--r-- | tests/result/whatsapp_login_call.pcap.out | 8 |
2 files changed, 58 insertions, 57 deletions
diff --git a/src/lib/protocols/rtp.c b/src/lib/protocols/rtp.c index bd0179287..90b73ab1e 100644 --- a/src/lib/protocols/rtp.c +++ b/src/lib/protocols/rtp.c @@ -58,14 +58,14 @@ static u_int8_t isValidMSRTPType(u_int8_t payloadType) { case 127: /* x-data */ return(1 /* RTP */); break; - + case 200: /* RTCP PACKET SENDER */ case 201: /* RTCP PACKET RECEIVER */ case 202: /* RTCP Source Description */ case 203: /* RTCP Bye */ return(2 /* RTCP */); break; - + default: return(0); } @@ -78,8 +78,10 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct, const u_int8_t * payload, const u_int16_t payload_len) { NDPI_LOG_DBG(ndpi_struct, "search RTP\n"); - if (payload_len < 2) + if((payload_len < 2) || flow->protos.stun_ssl.stun.num_binding_requests) { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); return; + } //struct ndpi_packet_struct *packet = &flow->packet; u_int8_t payloadType, payload_type = payload[1] & 0x7F; @@ -91,17 +93,17 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct, && ((payload_type <= 34) || ((payload_type >= 96) && (payload_type <= 127)) /* http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */ - ) - ) { + ) + ) { struct ndpi_packet_struct *packet = &flow->packet; - + if(packet->iph) { /* 125.209.252.xxx */ if(((ntohl(packet->iph->saddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00) || ((ntohl(packet->iph->daddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00)) { if((flow->packet.payload[0] == 0x80) && ((flow->packet.payload[1] == 0x78) || (flow->packet.payload[1] == 0xE8)) - ) { + ) { ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_LINE, NDPI_PROTOCOL_LINE); return; } @@ -112,7 +114,7 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct, ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_RTP, NDPI_PROTOCOL_UNKNOWN); return; } else if((payload_len >= 12) - && (((payload[0] & 0xFF) == 0x80) || ((payload[0] & 0xFF) == 0xA0)) /* RTP magic byte[1] */ + && (((payload[0] & 0xFF) == 0x80) || ((payload[0] & 0xFF) == 0xA0)) /* RTP magic byte[1] */ && (payloadType = isValidMSRTPType(payload[1] & 0xFF))) { if(payloadType == 1 /* RTP */) { NDPI_LOG_INFO(ndpi_struct, "Found Skype for Business (former MS Lync)\n"); @@ -126,7 +128,7 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct, return; #endif } - } + } /* No luck this time */ NDPI_EXCLUDE_PROTO(ndpi_struct, flow); @@ -139,7 +141,7 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd struct ndpi_packet_struct *packet = &flow->packet; /* printf("*** %s(pkt=%d)\n", __FUNCTION__, flow->packet_counter); */ - + if((packet->udp != NULL) /* && (ntohs(packet->udp->source) > 1023) */ && (ntohs(packet->udp->dest) > 1023)) @@ -204,14 +206,14 @@ u_int16_t update_seq(struct ndpi_detection_module_struct *ndpi_struct, struct nd u_int16_t delta = seq - flow->rtp_seqnum[direction]; - if (delta < RTP_MAX_OUT_OF_ORDER) { /* in order, with permissible gap */ + if(delta < RTP_MAX_OUT_OF_ORDER) { /* in order, with permissible gap */ flow->rtp_seqnum[direction] = seq; NDPI_LOG_DBG(ndpi_struct, "rtp_seqnum[%u] = %u (increased by %u)\n", - direction, seq, delta); + direction, seq, delta); return delta; } else { NDPI_LOG_DBG(ndpi_struct, "retransmission (dir %u, seqnum %u)\n", - direction, seq); + direction, seq); return 0; } } @@ -227,51 +229,51 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct, NDPI_LOG_DBG(ndpi_struct, "search rtp\n"); - if (payload_len == 4 && get_u_int32_t(packet->payload, 0) == 0 && flow->packet_counter < 8) { + if(payload_len == 4 && get_u_int32_t(packet->payload, 0) == 0 && flow->packet_counter < 8) { NDPI_LOG_DBG(ndpi_struct, "need next packet, maybe ClearSea out calls\n"); return; } - if (payload_len == 5 && memcmp(payload, "hello", 5) == 0) { + if(payload_len == 5 && memcmp(payload, "hello", 5) == 0) { NDPI_LOG_DBG(ndpi_struct, - "need next packet, initial hello packet of SIP out calls.\n"); + "need next packet, initial hello packet of SIP out calls.\n"); return; } - if (payload_len == 1 && payload[0] == 0) { + if(payload_len == 1 && payload[0] == 0) { NDPI_LOG_DBG(ndpi_struct, - "need next packet, payload_packet_len == 1 && payload[0] == 0.\n"); + "need next packet, payload_packet_len == 1 && payload[0] == 0.\n"); return; } - if (payload_len == 3 && memcmp(payload, "png", 3) == 0) { + if(payload_len == 3 && memcmp(payload, "png", 3) == 0) { /* weird packet found in Ninja GlobalIP trace */ NDPI_LOG_DBG(ndpi_struct, "skipping packet with len = 3 and png payload\n"); return; } - if (payload_len < 12) { + if(payload_len < 12) { NDPI_LOG_DBG(ndpi_struct, "minimal packet size for rtp packets: 12\n"); goto exclude_rtp; } - if (payload_len == 12 && get_u_int32_t(payload, 0) == 0 && get_u_int32_t(payload, 4) == 0 && get_u_int32_t(payload, 8) == 0) { + if(payload_len == 12 && get_u_int32_t(payload, 0) == 0 && get_u_int32_t(payload, 4) == 0 && get_u_int32_t(payload, 8) == 0) { NDPI_LOG_DBG(ndpi_struct, "skipping packet with len = 12 and only 0-bytes\n"); return; } - if ((payload[0] & 0xc0) == 0xc0 || (payload[0] & 0xc0) == 0x40 || (payload[0] & 0xc0) == 0x00) { + if((payload[0] & 0xc0) == 0xc0 || (payload[0] & 0xc0) == 0x40 || (payload[0] & 0xc0) == 0x00) { NDPI_LOG_DBG(ndpi_struct, "version = 3 || 1 || 0, maybe first rtp packet\n"); return; } - if ((payload[0] & 0xc0) != 0x80) { + if((payload[0] & 0xc0) != 0x80) { NDPI_LOG_DBG(ndpi_struct, "rtp version must be 2, first two bits of a packets must be 10\n"); goto exclude_rtp; } /* rtp_payload_type are the last seven bits of the second byte */ - if (flow->rtp_payload_type[packet->packet_direction] != (payload[1] & 0x7F)) { + if(flow->rtp_payload_type[packet->packet_direction] != (payload[1] & 0x7F)) { NDPI_LOG_DBG(ndpi_struct, "payload_type has changed, reset stages\n"); packet->packet_direction == 0 ? (flow->rtp_stage1 = 0) : (flow->rtp_stage2 = 0); } @@ -280,56 +282,56 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct, stage = (packet->packet_direction == 0 ? flow->rtp_stage1 : flow->rtp_stage2); - if (stage > 0) { + if(stage > 0) { NDPI_LOG_DBG(ndpi_struct, "stage = %u\n", packet->packet_direction == 0 ? flow->rtp_stage1 : flow->rtp_stage2); - if (flow->rtp_ssid[packet->packet_direction] != get_u_int32_t(payload, 8)) { + if(flow->rtp_ssid[packet->packet_direction] != get_u_int32_t(payload, 8)) { NDPI_LOG_DBG(ndpi_struct, "ssid has changed, goto exclude rtp\n"); goto exclude_rtp; } - if (seqnum == flow->rtp_seqnum[packet->packet_direction]) { + if(seqnum == flow->rtp_seqnum[packet->packet_direction]) { NDPI_LOG_DBG(ndpi_struct, "maybe \"retransmission\", need next packet\n"); return; - } else if ((u_int16_t) (seqnum - flow->rtp_seqnum[packet->packet_direction]) < RTP_MAX_OUT_OF_ORDER) { + } else if((u_int16_t) (seqnum - flow->rtp_seqnum[packet->packet_direction]) < RTP_MAX_OUT_OF_ORDER) { NDPI_LOG_DBG(ndpi_struct, - "new packet has larger sequence number (within valid range)\n"); + "new packet has larger sequence number (within valid range)\n"); update_seq(ndpi_struct, flow, packet->packet_direction, seqnum); - } else if ((u_int16_t) (flow->rtp_seqnum[packet->packet_direction] - seqnum) < RTP_MAX_OUT_OF_ORDER) { + } else if((u_int16_t) (flow->rtp_seqnum[packet->packet_direction] - seqnum) < RTP_MAX_OUT_OF_ORDER) { NDPI_LOG_DBG(ndpi_struct, - "new packet has smaller sequence number (within valid range)\n"); + "new packet has smaller sequence number (within valid range)\n"); init_seq(ndpi_struct, flow, packet->packet_direction, seqnum, 1); } else { NDPI_LOG_DBG(ndpi_struct, - "sequence number diff is too big, goto exclude rtp.\n"); + "sequence number diff is too big, goto exclude rtp.\n"); goto exclude_rtp; } } else { NDPI_LOG_DBG(ndpi_struct, "rtp_ssid[%u] = %u\n", packet->packet_direction, - flow->rtp_ssid[packet->packet_direction]); + flow->rtp_ssid[packet->packet_direction]); flow->rtp_ssid[packet->packet_direction] = get_u_int32_t(payload, 8); - if (flow->packet_counter < 3) { + if(flow->packet_counter < 3) { NDPI_LOG_DBG(ndpi_struct, "packet_counter < 3, need next packet\n"); } init_seq(ndpi_struct, flow, packet->packet_direction, seqnum, 1); } - if (seqnum <= 3) { + if(seqnum <= 3) { NDPI_LOG_DBG(ndpi_struct, "sequence_number = %u, too small, need next packet, return\n", seqnum); return; } - if (stage == 3) { + if(stage == 3) { NDPI_LOG_DBG(ndpi_struct, "add connection I\n"); ndpi_int_rtp_add_connection(ndpi_struct, flow); } else { packet->packet_direction == 0 ? flow->rtp_stage1++ : flow->rtp_stage2++; NDPI_LOG_DBG(ndpi_struct, "stage[%u]++; need next packet\n", - packet->packet_direction); + packet->packet_direction); } return; - exclude_rtp: - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN - || /* packet->real_protocol_read_only == NDPI_PROTOCOL_STUN */) { +exclude_rtp: + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN + || /* packet->real_protocol_read_only == NDPI_PROTOCOL_STUN */) { NDPI_LOG_DBG(ndpi_struct, "STUN: is detected, need next packet\n"); return; } @@ -344,17 +346,17 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd struct ndpi_packet_struct *packet = &flow->packet; - if (packet->udp) { + if(packet->udp) { ndpi_rtp_search(ndpi_struct, flow, packet->payload, packet->payload_packet_len); - } else if (packet->tcp) { + } else if(packet->tcp) { /* skip special packets seen at yahoo traces */ - if (packet->payload_packet_len >= 20 && ntohs(get_u_int16_t(packet->payload, 2)) + 20 == packet->payload_packet_len && - packet->payload[0] == 0x90 && packet->payload[1] >= 0x01 && packet->payload[1] <= 0x07) { - if (flow->packet_counter == 2) + if(packet->payload_packet_len >= 20 && ntohs(get_u_int16_t(packet->payload, 2)) + 20 == packet->payload_packet_len && + packet->payload[0] == 0x90 && packet->payload[1] >= 0x01 && packet->payload[1] <= 0x07) { + if(flow->packet_counter == 2) flow->l4.tcp.rtp_special_packets_seen = 1; NDPI_LOG_DBG(ndpi_struct, - "skipping STUN-like, special yahoo packets with payload[0] == 0x90.\n"); + "skipping STUN-like, special yahoo packets with payload[0] == 0x90.\n"); return; } @@ -365,12 +367,12 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd * we can remove this restriction */ - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN - || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_RTP) { + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN + || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_RTP) { /* RTP may be encapsulated in TCP packets */ - if (packet->payload_packet_len >= 2 && ntohs(get_u_int16_t(packet->payload, 0)) + 2 == packet->payload_packet_len) { + if(packet->payload_packet_len >= 2 && ntohs(get_u_int16_t(packet->payload, 0)) + 2 == packet->payload_packet_len) { /* TODO there could be several RTP packets in a single TCP packet so maybe the detection could be * improved by checking only the RTP packet of given length */ @@ -381,9 +383,9 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd } } - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN && flow->l4.tcp.rtp_special_packets_seen == 1) { + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN && flow->l4.tcp.rtp_special_packets_seen == 1) { - if (packet->payload_packet_len >= 4 && ntohl(get_u_int32_t(packet->payload, 0)) + 4 == packet->payload_packet_len) { + if(packet->payload_packet_len >= 4 && ntohl(get_u_int32_t(packet->payload, 0)) + 4 == packet->payload_packet_len) { /* TODO there could be several RTP packets in a single TCP packet so maybe the detection could be * improved by checking only the RTP packet of given length */ @@ -394,7 +396,7 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd } } - if (NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct, flow, NDPI_PROTOCOL_STUN)) { + if(NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct, flow, NDPI_PROTOCOL_STUN)) { NDPI_EXCLUDE_PROTO(ndpi_struct, flow); } else { NDPI_LOG_DBG(ndpi_struct, "STUN not yet excluded, need next packet\n"); @@ -416,4 +418,3 @@ void init_rtp_dissector(struct ndpi_detection_module_struct *ndpi_struct, *id += 1; } - diff --git a/tests/result/whatsapp_login_call.pcap.out b/tests/result/whatsapp_login_call.pcap.out index 6c4676815..c9f716709 100644 --- a/tests/result/whatsapp_login_call.pcap.out +++ b/tests/result/whatsapp_login_call.pcap.out @@ -3,13 +3,13 @@ MDNS 8 952 4 DHCP 10 3420 1 STUN 27 2322 2 ICMP 10 700 1 -RTP 706 91156 4 +RTP 44 7818 2 SSL 8 589 2 Dropbox 4 2176 1 Apple 190 50263 21 WhatsApp 182 25154 2 Spotify 3 258 1 -WhatsAppVoice 70 9464 14 +WhatsAppVoice 732 92802 16 ApplePush 22 5926 1 JA3 Host Stats: @@ -17,8 +17,8 @@ JA3 Host Stats: 1 192.168.2.4 1 - 1 UDP 192.168.2.4:51518 <-> 91.253.176.65:9344 [proto: 87/RTP][cat: Media/1][186 pkts/27025 bytes <-> 278 pkts/25895 bytes][PLAIN TEXT (zTdFPOk)] - 2 UDP 192.168.2.4:52794 <-> 91.253.176.65:9665 [proto: 87/RTP][cat: Media/1][141 pkts/17530 bytes <-> 57 pkts/12888 bytes] + 1 UDP 192.168.2.4:51518 <-> 91.253.176.65:9344 [proto: 78.189/STUN.WhatsAppVoice][cat: VoIP/10][186 pkts/27025 bytes <-> 278 pkts/25895 bytes][PLAIN TEXT (zTdFPOk)] + 2 UDP 192.168.2.4:52794 <-> 91.253.176.65:9665 [proto: 78.189/STUN.WhatsAppVoice][cat: VoIP/10][141 pkts/17530 bytes <-> 57 pkts/12888 bytes] 3 TCP 192.168.2.4:49202 <-> 184.173.179.37:5222 [proto: 142/WhatsApp][cat: Chat/9][100 pkts/14711 bytes <-> 80 pkts/10163 bytes][PLAIN TEXT (iPhone)] 4 TCP 192.168.2.4:49204 <-> 17.173.66.102:443 [proto: 91.140/SSL.Apple][cat: Web/5][29 pkts/11770 bytes <-> 24 pkts/6612 bytes][TLSv1.2][JA3C: 799135475da362592a4be9199d258726][JA3S: c253ec3ad88e42f8da4032682892f9a0 (INSECURE)][Cipher: TLS_RSA_WITH_RC4_128_MD5] 5 TCP 192.168.2.4:49201 <-> 17.178.104.12:443 [proto: 91.140/SSL.Apple][cat: Web/5][21 pkts/7644 bytes <-> 17 pkts/9576 bytes][TLSv1.2][JA3C: 799135475da362592a4be9199d258726][server: *.ess.apple.com][JA3S: c253ec3ad88e42f8da4032682892f9a0 (INSECURE)][organization: Apple Inc.][Cipher: TLS_RSA_WITH_RC4_128_MD5] |