Skip to content

Commit

Permalink
Added new risk NDPI_TCP_ISSUES
Browse files Browse the repository at this point in the history
  • Loading branch information
lucaderi committed Jan 24, 2023
1 parent 5e8c1eb commit 5849863
Show file tree
Hide file tree
Showing 60 changed files with 325 additions and 224 deletions.
8 changes: 7 additions & 1 deletion doc/flow_risks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -301,5 +301,11 @@ This risk is generated whenever a flow is observed at a specific periodic pace (
.. _Risk 049:

NDPI_MINOR_ISSUES
=====================
=================
Minor packet/flow issues (e.g. DNS traffic with zero TTL) have been detected.

.. _Risk 050:

NDPI_TCP_ISSUES
===============
Relevant TCP connection issues such as connection refused, scan, or probe attempt.
65 changes: 33 additions & 32 deletions example/ndpiReader.c
Original file line number Diff line number Diff line change
Expand Up @@ -2119,7 +2119,7 @@ static void updatePortStats(struct port_stats **stats, u_int32_t port,
/* *********************************************** */

/* @brief heuristic choice for receiver stats */
static int acceptable(u_int32_t num_pkts){
static int acceptable(u_int32_t num_pkts) {
return num_pkts > 5;
}

Expand Down Expand Up @@ -2177,7 +2177,7 @@ static void mergeTables(struct receiver **primary, struct receiver **secondary)

HASH_ITER(hh, *primary, r, tmp) {
HASH_FIND_INT(*secondary, (int *)&(r->addr), s);
if(s == NULL){
if(s == NULL) {
s = (struct receiver *)ndpi_malloc(sizeof(struct receiver));
if(!s) return;

Expand Down Expand Up @@ -2208,7 +2208,7 @@ static void deleteReceivers(struct receiver *rcvrs) {
/* *********************************************** */
/* implementation of: https://jeroen.massar.ch/presentations/files/FloCon2010-TopK.pdf
*
* if(table1.size < max1 || acceptable){
* if(table1.size < max1 || acceptable) {
* create new element and add to the table1
* if(table1.size > max2) {
* cut table1 back to max1
Expand All @@ -2230,7 +2230,7 @@ static void updateReceivers(struct receiver **rcvrs, u_int32_t dst_addr,
HASH_FIND_INT(*rcvrs, (int *)&dst_addr, r);
if(r == NULL) {
if(((size = HASH_COUNT(*rcvrs)) < MAX_TABLE_SIZE_1)
|| ((a = acceptable(num_pkts)) != 0)){
|| ((a = acceptable(num_pkts)) != 0)) {
r = (struct receiver *)ndpi_malloc(sizeof(struct receiver));
if(!r) return;

Expand All @@ -2240,13 +2240,13 @@ static void updateReceivers(struct receiver **rcvrs, u_int32_t dst_addr,

HASH_ADD_INT(*rcvrs, addr, r);

if((size = HASH_COUNT(*rcvrs)) > MAX_TABLE_SIZE_2){
if((size = HASH_COUNT(*rcvrs)) > MAX_TABLE_SIZE_2) {

HASH_SORT(*rcvrs, receivers_sort_asc);
*rcvrs = cutBackTo(rcvrs, size, MAX_TABLE_SIZE_1);
mergeTables(rcvrs, topRcvrs);

if((size = HASH_COUNT(*topRcvrs)) > MAX_TABLE_SIZE_1){
if((size = HASH_COUNT(*topRcvrs)) > MAX_TABLE_SIZE_1) {
HASH_SORT(*topRcvrs, receivers_sort_asc);
*topRcvrs = cutBackTo(topRcvrs, size, MAX_TABLE_SIZE_1);
}
Expand Down Expand Up @@ -2690,7 +2690,7 @@ static void printRiskStats() {
/* *********************************************** */

/*function to use in HASH_SORT function in verbose == 4 to order in creasing order to delete host with the leatest occurency*/
static int hash_stats_sort_to_order(void *_a, void *_b){
static int hash_stats_sort_to_order(void *_a, void *_b) {
struct hash_stats *a = (struct hash_stats*)_a;
struct hash_stats *b = (struct hash_stats*)_b;

Expand All @@ -2700,7 +2700,7 @@ static int hash_stats_sort_to_order(void *_a, void *_b){
/* *********************************************** */

/*function to use in HASH_SORT function in verbose == 4 to print in decreasing order*/
static int hash_stats_sort_to_print(void *_a, void *_b){
static int hash_stats_sort_to_print(void *_a, void *_b) {
struct hash_stats *a = (struct hash_stats*)_a;
struct hash_stats *b = (struct hash_stats*)_b;

Expand Down Expand Up @@ -2752,12 +2752,12 @@ static void printFlowsStats() {
ndpi_ja3_fingerprints_host *hostByJA3Found = NULL;

//check if this is a ssh-ssl flow
if(all_flows[i].flow->ssh_tls.ja3_client[0] != '\0'){
if(all_flows[i].flow->ssh_tls.ja3_client[0] != '\0') {
//looking if the host is already in the hash table
HASH_FIND_INT(ja3ByHostsHashT, &(all_flows[i].flow->src_ip), ja3ByHostFound);

//host ip -> ja3
if(ja3ByHostFound == NULL){
if(ja3ByHostFound == NULL) {
//adding the new host
ndpi_host_ja3_fingerprints *newHost = ndpi_malloc(sizeof(ndpi_host_ja3_fingerprints));
newHost->host_client_info_hasht = NULL;
Expand All @@ -2781,7 +2781,7 @@ static void printFlowsStats() {
HASH_FIND_STR(ja3ByHostFound->host_client_info_hasht,
all_flows[i].flow->ssh_tls.ja3_client, infoFound);

if(infoFound == NULL){
if(infoFound == NULL) {
ndpi_ja3_info *newJA3 = ndpi_malloc(sizeof(ndpi_ja3_info));
newJA3->ja3 = all_flows[i].flow->ssh_tls.ja3_client;
newJA3->unsafe_cipher = all_flows[i].flow->ssh_tls.client_unsafe_cipher;
Expand All @@ -2792,7 +2792,7 @@ static void printFlowsStats() {

//ja3 -> host ip
HASH_FIND_STR(hostByJA3C_ht, all_flows[i].flow->ssh_tls.ja3_client, hostByJA3Found);
if(hostByJA3Found == NULL){
if(hostByJA3Found == NULL) {
ndpi_ip_dns *newHost = ndpi_malloc(sizeof(ndpi_ip_dns));

newHost->ip = all_flows[i].flow->src_ip;
Expand All @@ -2810,7 +2810,7 @@ static void printFlowsStats() {
} else {
ndpi_ip_dns *innerElement = NULL;
HASH_FIND_INT(hostByJA3Found->ipToDNS_ht, &(all_flows[i].flow->src_ip), innerElement);
if(innerElement == NULL){
if(innerElement == NULL) {
ndpi_ip_dns *newInnerElement = ndpi_malloc(sizeof(ndpi_ip_dns));
newInnerElement->ip = all_flows[i].flow->src_ip;
newInnerElement->ip_string = all_flows[i].flow->src_name;
Expand All @@ -2820,10 +2820,10 @@ static void printFlowsStats() {
}
}

if(all_flows[i].flow->ssh_tls.ja3_server[0] != '\0'){
if(all_flows[i].flow->ssh_tls.ja3_server[0] != '\0') {
//looking if the host is already in the hash table
HASH_FIND_INT(ja3ByHostsHashT, &(all_flows[i].flow->dst_ip), ja3ByHostFound);
if(ja3ByHostFound == NULL){
if(ja3ByHostFound == NULL) {
//adding the new host in the hash table
ndpi_host_ja3_fingerprints *newHost = ndpi_malloc(sizeof(ndpi_host_ja3_fingerprints));
newHost->host_client_info_hasht = NULL;
Expand All @@ -2845,7 +2845,7 @@ static void printFlowsStats() {
ndpi_ja3_info *infoFound = NULL;
HASH_FIND_STR(ja3ByHostFound->host_server_info_hasht,
all_flows[i].flow->ssh_tls.ja3_server, infoFound);
if(infoFound == NULL){
if(infoFound == NULL) {
ndpi_ja3_info *newJA3 = ndpi_malloc(sizeof(ndpi_ja3_info));
newJA3->ja3 = all_flows[i].flow->ssh_tls.ja3_server;
newJA3->unsafe_cipher = all_flows[i].flow->ssh_tls.server_unsafe_cipher;
Expand All @@ -2855,7 +2855,7 @@ static void printFlowsStats() {
}

HASH_FIND_STR(hostByJA3S_ht, all_flows[i].flow->ssh_tls.ja3_server, hostByJA3Found);
if(hostByJA3Found == NULL){
if(hostByJA3Found == NULL) {
ndpi_ip_dns *newHost = ndpi_malloc(sizeof(ndpi_ip_dns));

newHost->ip = all_flows[i].flow->dst_ip;
Expand All @@ -2874,7 +2874,7 @@ static void printFlowsStats() {
ndpi_ip_dns *innerElement = NULL;

HASH_FIND_INT(hostByJA3Found->ipToDNS_ht, &(all_flows[i].flow->dst_ip), innerElement);
if(innerElement == NULL){
if(innerElement == NULL) {
ndpi_ip_dns *newInnerElement = ndpi_malloc(sizeof(ndpi_ip_dns));
newInnerElement->ip = all_flows[i].flow->dst_ip;
newInnerElement->ip_string = all_flows[i].flow->dst_name;
Expand Down Expand Up @@ -3063,7 +3063,7 @@ static void printFlowsStats() {
}
}

if (verbose == 4){
if (verbose == 4) {
//how long the table could be
unsigned int len_table_max = 1000;
//number of element to delete when the table is full
Expand All @@ -3073,25 +3073,25 @@ static void printFlowsStats() {
struct hash_stats *tmp = NULL;
int len_max = 0;

for (i = 0; i<num_flows; i++){
for (i = 0; i<num_flows; i++) {

if(all_flows[i].flow->host_server_name[0] != '\0'){
if(all_flows[i].flow->host_server_name[0] != '\0') {

int len = strlen(all_flows[i].flow->host_server_name);
len_max = ndpi_max(len,len_max);

struct hash_stats *hostFound;
HASH_FIND_STR(hostsHashT, all_flows[i].flow->host_server_name, hostFound);

if(hostFound == NULL){
if(hostFound == NULL) {
struct hash_stats *newHost = (struct hash_stats*)ndpi_malloc(sizeof(hash_stats));
newHost->domain_name = all_flows[i].flow->host_server_name;
newHost->occurency = 1;
if (HASH_COUNT(hostsHashT) == len_table_max) {
int i=0;
while (i<=toDelete){
while (i<=toDelete) {

HASH_ITER(hh, hostsHashT, host_iter, tmp){
HASH_ITER(hh, hostsHashT, host_iter, tmp) {
HASH_DEL(hostsHashT,host_iter);
free(host_iter);
i++;
Expand All @@ -3107,24 +3107,24 @@ static void printFlowsStats() {

}

if(all_flows[i].flow->ssh_tls.server_info[0] != '\0'){
if(all_flows[i].flow->ssh_tls.server_info[0] != '\0') {

int len = strlen(all_flows[i].flow->host_server_name);
len_max = ndpi_max(len,len_max);

struct hash_stats *hostFound;
HASH_FIND_STR(hostsHashT, all_flows[i].flow->ssh_tls.server_info, hostFound);

if(hostFound == NULL){
if(hostFound == NULL) {
struct hash_stats *newHost = (struct hash_stats*)ndpi_malloc(sizeof(hash_stats));
newHost->domain_name = all_flows[i].flow->ssh_tls.server_info;
newHost->occurency = 1;

if ((HASH_COUNT(hostsHashT)) == len_table_max) {
int i=0;
while (i<toDelete){
while (i<toDelete) {

HASH_ITER(hh, hostsHashT, host_iter, tmp){
HASH_ITER(hh, hostsHashT, host_iter, tmp) {
HASH_DEL(hostsHashT,host_iter);
ndpi_free(host_iter);
i++;
Expand All @@ -3150,7 +3150,7 @@ static void printFlowsStats() {

//print the element of the hash table
int j;
HASH_ITER(hh, hostsHashT, host_iter, tmp){
HASH_ITER(hh, hostsHashT, host_iter, tmp) {

printf("\t%s", host_iter->domain_name);
//to print the occurency in aligned column
Expand All @@ -3162,7 +3162,7 @@ static void printFlowsStats() {
printf("%s", "\n\n");

//freeing the hash table
HASH_ITER(hh, hostsHashT, host_iter, tmp){
HASH_ITER(hh, hostsHashT, host_iter, tmp) {
HASH_DEL(hostsHashT, host_iter);
ndpi_free(host_iter);
}
Expand Down Expand Up @@ -3982,9 +3982,10 @@ static void ndpi_process_packet(u_char *args,
/* allocate an exact size buffer to check overflows */
uint8_t *packet_checked = ndpi_malloc(header->caplen);

if(packet_checked == NULL){
if(packet_checked == NULL) {
return ;
}

memcpy(packet_checked, packet, header->caplen);
p = ndpi_workflow_process_packet(ndpi_thread_info[thread_id].workflow, header, packet_checked, &flow_risk);

Expand Down Expand Up @@ -4092,7 +4093,7 @@ static void ndpi_process_packet(u_char *args,
Leave the free as last statement to avoid crashes when ndpi_detection_giveup()
is called above by printResults()
*/
if(packet_checked){
if(packet_checked) {
ndpi_free(packet_checked);
packet_checked = NULL;
}
Expand Down
17 changes: 9 additions & 8 deletions src/include/ndpi_typedefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ typedef enum {
your app will clear this risk if future packets (not sent to nDPI)
are received in the opposite direction */
NDPI_HTTP_OBSOLETE_SERVER,
NDPI_PERIODIC_FLOW, /* Set in case a flow repeats at a specific pace [used by apps on top of nDPI] */
NDPI_MINOR_ISSUES, /* Generic packet issues (e.g. DNS with 0 TTL) */

NDPI_PERIODIC_FLOW, /* Set in case a flow repeats at a specific pace [used by apps on top of nDPI] */
NDPI_MINOR_ISSUES, /* Generic packet issues (e.g. DNS with 0 TTL) */
NDPI_TCP_ISSUES, /* TCP issues such as connection failed, probing or scan */

/* Leave this as last member */
NDPI_MAX_RISK /* must be <= 63 due to (**) */
} ndpi_risk_enum;
Expand Down Expand Up @@ -724,10 +725,9 @@ struct ndpi_flow_tcp_struct {
u_int32_t postgres_stage:3;

/* Part of the TCP header. */
u_int32_t seen_syn:1;
u_int32_t seen_syn_ack:1;
u_int32_t seen_ack:1;

u_int32_t seen_syn:1, seen_syn_ack:1, seen_ack:1, __notused:29;
u_int8_t cli2srv_tcp_flags, srv2cli_tcp_flags;

/* NDPI_PROTOCOL_ICECAST */
u_int32_t icecast_stage:1;

Expand Down Expand Up @@ -1525,7 +1525,8 @@ struct ndpi_flow_struct {
/* Only packets with L5 data (ie no TCP SYN, pure ACKs, ...) */
u_int16_t packet_counter; // can be 0 - 65000
u_int16_t packet_direction_counter[2];

u_int16_t all_packets_counter; /* All packets even those without payload */

/* Every packets */
u_int16_t packet_direction_complete_counter[2]; // can be 0 - 65000

Expand Down
Loading

0 comments on commit 5849863

Please sign in to comment.