From 66d4afb3d6f271bee5a37ea2ef58c5239300b1a7 Mon Sep 17 00:00:00 2001 From: lns Date: Thu, 16 Jun 2022 16:06:11 +0200 Subject: [PATCH] Added collectd dissector (again). Signed-off-by: lns --- example/reader_util.c | 11 +- src/include/ndpi_protocol_ids.h | 1 + src/include/ndpi_protocols.h | 1 + src/include/ndpi_typedefs.h | 6 +- src/lib/ndpi_main.c | 13 +- src/lib/protocols/collectd.c | 210 ++++++++++++++++++++++++++++++++ tests/pcap/collectd.pcap | Bin 0 -> 112232 bytes tests/result/collectd.pcap.out | 16 +++ tests/result/synscan.pcap.out | 4 +- 9 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 src/lib/protocols/collectd.c create mode 100644 tests/pcap/collectd.pcap create mode 100644 tests/result/collectd.pcap.out diff --git a/example/reader_util.c b/example/reader_util.c index 800305b456a..c50c3281f80 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -1140,7 +1140,16 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl ndpi_snprintf(flow->http.content_type, sizeof(flow->http.content_type), "%s", flow->ndpi_flow->http.content_type ? flow->ndpi_flow->http.content_type : ""); ndpi_snprintf(flow->http.request_content_type, sizeof(flow->http.request_content_type), "%s", flow->ndpi_flow->http.request_content_type ? flow->ndpi_flow->http.request_content_type : ""); } - } else if(is_ndpi_proto(flow, NDPI_PROTOCOL_TELNET)) { + } + /* COLLECTD */ + else if(is_ndpi_proto(flow, NDPI_PROTOCOL_COLLECTD)) { + flow->info_type = INFO_GENERIC; + if(flow->ndpi_flow->protos.collectd.client_username[0] != '\0') + ndpi_snprintf(flow->info, sizeof(flow->info), "Username: %s", + flow->ndpi_flow->protos.collectd.client_username); + } + /* TELNET */ + else if(is_ndpi_proto(flow, NDPI_PROTOCOL_TELNET)) { if(flow->ndpi_flow->protos.telnet.username[0] != '\0') flow->telnet.username = ndpi_strdup(flow->ndpi_flow->protos.telnet.username); if(flow->ndpi_flow->protos.telnet.password[0] != '\0') diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h index 2d2eeae30f2..c8812915b05 100644 --- a/src/include/ndpi_protocol_ids.h +++ b/src/include/ndpi_protocol_ids.h @@ -326,6 +326,7 @@ typedef enum { NDPI_PROTOCOL_1KXUN = 295, NDPI_PROTOCOL_IP_PGM = 296, NDPI_PROTOCOL_IP_PIM = 297, + NDPI_PROTOCOL_COLLECTD = 298, #ifdef CUSTOM_NDPI_PROTOCOLS #include "../../../nDPI-custom/custom_ndpi_protocol_ids.h" diff --git a/src/include/ndpi_protocols.h b/src/include/ndpi_protocols.h index a0a8bfc40f2..25395c1fa11 100644 --- a/src/include/ndpi_protocols.h +++ b/src/include/ndpi_protocols.h @@ -228,6 +228,7 @@ void init_xiaomi_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_i void init_mpegdash_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); void init_rsh_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); void init_ipsec_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); +void init_collectd_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); /* ndpi_main.c */ extern u_int32_t ndpi_ip_port_hash_funct(u_int32_t ip, u_int16_t port); diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 2f47a28b507..493fae6fba1 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1191,7 +1191,7 @@ struct ndpi_flow_struct { char flow_extra_info[16]; /* General purpose field used to save mainly hostname/SNI information. - * In details it used for: DNS, SSDP and NETBIOS name, HTTP and DHCP hostname, + * In details it used for: COLLECTD, DNS, SSDP and NETBIOS name, HTTP and DHCP hostname, * WHOIS request, TLS/QUIC server name, XIAOMI domain and STUN realm. * * Please, think *very* hard before increasing its size! @@ -1297,6 +1297,10 @@ struct ndpi_flow_struct { char command[48]; } rsh; + struct { + char client_username[32]; + } collectd; + struct { char version[32]; } ubntac2; diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 83a0cb7ab70..182ad45e5e2 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1916,9 +1916,13 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp ndpi_build_default_ports(ports_a, 514, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, 0 /* nw proto */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_PIM, - "IP_PIM", NDPI_PROTOCOL_CATEGORY_NETWORK, - ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, - ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); + "IP_PIM", NDPI_PROTOCOL_CATEGORY_NETWORK, + ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, + ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); + ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, 0 /* nw proto */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_COLLECTD, + "collectd", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS, + ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, + ndpi_build_default_ports(ports_b, 25826, 0, 0, 0, 0) /* UDP */); #ifdef CUSTOM_NDPI_PROTOCOLS #include "../../../nDPI-custom/custom_ndpi_main.c" @@ -4424,6 +4428,9 @@ static int ndpi_callback_init(struct ndpi_detection_module_struct *ndpi_str) { /* IPsec */ init_ipsec_dissector(ndpi_str, &a, detection_bitmask); + /* collectd */ + init_collectd_dissector(ndpi_str, &a, detection_bitmask); + #ifdef CUSTOM_NDPI_PROTOCOLS #include "../../../nDPI-custom/custom_ndpi_main_init.c" #endif diff --git a/src/lib/protocols/collectd.c b/src/lib/protocols/collectd.c new file mode 100644 index 00000000000..47927badfa3 --- /dev/null +++ b/src/lib/protocols/collectd.c @@ -0,0 +1,210 @@ +/* + * collectd.c + * + * Copyright (C) 2022 - ntop.org + * + * nDPI is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * nDPI is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with nDPI. If not, see . + * + */ + + +#include "ndpi_protocol_ids.h" + +#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_COLLECTD + +#include "ndpi_api.h" + +#define COLLECTD_MIN_BLOCKS_REQUIRED 3 +#define COLLECTD_MAX_BLOCKS_TO_DISSECT 5 + +#define COLLECTD_ENCR_AES256_MIN_BLOCK_SIZE 6 +#define COLLECTD_ENCR_AES256_IV_SIZE 16 + +enum collectd_type { + COLLECTD_TYPE_HOST = 0x0000, + COLLECTD_TYPE_TIME = 0x0001, + COLLECTD_TYPE_TIME_HR = 0x0008, + COLLECTD_TYPE_PLUGIN = 0x0002, + COLLECTD_TYPE_PLUGIN_INSTANCE = 0x0003, + COLLECTD_TYPE_TYPE = 0x0004, + COLLECTD_TYPE_TYPE_INSTANCE = 0x0005, + COLLECTD_TYPE_VALUES = 0x0006, + COLLECTD_TYPE_INTERVAL = 0x0007, + COLLECTD_TYPE_INTERVAL_HR = 0x0009, + COLLECTD_TYPE_MESSAGE = 0x0100, + COLLECTD_TYPE_SEVERITY = 0x0101, + COLLECTD_TYPE_SIGN_SHA256 = 0x0200, + COLELCTD_TYPE_ENCR_AES256 = 0x0210, +}; + +static u_int16_t const collectd_types[] = { + COLLECTD_TYPE_HOST, COLLECTD_TYPE_TIME, COLLECTD_TYPE_TIME_HR, COLLECTD_TYPE_PLUGIN, + COLLECTD_TYPE_PLUGIN_INSTANCE, COLLECTD_TYPE_TYPE, COLLECTD_TYPE_TYPE_INSTANCE, + COLLECTD_TYPE_VALUES, COLLECTD_TYPE_INTERVAL, COLLECTD_TYPE_INTERVAL_HR, + COLLECTD_TYPE_MESSAGE, COLLECTD_TYPE_SEVERITY, COLLECTD_TYPE_SIGN_SHA256, + COLELCTD_TYPE_ENCR_AES256 +}; +static const size_t collectd_types_length = NDPI_ARRAY_LENGTH(collectd_types); + +static void ndpi_int_collectd_add_connection(struct ndpi_detection_module_struct * const ndpi_struct, + struct ndpi_flow_struct * const flow) +{ + NDPI_LOG_INFO(ndpi_struct, "found collectd\n"); + ndpi_set_detected_protocol(ndpi_struct, flow, + NDPI_PROTOCOL_COLLECTD, + NDPI_PROTOCOL_UNKNOWN, + NDPI_CONFIDENCE_DPI); +} + +static u_int16_t npdi_int_collectd_block_size(struct ndpi_packet_struct const * const packet, + u_int16_t const block_offset) +{ + if (block_offset + 4 > packet->payload_packet_len) + { + return 0; + } + + u_int16_t next_block = ntohs(get_u_int16_t(packet->payload, block_offset + 2)); + if (block_offset + next_block > packet->payload_packet_len || + (u_int16_t)(block_offset + next_block) <= block_offset /* possible overflow or next_block is zero */) + { + return 0; + } + + return next_block; +} + +static int ndpi_int_collectd_check_type(u_int16_t block_type) +{ + size_t i; + + for (i = 0; i < collectd_types_length; ++i) + { + if (block_type == collectd_types[i]) + { + return 0; + } + } + + return 1; +} + +static int ndpi_int_collectd_dissect_hostname(struct ndpi_flow_struct * const flow, + struct ndpi_packet_struct const * const packet, + u_int16_t block_offset, u_int16_t block_length) +{ + return (ndpi_hostname_sni_set(flow, &packet->payload[4], block_length) == NULL); +} + +static int ndpi_int_collectd_dissect_username(struct ndpi_flow_struct * const flow, + struct ndpi_packet_struct const * const packet, + u_int16_t block_offset) +{ + u_int16_t username_length = ntohs(get_u_int16_t(packet->payload, 4)); + + if(username_length > packet->payload_packet_len - + COLLECTD_ENCR_AES256_MIN_BLOCK_SIZE - + COLLECTD_ENCR_AES256_IV_SIZE) + { + return 1; + } + + size_t sz_len = ndpi_min(sizeof(flow->protos.collectd.client_username) - 1, username_length); + memcpy(flow->protos.collectd.client_username, &packet->payload[6], sz_len); + flow->protos.collectd.client_username[sz_len] = '\0'; + + return 0; +} + +void ndpi_search_collectd(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow) +{ + struct ndpi_packet_struct const * const packet = &ndpi_struct->packet; + u_int16_t num_blocks, malformed_blocks = 0; + u_int16_t block_offset = 0, block_type, block_length; + u_int16_t hostname_offset, hostname_length = 0; + + NDPI_LOG_DBG(ndpi_struct, "search collectd\n"); + + for (num_blocks = 0; num_blocks < COLLECTD_MAX_BLOCKS_TO_DISSECT; + ++num_blocks, block_offset += block_length) + { + block_length = npdi_int_collectd_block_size(packet, block_offset); + if (block_length == 0) + { + break; + } + + block_type = ntohs(get_u_int16_t(packet->payload, block_offset)); + if (ndpi_int_collectd_check_type(block_type) != 0) + { + malformed_blocks++; + } else { + if (block_type == COLLECTD_TYPE_HOST) + { + /* + * Dissect the hostname later, when we are sure that it is + * the collectd protocol. + */ + hostname_offset = block_offset; + hostname_length = block_length; + } else if (block_type == COLELCTD_TYPE_ENCR_AES256) { + /* + * The encrypted data block is a special case. + * It is the only dissectable block as everything else in it + * is encrypted. + */ + if (block_length != packet->payload_packet_len || + block_length < COLLECTD_ENCR_AES256_MIN_BLOCK_SIZE || + ndpi_int_collectd_dissect_username(flow, packet, block_offset) != 0) + { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + } else { + ndpi_int_collectd_add_connection(ndpi_struct, flow); + } + return; + } + } + } + + if (num_blocks < COLLECTD_MIN_BLOCKS_REQUIRED) + { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + return; + } + + if ((hostname_length > 0 && + ndpi_int_collectd_dissect_hostname(flow, packet, hostname_offset, + hostname_length) != 0) || + malformed_blocks > 0) + { + ndpi_set_risk(ndpi_struct, flow, NDPI_MALFORMED_PACKET, "Invalid collectd Header"); + } + + ndpi_int_collectd_add_connection(ndpi_struct, flow); +} + +void init_collectd_dissector(struct ndpi_detection_module_struct *ndpi_struct, + u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) +{ + ndpi_set_bitmask_protocol_detection("collectd", ndpi_struct, detection_bitmask, *id, + NDPI_PROTOCOL_COLLECTD, + ndpi_search_collectd, + NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD, + SAVE_DETECTION_BITMASK_AS_UNKNOWN, + ADD_TO_DETECTION_BITMASK + ); + + *id += 1; +} diff --git a/tests/pcap/collectd.pcap b/tests/pcap/collectd.pcap new file mode 100644 index 0000000000000000000000000000000000000000..5621865c2fef6f40acdd9b27aacb722c4405d48f GIT binary patch literal 112232 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 127.0.0.1:25826 [proto: 298/collectd][ClearText][Confidence: DPI][cat: System/18][49 pkts/66012 bytes -> 0 pkts/0 bytes][Goodput ratio: 97/0][406.49 sec][Hostname/SNI: devlap.fritz.box][bytes ratio: 1.000 (Upload)][IAT c2s/s2c min/avg/max/stddev: 0/0 8783/0 10000/0 3188/0][Pkt Len c2s/s2c min/avg/max/stddev: 193/0 1347/0 1388/0 167/0][PLAIN TEXT (devlap.fritz.box)][Plen Bins: 0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,83,10,0,0,0,0,0] + 2 UDP 127.0.0.1:36832 -> 127.0.0.1:25826 [proto: 298/collectd][ClearText][Confidence: DPI][cat: System/18][17 pkts/22755 bytes -> 0 pkts/0 bytes][Goodput ratio: 97/0][134.67 sec][Hostname/SNI: devlap.fritz.box][bytes ratio: 1.000 (Upload)][IAT c2s/s2c min/avg/max/stddev: 0/0 8311/0 10000/0 3518/0][Pkt Len c2s/s2c min/avg/max/stddev: 924/0 1339/0 1384/0 104/0][PLAIN TEXT (devlap.fritz.box)][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,5,89,0,0,0,0,0,0] + 3 UDP 192.168.178.35:39576 -> 239.192.74.66:25826 [proto: 298/collectd][ClearText][Confidence: Match by port][cat: System/18][6 pkts/8363 bytes -> 0 pkts/0 bytes][Goodput ratio: 97/0][708570048.00 sec][bytes ratio: 1.000 (Upload)][IAT c2s/s2c min/avg/max/stddev: 907/0 839078848/0 4195363456/0 1678142336/0][Pkt Len c2s/s2c min/avg/max/stddev: 1274/0 1394/0 1434/0 54/0][PLAIN TEXT (RmBJSP)][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,33,50,0,0,0,0] + 4 UDP 127.0.0.1:54138 -> 127.0.0.1:25826 [proto: 298/collectd][ClearText][Confidence: DPI][cat: System/18][5 pkts/6744 bytes -> 0 pkts/0 bytes][Goodput ratio: 97/0][33.27 sec][Hostname/SNI: devlap.fritz.box][PLAIN TEXT (devlap.fritz.box)][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,20,40,20,0,0,0,0,0] + 5 UDP 192.168.178.35:39577 -> 239.192.74.66:25826 [proto: 298/collectd][ClearText][Confidence: Match by port][cat: System/18][1 pkts/1408 bytes -> 0 pkts/0 bytes][Goodput ratio: 97/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0] + 6 UDP 127.0.0.1:36064 -> 127.0.0.1:25826 [proto: 298/collectd][ClearText][Confidence: DPI][cat: System/18][1 pkts/1368 bytes -> 0 pkts/0 bytes][Goodput ratio: 97/0][< 1 sec][Hostname/SNI: devlap.fritz.box][Risk: ** Malformed Packet **][Risk Score: 10][Risk Info: Invalid collectd Header][PLAIN TEXT (devlap.fritz.box)][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0] + 7 UDP 127.0.0.1:36320 -> 127.0.0.1:25826 [proto: 298/collectd][ClearText][Confidence: Match by port][cat: System/18][1 pkts/1368 bytes -> 0 pkts/0 bytes][Goodput ratio: 97/0][< 1 sec][PLAIN TEXT (devlap.fritz.box)][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0] + 8 UDP 127.0.0.1:36576 -> 127.0.0.1:25826 [proto: 298/collectd][ClearText][Confidence: DPI][cat: System/18][1 pkts/1368 bytes -> 0 pkts/0 bytes][Goodput ratio: 97/0][< 1 sec][Hostname/SNI: devlap.fritz.box][PLAIN TEXT (devlap.fritz.box)][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0] diff --git a/tests/result/synscan.pcap.out b/tests/result/synscan.pcap.out index b0061fcd245..7de10deaa5a 100644 --- a/tests/result/synscan.pcap.out +++ b/tests/result/synscan.pcap.out @@ -104,7 +104,7 @@ iSCSI 2 116 2 43 TCP 172.16.0.8:36050 -> 64.13.134.52:2605 [proto: 13/BGP][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 44 TCP 172.16.0.8:36050 -> 64.13.134.52:3000 [proto: 26/ntop][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 45 TCP 172.16.0.8:36050 -> 64.13.134.52:3128 [proto: 131/HTTP_Proxy][ClearText][Confidence: Match by port][cat: Web/5][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - 46 TCP 172.16.0.8:36050 -> 64.13.134.52:3260 [proto: 298/iSCSI][ClearText][Confidence: Match by port][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + 46 TCP 172.16.0.8:36050 -> 64.13.134.52:3260 [proto: 299/iSCSI][ClearText][Confidence: Match by port][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 47 TCP 172.16.0.8:36050 -> 64.13.134.52:3306 [proto: 20/MySQL][ClearText][Confidence: Match by port][cat: Database/11][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 48 TCP 172.16.0.8:36050 -> 64.13.134.52:3389 [proto: 88/RDP][ClearText][Confidence: Match by port][cat: RemoteAccess/12][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Desktop/File Sharing **][Risk Score: 10][Risk Info: Found RDP][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 49 TCP 172.16.0.8:36050 -> 64.13.134.52:4343 [proto: 170/Whois-DAS][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] @@ -165,7 +165,7 @@ iSCSI 2 116 2 104 TCP 172.16.0.8:36051 -> 64.13.134.52:2605 [proto: 13/BGP][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 105 TCP 172.16.0.8:36051 -> 64.13.134.52:3000 [proto: 26/ntop][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 106 TCP 172.16.0.8:36051 -> 64.13.134.52:3128 [proto: 131/HTTP_Proxy][ClearText][Confidence: Match by port][cat: Web/5][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - 107 TCP 172.16.0.8:36051 -> 64.13.134.52:3260 [proto: 298/iSCSI][ClearText][Confidence: Match by port][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + 107 TCP 172.16.0.8:36051 -> 64.13.134.52:3260 [proto: 299/iSCSI][ClearText][Confidence: Match by port][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 108 TCP 172.16.0.8:36051 -> 64.13.134.52:3306 [proto: 20/MySQL][ClearText][Confidence: Match by port][cat: Database/11][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 109 TCP 172.16.0.8:36051 -> 64.13.134.52:3389 [proto: 88/RDP][ClearText][Confidence: Match by port][cat: RemoteAccess/12][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Risk: ** Desktop/File Sharing **][Risk Score: 10][Risk Info: Found RDP][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 110 TCP 172.16.0.8:36051 -> 64.13.134.52:4343 [proto: 170/Whois-DAS][ClearText][Confidence: Match by port][cat: Network/14][1 pkts/58 bytes -> 0 pkts/0 bytes][Goodput ratio: 0/0][< 1 sec][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]