diff --git a/include/Flow.h b/include/Flow.h
index f9aac0f88e..cfadabf875 100644
--- a/include/Flow.h
+++ b/include/Flow.h
@@ -65,10 +65,11 @@ class Flow : public GenericHashEntry {
bool detection_completed, protocol_processed,
cli2srv_direction, twh_over, twh_ok, dissect_next_http_packet, passVerdict,
- check_tor, l7_protocol_guessed, flow_alerted, flow_dropped_counts_increased,
+ check_tor, l7_protocol_guessed, flow_dropped_counts_increased,
good_low_flow_detected, good_ssl_hs, update_flow_port_stats,
quota_exceeded, has_malicious_signature;
u_int16_t diff_num_http_requests;
+ int64_t alert_rowid;
#ifdef NTOPNG_PRO
bool counted_in_aggregated_flow, status_counted_in_aggregated_flow;
bool ingress2egress_direction;
@@ -485,7 +486,8 @@ class Flow : public GenericHashEntry {
&& ((dst2src_tcp_flags & (TH_SYN | TH_ACK | TH_FIN)) == (TH_SYN | TH_ACK | TH_FIN))); }
inline bool isTCPReset() const { return (!isTCPClosed()
&& ((src2dst_tcp_flags & TH_RST) || (dst2src_tcp_flags & TH_RST))); }
- inline bool isFlowAlerted() { return(flow_alerted); }
+ inline bool isFlowAlerted() { return(alert_rowid >= 0); }
+ inline void setFlowAlerted(int64_t rowid) { alert_rowid = rowid; }
inline void setVRFid(u_int32_t v) { vrfId = v; }
inline void setFlowNwLatency(const struct timeval * const tv, bool client) {
diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua
index ef02e12fa2..0d7678e371 100644
--- a/scripts/locales/en.lua
+++ b/scripts/locales/en.lua
@@ -770,6 +770,31 @@ local lang = {
["type_explorer"] = "Type Explorer",
["visual_explorer"] = "Visual Explorer",
},
+ ["flow_callbacks"] = {
+ ["application_detected"] = "Application Detected",
+ ["callback"] = "Flow Callback",
+ ["callback_config"] = "Configuration",
+ ["callback_enabled"] = "Enabled",
+ ["idle"] = "Idle",
+ ["no_callbacks_defined"] = "No callbacks found for \"%{cb}\"",
+ ["note_flow_application_detected"] = "\"Application Detected\" callbacks are executed right after the detection of the application. This occurs within the first 12 packets of a flow for packet interfaces or immediately after a flow has been received for ZMQ interfaces.",
+ ["note_flow_idle"] = "\"Idle\" callbacks are executed when a flow has terminated its activity and it has gone idle.",
+ ["note_flow_lifecycle"] = "Callbacks are executed at certain moments in the lifecycle of a flow.",
+ ["note_flow_periodic_update"] = "\"Periodic Update\" callbacks are executed periodically after a flow has been active for more than five minutes.",
+ ["note_flow_staus_changed"] = "\"Status Changed\" callbacks are executed every time there is a status change in the flow. For example when connection issues such as retransmissions are seen.",
+ ["notes"] = "NOTES",
+ ["periodic_update"] = "Periodic Update",
+ ["status_changed"] = "Status Changed",
+ },
+ ["flow_callbacks_config"] = {
+ ["blacklisted"] = "Blacklisted Flow",
+ ["blacklisted_description"] = "Trigger an alert when at least one among the client and server is blacklisted",
+ ["mud"] = "MUD",
+ ["mud_description"] = "Handle host Manufacturer usage descriptions (MUD)",
+ ["no_input"] = "No configuration necessary",
+ ["score"] = "Flow Score",
+ ["score_description"] = "Evaluate the flow and compute its score",
+ },
["flow_details"] = {
["acceptable_label"] = "Acceptable",
["actual_peak_throughput"] = "Actual / Peak Throughput",
@@ -815,6 +840,7 @@ local lang = {
["existing_rules_note"] = "Existing rules can be found at the %{name} page.",
["first_last_flow_sequence"] = "First / Last Flow Sequence",
["flow_active_msg"] = "Flow is active.",
+ ["flow_alerted"] = "Flow Alerted",
["flow_blocked_by_bridge"] = "Flow blocked due to configured policies",
["flow_cannot_be_found_message"] = "This flow cannot be found.",
["flow_completed_msg"] = "Flow is closed.",
diff --git a/scripts/lua/flow_details.lua b/scripts/lua/flow_details.lua
index 26a8f28e2e..204a42b481 100644
--- a/scripts/lua/flow_details.lua
+++ b/scripts/lua/flow_details.lua
@@ -7,6 +7,7 @@ package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local shaper_utils
require "lua_utils"
+require "alert_utils"
local format_utils = require "format_utils"
local have_nedge = ntop.isnEdge()
local NfConfig = nil
@@ -951,22 +952,38 @@ else
end
-- ######################################
-
- if interface.isPacketInterface() then
- print("
| "..i18n("flow_details.flow_status").." | ")
- for id, t in pairs(flow_consts.flow_status_types) do
- if ntop.bitmapIsSet(flow["status_map"], id) then
- print(getFlowStatus(id, flow2statusinfo(flow)).." ")
+
+ if flow["flow.alerted"] then
+ local message = nil
+
+ print(" |
|---|
| "..i18n("flow_details.flow_alerted").." | ")
+
+ if(flow["flow.alert_rowid"] ~= nil) then
+ -- Try to fetch the alert
+ local res = performAlertsQuery("SELECT *", "historical-flows", {row_id = flow["flow.alert_rowid"]})
+
+ if((res ~= nil) and (#res == 1)) then
+ message = formatAlertMessage(ifid, res[1], true --[[ skip peers, we are already showing the flow ]])
end
end
- print(" |
\n")
- if debug_score then
- if(flow["score"] > 0) then
- print("| "..i18n("flow_details.flow_score").." | "..flow["score"].." |
\n")
- end
+ print(message)
+ print("\n")
+ end
+
+ print("| "..i18n("flow_details.flow_status").." | ")
+ for id, t in pairs(flow_consts.flow_status_types) do
+ if ntop.bitmapIsSet(flow["status_map"], id) then
+ print(getFlowStatus(id, flow2statusinfo(flow)).." ")
end
end
+ print(" |
\n")
+
+ if debug_score then
+ if(flow["score"] > 0) then
+ print("| "..i18n("flow_details.flow_score").." | "..flow["score"].." |
\n")
+ end
+ end
if((flow.client_process == nil) and (flow.server_process == nil)) then
print("| "..i18n("flow_details.actual_peak_throughput").." | ")
diff --git a/scripts/lua/modules/alert_utils.lua b/scripts/lua/modules/alert_utils.lua
index 141d05fd82..df5f84f784 100644
--- a/scripts/lua/modules/alert_utils.lua
+++ b/scripts/lua/modules/alert_utils.lua
@@ -659,7 +659,7 @@ end
-- #################################
-local function formatRawFlow(record, flow_json, skip_add_links)
+local function formatRawFlow(record, flow_json, skip_add_links, skip_peers)
require "flow_utils"
local time_bounds
local add_links = (not skip_add_links)
@@ -681,7 +681,7 @@ local function formatRawFlow(record, flow_json, skip_add_links)
local status_info = alert2statusinfo(decoded)
-- active flow lookup
- if not interface.isView() and status_info and status_info["ntopng.key"] and record["alert_tstamp"] then
+ if not interface.isView() and status_info and status_info["ntopng.key"] and record["alert_tstamp"] and (not skip_peers) then
-- attempt a lookup on the active flows
local active_flow = interface.findFlowByKey(status_info["ntopng.key"])
@@ -700,7 +700,12 @@ local function formatRawFlow(record, flow_json, skip_add_links)
["srv.ip"] = record["srv_addr"], ["srv.port"] = tonumber(record["srv_port"]),
["srv.blacklisted"] = tostring(record["srv_blacklisted"]) == "1",
["vlan"] = record["vlan_id"]}
- flow = "["..i18n("flow")..": "..(getFlowLabel(flow, false, add_links, time_bounds, host_page) or "").."] "
+
+ if skip_peers then
+ flow = ""
+ else
+ flow = "["..i18n("flow")..": "..(getFlowLabel(flow, false, add_links, time_bounds, host_page) or "").."] "
+ end
local l4_proto_label = l4_proto_to_string(record["proto"] or 0) or ""
@@ -2591,11 +2596,11 @@ end
-- #################################
-function formatAlertMessage(ifid, alert)
+function formatAlertMessage(ifid, alert, skip_peers)
local msg
if(alert.alert_entity == alertEntity("flow") or (alert.alert_entity == nil)) then
- msg = formatRawFlow(alert, alert["alert_json"])
+ msg = formatRawFlow(alert, alert["alert_json"], nil, skip_peers)
else
msg = alert["alert_json"]
diff --git a/src/AlertsManager.cpp b/src/AlertsManager.cpp
index aac6508a7e..4b715a5c47 100644
--- a/src/AlertsManager.cpp
+++ b/src/AlertsManager.cpp
@@ -564,8 +564,10 @@ int AlertsManager::storeFlowAlert(Flow *f) {
if(stmt3) sqlite3_finalize(stmt3);
m.unlock(__FILE__, __LINE__);
- if((rc == 0) && (cur_rowid != (u_int64_t)-1))
+ if((rc == 0) && (cur_rowid != (u_int64_t)-1)) {
+ f->setFlowAlerted(cur_rowid);
notifyFlowAlert(cur_rowid);
+ }
if(cli) cli->incTotalAlerts(alert_type);
if(srv) srv->incTotalAlerts(alert_type);
@@ -771,8 +773,10 @@ int AlertsManager::storeFlowAlert(Flow *f, AlertType alert_type, AlertLevel aler
if(stmt3) sqlite3_finalize(stmt3);
m.unlock(__FILE__, __LINE__);
- if((rc == 0) && (cur_rowid != (u_int64_t)-1))
+ if((rc == 0) && (cur_rowid != (u_int64_t)-1)) {
+ f->setFlowAlerted(cur_rowid);
notifyFlowAlert(cur_rowid);
+ }
if(cli) cli->incTotalAlerts(alert_type);
if(srv) srv->incTotalAlerts(alert_type);
diff --git a/src/Flow.cpp b/src/Flow.cpp
index a028d298dd..31e3c0870d 100644
--- a/src/Flow.cpp
+++ b/src/Flow.cpp
@@ -45,9 +45,10 @@ Flow::Flow(NetworkInterface *_iface,
srv2cli_last_packets = 0, srv2cli_last_bytes = 0,
cli_host = srv_host = NULL, good_low_flow_detected = false,
srv2cli_last_goodput_bytes = cli2srv_last_goodput_bytes = 0, good_ssl_hs = true,
- flow_alerted = flow_dropped_counts_increased = false, vrfId = 0;
+ flow_dropped_counts_increased = false, vrfId = 0;
alert_score = CONST_NO_SCORE_SET;
+ alert_rowid = -1;
last_notified_status_map = Utils::bitmapSet(0, status_normal);
purge_acknowledged_mark = detection_completed = update_flow_port_stats = false;
ndpiDetectedProtocol = ndpiUnknownProtocol;
@@ -354,7 +355,6 @@ void Flow::dumpFlowAlert() {
if(do_dump) {
iface->getAlertsManager()->storeFlowAlert(this);
- flow_alerted = true;
if(cli_host) cli_host->incNumAlertedFlows();
if(srv_host) srv_host->incNumAlertedFlows();
@@ -2033,7 +2033,11 @@ void Flow::lua(lua_State* vm, AddressTree * ptree,
lua_push_bool_table_entry(vm, "flow.idle", idle());
lua_push_uint64_table_entry(vm, "flow.status", getFlowStatus(&status_map));
- lua_push_bool_table_entry(vm, "flow.alerted", flow_alerted);
+
+ if(isFlowAlerted()) {
+ lua_push_bool_table_entry(vm, "flow.alerted", isFlowAlerted());
+ lua_push_uint64_table_entry(vm, "flow.alert_rowid", alert_rowid);
+ }
lua_push_uint64_table_entry(vm, "status_map", status_map);
@@ -4108,7 +4112,7 @@ void Flow::postFlowSetIdle(time_t t) {
if(srv_host) srv_host->incNumAnomalousFlows(false);
}
- if(flow_alerted) {
+ if(isFlowAlerted()) {
if(cli_host) cli_host->decNumAlertedFlows();
if(srv_host) srv_host->decNumAlertedFlows();
}
|
|---|