Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rare/Unusual Domain & Destination Flow Check #7807

Closed
wants to merge 59 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
14a00a7
test: flow's server address handling
DropB1t Apr 12, 2023
931fe1b
First sketch
LeoBubi May 3, 2023
233638f
Second sketch
LeoBubi May 3, 2023
2c378d1
Host extension for RareDest implementation.
F3rto May 5, 2023
880d221
refactor: polished hashing section
DropB1t May 5, 2023
b005bbb
fix: fix typo & set dummy default params
DropB1t May 5, 2023
3f32c19
API adaption to new Host class
LeoBubi May 7, 2023
98e92ed
[fix] API adaption to new Host class
LeoBubi May 7, 2023
e2278e4
features & refactor & fixes:
DropB1t May 7, 2023
6f358bf
Merge pull request #1 from DropB1t/host_extension
DropB1t May 8, 2023
1802dc2
Variables renaming and hashing implementation
LeoBubi May 8, 2023
f9ccc38
Fix typo
LeoBubi May 8, 2023
a626af3
bugfix: correct memory leak
DropB1t May 8, 2023
5ab82e4
Merge pull request #2 from DropB1t/host_extension
DropB1t May 8, 2023
66a3fa8
fix: fixed typos
DropB1t May 8, 2023
eb1d0e3
Hashing edit (#3)
DropB1t May 8, 2023
0cd2560
Merge branch 'epoch-feature' into rare_dest
DropB1t May 8, 2023
16f5dfd
Merge pull request #4 from DropB1t/rare_dest
DropB1t May 8, 2023
410ad41
refactor: refactor naming convention,
DropB1t May 8, 2023
fdc6d10
RareDestination.cpp refactoring
LeoBubi May 10, 2023
bb399cf
refactor & fixes:
DropB1t May 10, 2023
a62d3dc
Testing feature & fixes
DropB1t May 12, 2023
7f21dbc
fix: fixed getDestinationHash's function signature
DropB1t May 12, 2023
cdda897
[fix] loadRareDestFromRedis memory leak
LeoBubi May 13, 2023
05d851d
Merge branch 'rareDestination-refactor' into synced-latest-dev
DropB1t May 18, 2023
454ee3b
Merge pull request #5 from DropB1t/synced-latest-dev
DropB1t May 18, 2023
09231d2
refactor: moved implementation into LocalHost
DropB1t May 18, 2023
ab8713d
Commented Prints
DropB1t May 18, 2023
9c8411b
Code cleanup
LeoBubi May 19, 2023
e5795f4
refactor: moved hashing function
DropB1t May 19, 2023
300df1d
test: simplified hash function
DropB1t Jul 13, 2023
967e182
Cleanup RareDestination
DropB1t Jul 18, 2023
1dd4ec7
periodic training implemented + minor performance enhancing
DropB1t Jul 25, 2023
841c2cb
simplified hash and training functions
DropB1t Jul 26, 2023
6979e15
improved performance tweaks
DropB1t Jul 26, 2023
637460d
RareDestination minor fix
LeoBubi Jul 28, 2023
8b33fc9
Fixed incorrect behavior and code cleanup
LeoBubi Jul 28, 2023
73c75ec
Rimozione puntatore a bitmap in RareDestination.cpp e fix relativi me…
F3rto Jul 31, 2023
e436dae
Minor fix
LeoBubi Jul 31, 2023
6cad577
Method refactor for performance improvement
LeoBubi Jul 31, 2023
4ea53a8
Fix metodi set e isSet per Bitmap
F3rto Jul 31, 2023
f491356
Fix set and isSet method
F3rto Jul 31, 2023
981b955
Code fix and method renaming
LeoBubi Aug 1, 2023
54c149a
removed commented prints
DropB1t Sep 5, 2023
0ed8b58
removed trailing whitespacing after changes
DropB1t Sep 5, 2023
57faabb
Merge branch 'dev' into periodic-training-ver
DropB1t Sep 7, 2023
cbd7892
Hashing code fix
LeoBubi Sep 12, 2023
397cd3e
Background training implementation
LeoBubi Sep 14, 2023
b7ace8b
Swap form LocalHost to NetworkInterface
F3rto Sep 15, 2023
8a3577f
Fix swap method
F3rto Sep 15, 2023
8c2cd4b
Added method implementation
LeoBubi Sep 16, 2023
bdd88e2
Code cleanup
LeoBubi Sep 17, 2023
8505a07
feature&fixes:
DropB1t Sep 17, 2023
6dca7fa
Periodic background training w/o gaps implementation
LeoBubi Sep 17, 2023
fdf6266
Minor Bug Fixes
DropB1t Sep 17, 2023
7f08d01
Fixed Typos
DropB1t Sep 17, 2023
c58b782
loadRareDestFromRedis:
DropB1t Sep 17, 2023
e3a555a
Fix: fixed memory leaks for bitmap initialization
DropB1t Sep 19, 2023
c8a40a9
Merge pull request #7 from DropB1t/post-review-adjustment
DropB1t Sep 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions include/NetworkInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ class NetworkInterface : public NetworkInterfaceAlertableEntity {
u_int32_t local_hosts, remote_hosts;
} tot_num_anomalies;
AlertsQueue *alertsQueue;

/* RareDestination data implementation*/
ndpi_bitmap *rare_dest_local;
ndpi_bitmap *rare_dest_remote;
ndpi_bitmap *rare_dest_local_bg;
ndpi_bitmap *rare_dest_remote_bg;

struct {
bool initialTraining;
time_t checkPoint;
} rareDestTraining;
/***************************************/

#if defined(NTOPNG_PRO)
PeriodicityMap *pMap;
ServiceMap *sMap;
Expand Down Expand Up @@ -433,6 +446,15 @@ class NetworkInterface : public NetworkInterfaceAlertableEntity {
void build_protocol_flow_stats_lua_rsp(lua_State *vm, AggregatedFlowsStats *fs,
u_int32_t size, u_int *num);

void saveRareDestToRedis();
bool loadRareDestFromRedis();

void setRareDestStructRedisField(const char *key, const char *field, u_int64_t value);
bool getRareDestStructRedisField(const char *key, const char *field, u_int64_t *value);

void setRareDestBitmapRedisField(const char *key, const char *field, ndpi_bitmap **bitmap);
bool getRareDestBitmapRedisField(const char *key, const char *field, ndpi_bitmap **bitmap);

public:
/**
* @brief A Constructor
Expand Down Expand Up @@ -1370,6 +1392,34 @@ class NetworkInterface : public NetworkInterfaceAlertableEntity {
void *user_data,
bool *matched);

/*RareDestination method implementation*/

inline void setLocalRareDestBitmap(u_int32_t hash) { if(rare_dest_local) ndpi_bitmap_set(rare_dest_local, hash); }
inline void setRemoteRareDestBitmap(u_int32_t hash) { if(rare_dest_remote) ndpi_bitmap_set(rare_dest_remote, hash); }
inline bool isSetLocalRareDestBitmap(u_int32_t hash) const { return ndpi_bitmap_isset(rare_dest_local, hash); }
inline bool isSetRemoteRareDestBitmap(u_int32_t hash) const { return ndpi_bitmap_isset(rare_dest_remote, hash); }

inline void setLocalRareDestBitmap_BG(u_int32_t hash) { if(rare_dest_local_bg) ndpi_bitmap_set(rare_dest_local_bg, hash); }
inline void setRemoteRareDestBitmap_BG(u_int32_t hash) { if(rare_dest_remote_bg) ndpi_bitmap_set(rare_dest_remote_bg, hash); }

inline bool getRareDestInitialTraining() const { return rareDestTraining.initialTraining;}
inline void endRareDestInitialTraining(time_t t) { rareDestTraining.initialTraining = false; rareDestTraining.checkPoint = t; }

inline time_t getRareDestTrainingCheckPoint() const { return rareDestTraining.checkPoint; }
inline void setRareDestTrainingCheckPoint(time_t t) { rareDestTraining.checkPoint = t; }

void swapRareDestBitmaps() {
ndpi_bitmap_free(rare_dest_local);
rare_dest_local = rare_dest_local_bg;
rare_dest_local_bg = ndpi_bitmap_alloc();

ndpi_bitmap_free(rare_dest_remote);
rare_dest_remote = rare_dest_remote_bg;
rare_dest_remote_bg = ndpi_bitmap_alloc();
}

/***************************************/

#ifdef NTOPNG_PRO
static bool compute_client_server_flow_stats(GenericHashEntry *node,
void *user_data, bool *matched);
Expand Down
3 changes: 3 additions & 0 deletions include/flow_checks/RareDestination.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#include "ntop_includes.h"

class RareDestination : public FlowCheck {
private:
u_int32_t getDestinationHash(Flow *f, u_int8_t *destType);

public:
RareDestination()
: FlowCheck(ntopng_edition_community, true /* Packet Interfaces only */,
Expand Down
6 changes: 6 additions & 0 deletions include/ntop_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -1505,4 +1505,10 @@ extern struct ntopngLuaContext *getUserdata(struct lua_State *vm);
#define OFFLINE_LOCAL_HOSTS_KEY "ntopng.hosts.offline.ifid_%d"
/******************************************************************************/

#define IFACE_RARE_DEST_SERIALIZED_KEY "ntopng.iface_rare_dest_fields.ifid_%d"
#define RARE_DEST_INITIAL_TRAINING_DURATION 86400 /* seconds ( 1 day ) */
#define RARE_DEST_BACKGROUND_TRAINING_DURATION 604800 /* seconds ( 1 week ) */

/******************************************************************************/

#endif /* _NTOP_DEFINES_H_ */
139 changes: 139 additions & 0 deletions src/NetworkInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,15 @@ NetworkInterface::NetworkInterface(const char *name,
}
#endif

if( id >= 0 && (!loadRareDestFromRedis() || (( time(NULL) - rareDestTraining.checkPoint ) > (2 * RARE_DEST_BACKGROUND_TRAINING_DURATION))) ){
rareDestTraining.checkPoint = 0;
rareDestTraining.initialTraining = true;
rare_dest_local = ndpi_bitmap_alloc();
rare_dest_local_bg = ndpi_bitmap_alloc();
rare_dest_remote = ndpi_bitmap_alloc();
rare_dest_remote_bg = ndpi_bitmap_alloc();
}

is_loopback = (strncmp(ifname, "lo", 2) == 0) ? true : false;

updateTrafficMirrored();
Expand Down Expand Up @@ -1022,6 +1031,14 @@ NetworkInterface::~NetworkInterface() {
cleanShadownDPI();

if (smart_recording_instance_name) free(smart_recording_instance_name);

if ( id >= 0) {
saveRareDestToRedis();
if(rare_dest_local) ndpi_bitmap_free(rare_dest_local);
if(rare_dest_local_bg) ndpi_bitmap_free(rare_dest_local_bg);
if(rare_dest_remote) ndpi_bitmap_free(rare_dest_remote);
if(rare_dest_remote_bg) ndpi_bitmap_free(rare_dest_remote_bg);
}
}

/* **************************************************** */
Expand Down Expand Up @@ -12365,3 +12382,125 @@ void NetworkInterface::getActiveMacs(lua_State *vm) {
walker(&begin_slot, true /* walk_all */, walker_macs,
active_mac_search_walker, (void *)&s);
}

/* *************************************** */

void NetworkInterface::setRareDestStructRedisField(const char *key, const char *field, u_int64_t value){
char buf[32];
snprintf(buf, sizeof(buf), "%lu", value);
ntop->getRedis()->hashSet(key, field, buf);
}

void NetworkInterface::setRareDestBitmapRedisField(const char *key, const char *field, ndpi_bitmap **bitmap){
char *value = NULL;
size_t size;

size = ndpi_bitmap_serialize((*bitmap), &value);

if( value == NULL ) return;

char *encoded_bmap = value ? Utils::base64_encode((unsigned char *)value, size) : NULL;

if (encoded_bmap != NULL) {
size = strlen(encoded_bmap);
ntop->getRedis()->hashSet(key, field, encoded_bmap);

char len_field[32];
snprintf(len_field, sizeof(len_field), "%s_len", field);
setRareDestStructRedisField(key, len_field, (u_int64_t)size);

free(encoded_bmap);
free(value);
}
}

void NetworkInterface::saveRareDestToRedis() {
char key[CONST_MAX_LEN_REDIS_KEY];

if((!ntop->getRedis()) || (!rare_dest_local) || (!rare_dest_remote) || (!rare_dest_local_bg) || (!rare_dest_remote_bg)) return;

snprintf(key, sizeof(key), IFACE_RARE_DEST_SERIALIZED_KEY, get_id());

setRareDestBitmapRedisField(key, "rare_dest_local", &rare_dest_local);
setRareDestBitmapRedisField(key, "rare_dest_local_bg", &rare_dest_local_bg);

setRareDestBitmapRedisField(key, "rare_dest_remote", &rare_dest_remote);
setRareDestBitmapRedisField(key, "rare_dest_remote_bg", &rare_dest_remote_bg);

setRareDestStructRedisField(key, "checkPoint", (u_int64_t)rareDestTraining.checkPoint);
setRareDestStructRedisField(key, "initialTraining", (u_int64_t)(rareDestTraining.initialTraining ? 1 : 0));
}

bool NetworkInterface::getRareDestStructRedisField(const char *key, const char *field, u_int64_t *value){
char buf[32];
if( ntop->getRedis()->hashGet(key, field, buf, sizeof(buf)) != 0 ) return(false);
*value = strtoul(buf, NULL, 10);
return(true);
}

bool NetworkInterface::getRareDestBitmapRedisField(const char *key, const char *field, ndpi_bitmap **bitmap){
char *bitmap_field_val = NULL;
u_int64_t value;
size_t size;

char len_field[32];
snprintf(len_field, sizeof(len_field), "%s_len", field);

if (!getRareDestStructRedisField(key, len_field, &value)) return(false);
size = (size_t)(value);

if((bitmap_field_val = (char *) malloc(size)) == NULL) {
ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to allocate memory to deserialize %s", key);
return(false);
}

if(ntop->getRedis()->hashGet(key, field, bitmap_field_val, (size)) != 0) {
free(bitmap_field_val);
return(false);
}

if( bitmap_field_val == NULL ) return(false);

(*bitmap) = ndpi_bitmap_deserialize((char *)(Utils::base64_decode((std::string)bitmap_field_val).c_str()));

free(bitmap_field_val);
return(true);
}

bool NetworkInterface::loadRareDestFromRedis() {
char key[CONST_MAX_LEN_REDIS_KEY];
u_int64_t value;
rare_dest_local = rare_dest_local_bg = rare_dest_remote = rare_dest_remote_bg = NULL;

if((!ntop->getRedis())) return(false);

snprintf(key, sizeof(key), IFACE_RARE_DEST_SERIALIZED_KEY, get_id());

if (!getRareDestStructRedisField(key, "checkPoint", &value)) return(false);
rareDestTraining.checkPoint = (time_t)(value);

if (!getRareDestStructRedisField(key, "initialTraining", &value)) return(false);
rareDestTraining.initialTraining = value ? true : false;

if (!getRareDestBitmapRedisField(key, "rare_dest_local", &rare_dest_local)) return(false);

if (!getRareDestBitmapRedisField(key, "rare_dest_local_bg", &rare_dest_local_bg)) {
ndpi_bitmap_free(rare_dest_local);
return(false);
}

if (!getRareDestBitmapRedisField(key, "rare_dest_remote", &rare_dest_remote)) {
ndpi_bitmap_free(rare_dest_local);
ndpi_bitmap_free(rare_dest_local_bg);
return(false);
}

if (!getRareDestBitmapRedisField(key, "rare_dest_remote_bg", &rare_dest_remote_bg)) {
ndpi_bitmap_free(rare_dest_local);
ndpi_bitmap_free(rare_dest_local_bg);
ndpi_bitmap_free(rare_dest_remote);
return(false);
}

return(true);
}
77 changes: 70 additions & 7 deletions src/flow_checks/RareDestination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,79 @@

/* ***************************************************** */

u_int32_t RareDestination::getDestinationHash(Flow *f, u_int8_t *destType) {

u_int32_t hash = 0;

if (f->isLocalToLocal()) {

*destType = 0; // local destination
LocalHost *ldest = (LocalHost*)f->get_srv_host();

if (!ldest->isLocalUnicastHost() && ldest->isDHCPHost()) {
Mac *mac = ldest->getMac();
hash = mac ? mac->key() : 0;
}
else if (ldest->isIPv6() || ldest->isIPv4()) {
hash = ldest->get_ip()->key();
}

}
else if (f->isLocalToRemote()) {
*destType = 1; // remote destination
hash = Utils::hashString(f->getFlowServerInfo());
}

return hash;
}

/* ***************************************************** */

void RareDestination::protocolDetected(Flow *f) {

bool is_rare_destination = false;

/* TODO: check if this is a real rare destination */
if (f->getFlowServerInfo() != NULL) {
#ifdef TODO_HERE
ntop->getTrace()->traceEvent(TRACE_NORMAL, "*** Rare destination %s",
f->getFlowServerInfo());
is_rare_destination = true;
#endif
if( f->get_cli_host()->isLocalHost() && (f->getFlowServerInfo() != NULL || !f->get_srv_ip_addr()->isEmpty()) ) {

time_t t_now = time(NULL);
NetworkInterface *iface = f->getInterface();

u_int8_t destType;
u_int32_t hash = getDestinationHash(f, &destType);
if(hash == 0) return;

/* initial training */
if (iface->getRareDestInitialTraining()) {
destType == 0 ? iface->setLocalRareDestBitmap(hash) : iface->setRemoteRareDestBitmap(hash);

if (!iface->getRareDestTrainingCheckPoint())
iface->setRareDestTrainingCheckPoint(t_now);

else if (t_now - iface->getRareDestTrainingCheckPoint() >= RARE_DEST_INITIAL_TRAINING_DURATION)
iface->endRareDestInitialTraining(t_now);

return;
}

/* background training */
destType == 0 ? iface->setLocalRareDestBitmap_BG(hash) : iface->setRemoteRareDestBitmap_BG(hash);

/* update bitmap */
if (destType == 0 && !iface->isSetLocalRareDestBitmap(hash)) {
is_rare_destination = true;
iface->setLocalRareDestBitmap(hash);
}

else if (destType == 1 && !iface->isSetRemoteRareDestBitmap(hash)) {
is_rare_destination = true;
iface->setRemoteRareDestBitmap(hash);
}

/* check if background training has to restart */
if (t_now - iface->getRareDestTrainingCheckPoint() >= RARE_DEST_BACKGROUND_TRAINING_DURATION) {
iface->setRareDestTrainingCheckPoint(t_now);
iface->swapRareDestBitmaps();
}
}

if (is_rare_destination) {
Expand Down