aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca <deri@ntop.org>2019-07-29 16:28:56 +0200
committerLuca <deri@ntop.org>2019-07-29 16:28:56 +0200
commita0be9ea63951978b6add9172d575bbdec3d11c9e (patch)
tree908aba63cccabdcb5223f4dbe72a71348c30cbc4
parentfbe87ed6407830403173e177142d4858c583be3b (diff)
Fixed wrong detection of RTP as WhatsApp voice
-rw-r--r--src/lib/protocols/rtp.c107
-rw-r--r--tests/result/whatsapp_login_call.pcap.out8
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]