aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/ndpi_protocol_ids.h1
-rw-r--r--src/include/ndpi_protocols.h1
-rw-r--r--src/lib/ndpi_main.c7
-rw-r--r--src/lib/protocols/cassandra.c139
-rw-r--r--tests/pcap/cassandra.pcapbin0 -> 130616 bytes
-rw-r--r--tests/result/cassandra.pcap.out8
-rw-r--r--tests/result/synscan.pcap.out4
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
new file mode 100644
index 000000000..37522b435
--- /dev/null
+++ b/tests/pcap/cassandra.pcap
Binary files differ
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]