diff options
author | lucasbaile <lucasbaile14@gmail.com> | 2021-09-09 17:47:58 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-09 22:47:58 +0200 |
commit | 1fadf4754a1741e6fd690dbb65ae778fd1dc0313 (patch) | |
tree | d8a6613a5cf512c7bc1c9d6091f2828d3ceebe3f | |
parent | 36f08b8d2e947ec0877ebd3dcb160def7ec6fc54 (diff) |
Add Cassandra protocol dissector (#1285)
Co-authored-by: Lucas Santos <lucas.santos@zerum.com>
-rw-r--r-- | src/include/ndpi_protocol_ids.h | 1 | ||||
-rw-r--r-- | src/include/ndpi_protocols.h | 1 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 7 | ||||
-rw-r--r-- | src/lib/protocols/cassandra.c | 139 | ||||
-rw-r--r-- | tests/pcap/cassandra.pcap | bin | 0 -> 130616 bytes | |||
-rw-r--r-- | tests/result/cassandra.pcap.out | 8 | ||||
-rw-r--r-- | tests/result/synscan.pcap.out | 4 |
7 files changed, 158 insertions, 2 deletions
diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h index ec67eeda6..d57b17add 100644 --- a/src/include/ndpi_protocol_ids.h +++ b/src/include/ndpi_protocol_ids.h @@ -292,6 +292,7 @@ typedef enum { NDPI_PROTOCOL_LIKEE = 261, NDPI_PROTOCOL_GITLAB = 262, NDPI_PROTOCOL_AVAST_SECUREDNS = 263, /* Toni Uhlig <matzeton@googlemail.com> */ + NDPI_PROTOCOL_CASSANDRA = 264, /* Lucas Santos <lfneiva.santos@gmail.com> */ #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 40b9e4dce..31682278e 100644 --- a/src/include/ndpi_protocols.h +++ b/src/include/ndpi_protocols.h @@ -216,5 +216,6 @@ void init_hpvirtgrp_dissector(struct ndpi_detection_module_struct *ndpi_struct, void init_genshin_impact_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); void init_z3950_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); void init_avast_securedns_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); +void init_cassandra_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); #endif /* __NDPI_PROTOCOLS_H__ */ diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 7ae8861ac..d5a169eac 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1742,6 +1742,10 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp "AVAST SecureDNS", 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 */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CASSANDRA, + "Cassandra", NDPI_PROTOCOL_CATEGORY_DATABASE, + ndpi_build_default_ports(ports_a, 9042, 0, 0, 0, 0) /* TCP */, + ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); #ifdef CUSTOM_NDPI_PROTOCOLS #include "../../../nDPI-custom/custom_ndpi_main.c" @@ -4030,6 +4034,9 @@ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *n /* AVAST SecureDNS */ init_avast_securedns_dissector(ndpi_str, &a, detection_bitmask); + /* Cassandra */ + init_cassandra_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/cassandra.c b/src/lib/protocols/cassandra.c new file mode 100644 index 000000000..1072ed4b5 --- /dev/null +++ b/src/lib/protocols/cassandra.c @@ -0,0 +1,139 @@ +/* + * cassandra.c + * + * Copyright (C) 2021 by Lucas Santos <lfneiva.santos@gmail.com> + * + * This file is part of nDPI, an open source deep packet inspection + * library based on the OpenDPI and PACE technology by ipoque GmbH + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include "ndpi_protocol_ids.h" +#include "ndpi_api.h" + +#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_CASSANDRA +#define CASSANDRA_HEADER_LEN 9 +#define CASSANDRA_MAX_BODY_SIZE 268435456 //256MB (256 * 1024^2) + +enum cassandra_version +{ + CASSANDRA_V1_REQUEST = 0x01, + CASSANDRA_V1_RESPONSE = 0x81, + CASSANDRA_V2_REQUEST = 0x02, + CASSANDRA_V2_RESPONSE = 0x82, + CASSANDRA_V3_REQUEST = 0x03, + CASSANDRA_V3_RESPONSE = 0x83, + CASSANDRA_V4_REQUEST = 0x04, + CASSANDRA_V4_RESPONSE = 0x84 +}; + +enum cassandra_opcode +{ + CASSANDRA_ERROR = 0x00, + CASSANDRA_STARTUP = 0x01, + CASSANDRA_READY = 0x02, + CASSANDRA_AUTHENTICATE = 0x03, + CASSANDRA_OPTIONS = 0x05, + CASSANDRA_SUPPORTED = 0x06, + CASSANDRA_QUERY = 0x07, + CASSANDRA_RESULT = 0x08, + CASSANDRA_PREPARE = 0x09, + CASSANDRA_EXECUTE = 0x0A, + CASSANDRA_REGISTER = 0x0B, + CASSANDRA_EVENT = 0x0C, + CASSANDRA_BATCH = 0x0D, + CASSANDRA_AUTH_CHALLENGE = 0x0E, + CASSANDRA_AUTH_RESPONSE = 0x0F, + CASSANDRA_AUTH_SUCCESS = 0x10 +}; + +static bool ndpi_check_valid_cassandra_version(uint8_t version) +{ + switch(version) { + case CASSANDRA_V1_REQUEST: + case CASSANDRA_V1_RESPONSE: + case CASSANDRA_V2_REQUEST: + case CASSANDRA_V2_RESPONSE: + case CASSANDRA_V3_REQUEST: + case CASSANDRA_V3_RESPONSE: + case CASSANDRA_V4_REQUEST: + case CASSANDRA_V4_RESPONSE: + return true; + } + return false; +} + +static bool ndpi_check_valid_cassandra_opcode(uint8_t opcode) +{ + switch (opcode) { + case CASSANDRA_ERROR: + case CASSANDRA_STARTUP: + case CASSANDRA_READY: + case CASSANDRA_AUTHENTICATE: + case CASSANDRA_OPTIONS: + case CASSANDRA_SUPPORTED: + case CASSANDRA_QUERY: + case CASSANDRA_RESULT: + case CASSANDRA_PREPARE: + case CASSANDRA_EXECUTE: + case CASSANDRA_REGISTER: + case CASSANDRA_EVENT: + case CASSANDRA_BATCH: + case CASSANDRA_AUTH_CHALLENGE: + case CASSANDRA_AUTH_RESPONSE: + case CASSANDRA_AUTH_SUCCESS: + return true; + } + return false; +} + +void ndpi_search_cassandra(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow) +{ + struct ndpi_packet_struct *packet = &flow->packet; + + if (packet->tcp) { + if (packet->payload_packet_len >= CASSANDRA_HEADER_LEN && + ndpi_check_valid_cassandra_version(get_u_int8_t(packet->payload, 0)) && + ndpi_check_valid_cassandra_opcode(get_u_int8_t(packet->payload, 4)) && + get_u_int32_t(packet->payload, 5) <= CASSANDRA_MAX_BODY_SIZE && + get_u_int32_t(packet->payload, 5) >= (uint32_t) (packet->payload_packet_len - CASSANDRA_HEADER_LEN)) { + ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_CASSANDRA, NDPI_PROTOCOL_UNKNOWN); + return; + } + } + + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); +} + +/* ********************************* */ + + +void init_cassandra_dissector(struct ndpi_detection_module_struct *ndpi_struct, + u_int32_t *id, + NDPI_PROTOCOL_BITMASK *detection_bitmask) { + + ndpi_set_bitmask_protocol_detection("Cassandra", + ndpi_struct, detection_bitmask, + *id, + NDPI_PROTOCOL_CASSANDRA, + ndpi_search_cassandra, + NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD, + SAVE_DETECTION_BITMASK_AS_UNKNOWN, + ADD_TO_DETECTION_BITMASK); + + *id += 1; +} diff --git a/tests/pcap/cassandra.pcap b/tests/pcap/cassandra.pcap Binary files differnew file mode 100644 index 000000000..37522b435 --- /dev/null +++ b/tests/pcap/cassandra.pcap diff --git a/tests/result/cassandra.pcap.out b/tests/result/cassandra.pcap.out new file mode 100644 index 000000000..44ebf7193 --- /dev/null +++ b/tests/result/cassandra.pcap.out @@ -0,0 +1,8 @@ +Guessed flow protos: 0 + +DPI Packets (TCP): 8 (4.00 pkts/flow) + +Cassandra 286 126016 2 + + 1 TCP 127.0.0.1:46536 <-> 127.0.0.1:9042 [proto: 264/Cassandra][ClearText][cat: Database/11][75 pkts/9730 bytes <-> 69 pkts/78014 bytes][Goodput ratio: 49/94][200.04 sec][bytes ratio: -0.778 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 3063/2427 32715/30000 8555/7658][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 130/1131 462/25214 82/4102][PLAIN TEXT (COMPRESSION)][Plen Bins: 8,16,44,9,5,0,6,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2] + 2 TCP 127.0.0.1:46537 <-> 127.0.0.1:9042 [proto: 264/Cassandra][ClearText][cat: Database/11][74 pkts/9855 bytes <-> 68 pkts/28417 bytes][Goodput ratio: 50/84][200.00 sec][bytes ratio: -0.485 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 2835/2737 33012/33012 6521/6804][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 133/418 399/11512 80/1399][PLAIN TEXT (COMPRESSION)][Plen Bins: 13,13,32,12,5,2,1,6,0,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,0,0,0,1,0,0,0,0,0,1] diff --git a/tests/result/synscan.pcap.out b/tests/result/synscan.pcap.out index f7e8b9dc9..29a491860 100644 --- a/tests/result/synscan.pcap.out +++ b/tests/result/synscan.pcap.out @@ -101,7 +101,7 @@ iSCSI 2 116 2 43 TCP 172.16.0.8:36050 -> 64.13.134.52:2605 [proto: 13/BGP][ClearText][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][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][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: 264/iSCSI][ClearText][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: 265/iSCSI][ClearText][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][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][cat: RemoteAccess/12][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] 49 TCP 172.16.0.8:36050 -> 64.13.134.52:4343 [proto: 170/Whois-DAS][ClearText][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] @@ -162,7 +162,7 @@ iSCSI 2 116 2 104 TCP 172.16.0.8:36051 -> 64.13.134.52:2605 [proto: 13/BGP][ClearText][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][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][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: 264/iSCSI][ClearText][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: 265/iSCSI][ClearText][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][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][cat: RemoteAccess/12][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] 110 TCP 172.16.0.8:36051 -> 64.13.134.52:4343 [proto: 170/Whois-DAS][ClearText][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] |