From c6d09df8846e6566d7d11b471732d11e15f8b93f Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Tue, 19 May 2015 08:14:33 +0200 Subject: Skype test files --- tests/pcap/skype.pcap | Bin 0 -> 699646 bytes tests/pcap/skype_no_unknown.pcap | Bin 0 -> 526100 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/pcap/skype.pcap create mode 100644 tests/pcap/skype_no_unknown.pcap (limited to 'tests') diff --git a/tests/pcap/skype.pcap b/tests/pcap/skype.pcap new file mode 100644 index 000000000..d8c85f508 Binary files /dev/null and b/tests/pcap/skype.pcap differ diff --git a/tests/pcap/skype_no_unknown.pcap b/tests/pcap/skype_no_unknown.pcap new file mode 100644 index 000000000..5266bca6f Binary files /dev/null and b/tests/pcap/skype_no_unknown.pcap differ -- cgit v1.2.3 From 993665726aa807ff64ca28776af6aee43b19b66d Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Tue, 19 May 2015 12:30:44 +0200 Subject: Fixed bug that prevented (due to endianess) to properly match hosts Added tests for skype detection --- src/lib/ndpi_content_match.c.inc | 7 +++++-- src/lib/ndpi_main.c | 4 +++- tests/result/skype.pcap.out | 13 +++++++++++++ tests/result/skype_no_unknown.pcap.out | 11 +++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 tests/result/skype.pcap.out create mode 100644 tests/result/skype_no_unknown.pcap.out (limited to 'tests') diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc index 3b4693fc3..1a7f8eef6 100644 --- a/src/lib/ndpi_content_match.c.inc +++ b/src/lib/ndpi_content_match.c.inc @@ -72,12 +72,14 @@ static ndpi_network host_protocol_list[] = { { 0x6CA0A000 /* 108.160.160.0 */, 20, NDPI_PROTOCOL_DROPBOX }, /* - Skype + Skype (Microsoft CDN) 157.56.0.0/14, 157.60.0.0/16, 157.54.0.0/15 + 111.221.64.0 - 111.221.127.255 */ { 0x9D380000 /* 157.56.0.0 */, 14, NDPI_PROTOCOL_SKYPE }, { 0x9D3C0000 /* 157.60.0.0 */, 16, NDPI_PROTOCOL_SKYPE }, - { 0x9D360000 /* 157.54.0.0/ */, 15, NDPI_PROTOCOL_SKYPE }, + { 0x9D360000 /* 157.54.0.0 */, 15, NDPI_PROTOCOL_SKYPE }, + { 0x6FDD4000 /* 111.221.64.0 */, 18, NDPI_PROTOCOL_SKYPE }, /* Google @@ -258,6 +260,7 @@ static ndpi_network host_protocol_list[] = { { 0xD820F200, 24, NDPI_PROTOCOL_SKYPE }, { 0xD821F000, 22, NDPI_PROTOCOL_SKYPE }, { 0xD4A10800, 24, NDPI_PROTOCOL_SKYPE }, + { 0x012A1231, 32, NDPI_PROTOCOL_TOR }, { 0x01E69FA1, 32, NDPI_PROTOCOL_TOR }, { 0x020DE985, 32, NDPI_PROTOCOL_TOR }, diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 7719f766e..8d39d8115 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1677,6 +1677,7 @@ static int fill_prefix_v4(prefix_t *p, struct in_addr *a, int b, int mb) { if(b < 0 || b > mb) return(-1); + memset(p, 0, sizeof(prefix_t)); memcpy(&p->add.sin, a, (mb+7)/8); p->family = AF_INET; p->bitlen = b; @@ -1692,6 +1693,7 @@ u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_str prefix_t prefix; patricia_node_t *node; + pin->s_addr = ntohl(pin->s_addr); /* Make sure all in network byte order otherwise compares wont work */ fill_prefix_v4(&prefix, pin, 32, ((patricia_tree_t*)ndpi_struct->protocols_ptree)->maxbits); node = ndpi_patricia_search_best(ndpi_struct->protocols_ptree, &prefix); @@ -1755,7 +1757,7 @@ static void ndpi_init_ptree_ipv4(struct ndpi_detection_module_struct *ndpi_str, struct in_addr pin; patricia_node_t *node; - pin.s_addr = host_list[i].network; + pin.s_addr = ntohl(host_list[i].network); if((node = add_to_ptree(ptree, AF_INET, &pin, host_list[i].cidr /* bits */)) != NULL) node->value.user_value = host_list[i].value; } diff --git a/tests/result/skype.pcap.out b/tests/result/skype.pcap.out new file mode 100644 index 000000000..404442549 --- /dev/null +++ b/tests/result/skype.pcap.out @@ -0,0 +1,13 @@ +Unknown 409 49221 18 +DNS 8 807 4 +MDNS 8 1736 2 +NTP 2 180 1 +SSDP 101 38156 6 +ICMP 8 656 1 +IGMP 5 258 4 +SSL 20 1516 1 +DropBox 38 17948 5 +Skype 2362 501011 246 +Apple 15 2045 2 +AppleiCloud 88 20520 2 +Spotify 5 430 1 diff --git a/tests/result/skype_no_unknown.pcap.out b/tests/result/skype_no_unknown.pcap.out new file mode 100644 index 000000000..2b6435897 --- /dev/null +++ b/tests/result/skype_no_unknown.pcap.out @@ -0,0 +1,11 @@ +Unknown 241 60170 16 +DNS 6 627 3 +MDNS 3 400 2 +NetBIOS 22 3106 7 +SSDP 40 14100 3 +ICMP 4 328 1 +IGMP 4 226 4 +SSL 22 1444 3 +DropBox 16 7342 5 +Skype 1637 379382 221 +Apple 84 20699 2 -- cgit v1.2.3 From 8f3b8ff4dfb5b7674b6d87c78c1bdb275f178d4d Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 20 May 2015 09:27:04 +0200 Subject: Added fix to harden quic detection and limit it to port 80/443 UDP --- src/lib/protocols/quic.c | 193 +++++++++++++++++++++++---------------------- tests/do.sh | 5 +- tests/result/quic.pcap.out | 2 +- 3 files changed, 105 insertions(+), 95 deletions(-) (limited to 'tests') diff --git a/src/lib/protocols/quic.c b/src/lib/protocols/quic.c index 2e1ad6628..cbc95519d 100644 --- a/src/lib/protocols/quic.c +++ b/src/lib/protocols/quic.c @@ -46,111 +46,118 @@ static void ndpi_int_quic_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { - ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_QUIC, NDPI_REAL_PROTOCOL); + ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_QUIC, NDPI_REAL_PROTOCOL); } int connect_id(const unsigned char pflags) { - u_int cid_len; + u_int cid_len; - // Check CID length. - switch (pflags & QUIC_CID_MASK) - { - case CID_LEN_8: cid_len = 8; break; - case CID_LEN_4: cid_len = 4; break; - case CID_LEN_1: cid_len = 1; break; - case CID_LEN_0: cid_len = 0; break; - default: - return -1; - - } - // Return offset. - return cid_len + 1; + // Check CID length. + switch (pflags & QUIC_CID_MASK) + { + case CID_LEN_8: cid_len = 8; break; + case CID_LEN_4: cid_len = 4; break; + case CID_LEN_1: cid_len = 1; break; + case CID_LEN_0: cid_len = 0; break; + default: + return -1; + + } + // Return offset. + return cid_len + 1; } int sequence(const unsigned char *payload) { - unsigned char conv[6] = {0}; - u_int seq_value = -1; - u_int seq_lens; - u_int cid_offs; - int i; - - // Search SEQ bytes length. - switch (payload[0] & QUIC_SEQ_MASK) - { - case SEQ_LEN_6: seq_lens = 6; break; - case SEQ_LEN_4: seq_lens = 4; break; - case SEQ_LEN_2: seq_lens = 2; break; - case SEQ_LEN_1: seq_lens = 1; break; - default: - return -1; - } - // Retrieve SEQ offset. - cid_offs = connect_id(payload[0]); - - if (cid_offs >= 0 && seq_lens > 0) - { - for (i = 0; i < seq_lens; i++) - conv[i] = payload[cid_offs + i]; - - seq_value = SEQ_CONV(conv); - } - // Return SEQ dec value; - return seq_value; + unsigned char conv[6] = {0}; + u_int seq_value = -1; + u_int seq_lens; + u_int cid_offs; + int i; + + // Search SEQ bytes length. + switch (payload[0] & QUIC_SEQ_MASK) + { + case SEQ_LEN_6: seq_lens = 6; break; + case SEQ_LEN_4: seq_lens = 4; break; + case SEQ_LEN_2: seq_lens = 2; break; + case SEQ_LEN_1: seq_lens = 1; break; + default: + return -1; + } + // Retrieve SEQ offset. + cid_offs = connect_id(payload[0]); + + if (cid_offs >= 0 && seq_lens > 0) + { + for (i = 0; i < seq_lens; i++) + conv[i] = payload[cid_offs + i]; + + seq_value = SEQ_CONV(conv); + } + // Return SEQ dec value; + return seq_value; } void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { - struct ndpi_packet_struct *packet = &flow->packet; - u_int ver_offs; - - if(packet->udp != NULL) { - NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "calculating quic over udp.\n"); - - // Settings without version. First check if PUBLIC FLAGS & SEQ bytes are 0x0. SEQ must be 1 at least. - if ((packet->payload[0] == 0x00 && packet->payload[1] != 0x00) || ((packet->payload[0] & QUIC_NO_V_RES_RSV) == 0)) - { - if (sequence(packet->payload) < 1) - { - - NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "exclude quic.\n"); - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_QUIC); - } - - NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "found quic.\n"); - ndpi_int_quic_add_connection(ndpi_struct, flow); - } - - // Check if version, than the CID length. - else if (packet->payload[0] & QUIC_VER_MASK) - { - // Skip CID length. - ver_offs = connect_id(packet->payload[0]); - - if (ver_offs >= 0){ - unsigned char vers[] = {packet->payload[ver_offs], packet->payload[ver_offs + 1], - packet->payload[ver_offs + 2], packet->payload[ver_offs + 3]}; - - // Version Match. - if (vers[0] == 'Q' && vers[1] == '0' && - (vers[2] == '2' && (vers[3] == '5' || vers[3] == '4' || vers[3] == '3' || vers[3] == '2' || - vers[3] == '1' || vers[3] == '0')) || - (vers[2] == '1' && (vers[3] == '9' || vers[3] == '8' || vers[3] == '7' || vers[3] == '6' || - vers[3] == '5' || vers[3] == '4' || vers[3] == '3' || vers[3] == '2' || - vers[3] == '1' || vers[3] == '0')) || - (vers[2] == '0' && vers[3] == '9')) - - { - NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "found quic.\n"); - ndpi_int_quic_add_connection(ndpi_struct, flow); - } - } - } else - { - NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "exclude quic.\n"); - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_QUIC); - } - } + struct ndpi_packet_struct *packet = &flow->packet; + u_int ver_offs; + + if(packet->udp != NULL) { + u_int16_t sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest); + + NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "calculating quic over udp.\n"); + + if(((packet->payload[0] & 0xF0) != 0) + || (!(sport == 80 || dport == 80 || sport == 443 || dport == 443))) + goto exclude_quic; + + // Settings without version. First check if PUBLIC FLAGS & SEQ bytes are 0x0. SEQ must be 1 at least. + if ((packet->payload[0] == 0x00 && packet->payload[1] != 0x00) || ((packet->payload[0] & QUIC_NO_V_RES_RSV) == 0)) + { + if (sequence(packet->payload) < 1) + { + + NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "exclude quic.\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_QUIC); + } + + NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "found quic.\n"); + ndpi_int_quic_add_connection(ndpi_struct, flow); + } + + // Check if version, than the CID length. + else if (packet->payload[0] & QUIC_VER_MASK) + { + // Skip CID length. + ver_offs = connect_id(packet->payload[0]); + + if (ver_offs >= 0){ + unsigned char vers[] = {packet->payload[ver_offs], packet->payload[ver_offs + 1], + packet->payload[ver_offs + 2], packet->payload[ver_offs + 3]}; + + // Version Match. + if (vers[0] == 'Q' && vers[1] == '0' && + (vers[2] == '2' && (vers[3] == '5' || vers[3] == '4' || vers[3] == '3' || vers[3] == '2' || + vers[3] == '1' || vers[3] == '0')) || + (vers[2] == '1' && (vers[3] == '9' || vers[3] == '8' || vers[3] == '7' || vers[3] == '6' || + vers[3] == '5' || vers[3] == '4' || vers[3] == '3' || vers[3] == '2' || + vers[3] == '1' || vers[3] == '0')) || + (vers[2] == '0' && vers[3] == '9')) + + { + NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "found quic.\n"); + ndpi_int_quic_add_connection(ndpi_struct, flow); + } + } + } else + { + exclude_quic: + NDPI_LOG(NDPI_PROTOCOL_QUIC, ndpi_struct, NDPI_LOG_DEBUG, "exclude quic.\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_QUIC); + } + } } #endif diff --git a/tests/do.sh b/tests/do.sh index 4f81906f7..e7d28aa9c 100755 --- a/tests/do.sh +++ b/tests/do.sh @@ -15,13 +15,16 @@ build_results() { check_results() { for f in $PCAPS; do if [ -f result/$f.out ]; then - $READER -q -i pcap/$f -w /tmp/reader.out + CMD="$READER -q -i pcap/$f -w /tmp/reader.out" + $CMD NUM_DIFF=`diff result/$f.out /tmp/reader.out | wc -l` if [ $NUM_DIFF -eq 0 ]; then echo "$f\t OK" else echo "$f\t ERROR" + echo "$CMD" + diff result/$f.out /tmp/reader.out fi /bin/rm /tmp/reader.out diff --git a/tests/result/quic.pcap.out b/tests/result/quic.pcap.out index 283fb04d2..900864e4d 100644 --- a/tests/result/quic.pcap.out +++ b/tests/result/quic.pcap.out @@ -1 +1 @@ -Unknown 413 254874 1 +Quic 413 254874 1 -- cgit v1.2.3