Implements flow callbacks and alerts in C++

This commit is contained in:
Simone Mainardi 2021-03-22 09:51:36 +01:00
parent 3659188002
commit aea9138bfb
353 changed files with 10790 additions and 4455 deletions

View file

@ -802,13 +802,13 @@ else
print("</tr>")
end
local status_info = flow2statusinfo(flow)
local alert_info = flow2alertinfo(flow)
local forbidden_proto = flow["proto.ndpi_id"]
local forbidden_peer = nil
if status_info then
forbidden_proto = status_info["devproto_forbidden_id"] or forbidden_proto
forbidden_peer = status_info["devproto_forbidden_peer"]
if alert_info then
forbidden_proto = alert_info["devproto_forbidden_id"] or forbidden_proto
forbidden_peer = alert_info["devproto_forbidden_peer"]
end
local cli_mac = flow["cli.mac"] and interface.getMacInfo(flow["cli.mac"])
@ -1245,19 +1245,10 @@ else
-- ######################################
local alerted_status = nil
if flow["flow.alerted"] then
alerted_status = flow["alerted_status"]
local flow_alert = interface.flowAlertByKeyAndHashId(tonumber(flow_key), tonumber(flow_hash_id)) -- new API
local message = alert_consts.alertTypeLabel(flow["predominant_alert"])
if flow_alert then
flow_alert = json.decode(flow_alert)
end
local message = alert_utils.formatAlertMessage(ifid, flow_alert, json.decode(flow_alert["alert_json"]), true --[[ skip live data, we're already in the live flow page --]])
message = message .. string.format(" [%s: %d]", i18n("score"), flow["alerted_status_score"])
message = message .. string.format(" [%s: %d]", i18n("score"), flow["predominant_alert_score"])
print("<tr><th width=30%>"..i18n("flow_details.flow_alerted").."</th><td colspan=2>")
print(message)
@ -1265,17 +1256,17 @@ else
end
-- Print additional flow statuses
if flow["status_map"] then
if flow["alert_map"] then
local first = true
local num_statuses = 0
for _, t in pairsByKeys(alert_consts.alert_types) do
if t.meta and t.meta.status_key then
local id = t.meta.status_key
if t.meta and t.meta.alert_key then
local id = t.meta.alert_key
if id ~= flow["alerted_status"] and flow["status_map"][id] then
if id ~= flow["predominant_alert"] and flow["alert_map"][id] then
if first then
print("<tr><th width=30%>"..i18n("flow_details.additional_flow_status").."</th><td colspan=2>")
print("<tr><th width=30%>"..i18n("flow_details.additional_alert_type").."</th><td colspan=2>")
first = false
end

View file

@ -50,8 +50,8 @@ local inIfIdx = _GET["inIfIdx"]
local outIfIdx = _GET["outIfIdx"]
local traffic_type = _GET["traffic_type"]
local flow_status = _GET["flow_status"]
local flow_status_severity = _GET["flow_status_severity"]
local alert_type = _GET["alert_type"]
local alert_type_severity = _GET["alert_type_severity"]
local tcp_state = _GET["tcp_flow_state"]
local port = _GET["port"]
local network_id = _GET["network"]
@ -135,12 +135,12 @@ if(traffic_type ~= nil) then
page_params["traffic_type"] = traffic_type
end
if(flow_status ~= nil) then
page_params["flow_status"] = flow_status
if(alert_type ~= nil) then
page_params["alert_type"] = alert_type
end
if(flow_status_severity ~= nil) then
page_params["flow_status_severity"] = flow_status_severity
if(alert_type_severity ~= nil) then
page_params["alert_type_severity"] = alert_type_severity
end
if(tcp_state ~= nil) then

View file

@ -15,6 +15,7 @@ local alerts_api = require "alerts_api"
local alert_consts = require "alert_consts"
local recording_utils = require "recording_utils"
local user_scripts = require "user_scripts"
local alert_exclusions = require "alert_exclusions"
sendHTTPHeader('application/json')
@ -121,6 +122,7 @@ for k,v in ipairs(alerts) do
local column_severity = alert_consts.alertSeverityLabel(tonumber(v["alert_severity"]))
local column_type = alert_consts.alertTypeLabel(tonumber(v["alert_type"]))
local column_type_str = alert_consts.alertTypeLabel(tonumber(v["alert_type"]), true)
local column_count = format_utils.formatValue(tonumber(v["alert_counter"]))
local column_score = format_utils.formatValue(tonumber(v["score"]))
local alert_info = alert_utils.getAlertInfo(v)
@ -196,6 +198,7 @@ for k,v in ipairs(alerts) do
record["column_count"] = column_count
record["column_score"] = column_score
record["column_type"] = column_type
record["column_type_str"] = column_type_str
record["column_type_id"] = tonumber(v["alert_type"])
record["column_msg"] = column_msg
record["column_entity_id"] = alert_entity
@ -209,10 +212,11 @@ for k,v in ipairs(alerts) do
record["column_subdir"] = alert_info.alert_generation.subdir or nil
-- Checking if the filter column needs to be skipped
if user_scripts.excludeScriptFilters(alert, alert_info, record["column_script_key"], record["column_subdir"]) == false then
record["column_filter"] = user_scripts.getFilterPreset(alert, alert_info)
elseif record["column_subdir"] == "flow" then
record["column_filter_disabled"] = true
if record["column_subdir"] == "flow" then
-- Enabled, show the bell to disable
record["column_filter"] = v["cli_addr"].."|"..v["srv_addr"]
else
record["column_filter"] = user_scripts.getFilterPreset(alert, alert_info)
end
end

View file

@ -266,9 +266,9 @@ for _key, value in ipairs(flows_stats) do -- pairsByValues(vals, funct) do
end
local column_proto_l4 = ''
if value["alerted_status"] then
local status_info = alert_consts.statusTypeLabel(value["alerted_status"], true)
column_proto_l4 = alert_consts.statusTypeIcon(value["alerted_status"], value["alerted_severity"]) -- "<i class='fas fa-exclamation-triangle' style=' title='"..noHtml(status_info) .."'></i> "
if value["predominant_alert"] then
local alert_info = alert_consts.alertTypeLabel(value["predominant_alert"], true)
column_proto_l4 = alert_consts.alertTypeIcon(value["predominant_alert"], value["alerted_severity"]) -- "<i class='fas fa-exclamation-triangle' style=' title='"..noHtml(alert_info) .."'></i> "
end
column_proto_l4 = column_proto_l4..value["proto.l4"]

View file

@ -631,21 +631,25 @@ if isScoreEnabled() then
print("<tr><th rowspan=2>"..i18n("score").." " .. score_chart .."</th>")
print("<th>"..i18n("host_details.client_score").."</th><th>"..i18n("host_details.server_score").."</th></tr>")
local c = host.score_pct["score_breakdown_client"]
local s = host.score_pct["score_breakdown_server"]
local c = host.score_pct and host.score_pct["score_breakdown_client"]
local s = host.score_pct and host.score_pct["score_breakdown_server"]
print("<tr>")
print("<td>")
print("<div class='d-flex align-items-center'>")
print("<span id='score_as_client'>".. host["score.as_client"] .."</span> <span class='ml-1' id='client_score_trend'></span>")
scoreBreakdown(c)
print("<span id='score_as_client'>".. (host["score.as_client"] or 0) .."</span> <span class='ml-1' id='client_score_trend'></span>")
if c then
scoreBreakdown(c)
end
print("</div>")
print("</td>")
print("<td>")
print("<div class='d-flex align-items-center'>")
print("<span id='score_as_server'>".. host["score.as_server"] .."</span><span class='ml-1' id='server_score_trend'></span>")
scoreBreakdown(s)
print("<span id='score_as_server'>".. (host["score.as_server"] or 0).."</span><span class='ml-1' id='server_score_trend'></span>")
if s then
scoreBreakdown(s)
end
print("</div>")
print("</td>")
@ -736,7 +740,7 @@ end
if(host["active_alerted_flows"] > 0) then
print("<tr><th>"..i18n("host_details.active_alerted_flows").."</th><td colspan=2></li>"..hostinfo2detailshref(host, {page = "flows", flow_status = "alerted"}, "<span id=num_flow_alerts>"..host["active_alerted_flows"] .. "</span>").." <span id=flow_alerts_trend></span></td></tr>\n")
print("<tr><th>"..i18n("host_details.active_alerted_flows").."</th><td colspan=2></li>"..hostinfo2detailshref(host, {page = "flows", alert_type = "alerted"}, "<span id=num_flow_alerts>"..host["active_alerted_flows"] .. "</span>").." <span id=flow_alerts_trend></span></td></tr>\n")
end
if ntop.isPro() and ifstats.inline and (host["has_blocking_quota"] or host["has_blocking_shaper"]) then
@ -782,7 +786,7 @@ end
end
if interfaceHasNindexSupport() then
flows_th = flows_th .. ' <a class="btn btn-sm btn-info" href="?host='..hostinfo2hostkey(host_info)..'&page=historical&detail_view=flows&zoom=1h&flow_status=alerted"><i class="fas fa-search-plus"></i></a>'
flows_th = flows_th .. ' <a class="btn btn-sm btn-info" href="?host='..hostinfo2hostkey(host_info)..'&page=historical&detail_view=flows&zoom=1h&alert_type=alerted"><i class="fas fa-search-plus"></i></a>'
end
print("<tr><th></th><th>"..i18n("details.as_client").."</th><th>"..i18n("details.as_server").."</th></tr>\n")
@ -1717,7 +1721,7 @@ print [[
local page_params = {
application = _GET["application"],
category = _GET["category"],
flow_status = _GET["flow_status"],
alert_type = _GET["alert_type"],
tcp_flow_state = _GET["tcp_flow_state"],
flowhosts_type = _GET["flowhosts_type"],
traffic_type = _GET["traffic_type"],

View file

@ -38,7 +38,7 @@ local inIfIdx = _GET["inIfIdx"]
local outIfIdx = _GET["outIfIdx"]
local traffic_type = _GET["traffic_type"]
local flow_status = _GET["flow_status"]
local alert_type = _GET["alert_type"]
local tcp_state = _GET["tcp_flow_state"]
local port = _GET["port"]
local container = _GET["container"]
@ -115,8 +115,8 @@ if(traffic_type ~= nil) then
page_params["traffic_type"] = traffic_type
end
if(flow_status ~= nil) then
page_params["flow_status"] = flow_status
if(alert_type ~= nil) then
page_params["alert_type"] = alert_type
end
if(tcp_state ~= nil) then

View file

@ -383,12 +383,12 @@ print[[
}
if(rsp.alerted_flows_warning > 0 && !(systemInterfaceEnabled)) {
msg += "<a href=\"]] print (ntop.getHttpPrefix()) print [[/lua/flows_stats.lua?flow_status_severity=warning\">"
msg += "<a href=\"]] print (ntop.getHttpPrefix()) print [[/lua/flows_stats.lua?alert_type_severity=warning\">"
msg += "<span class=\"badge badge-warning\">"+NtopUtils.addCommas(rsp.alerted_flows_warning)+ " <i class=\"fas fa-stream\"></i> ]] print[[ <i class=\"fas fa-exclamation-triangle\"></i></span></a>";
}
if(rsp.alerted_flows_error > 0 && !(systemInterfaceEnabled)) {
msg += "<a href=\"]] print (ntop.getHttpPrefix()) print [[/lua/flows_stats.lua?flow_status_severity=error_or_higher\">"
msg += "<a href=\"]] print (ntop.getHttpPrefix()) print [[/lua/flows_stats.lua?alert_type_severity=error_or_higher\">"
msg += "<span class=\"badge badge-danger\">"+NtopUtils.addCommas(rsp.alerted_flows_error)+ " <i class=\"fas fa-stream\"></i> ]] print[[ <i class=\"fas fa-exclamation-triangle\"></i></span></a>";
}
}

View file

@ -51,10 +51,10 @@ end
-- ##############################################
function Alert:_build_flow_status_info()
local flow_status_info = {
-- TODO: remove when alerts triggered from C++
function Alert:_build_alert_type_info()
local alert_type_info = {
status_type = {
status_key = self.meta.status_key,
alert_type = self.meta,
},
alert_severity = self.alert_severity,
@ -63,14 +63,14 @@ function Alert:_build_flow_status_info()
}
if self.alert_attacker ~= nil then
flow_status_info.alert_type_params.alert_attacker = self.alert_attacker
alert_type_info.alert_type_params.alert_attacker = self.alert_attacker
end
if self.alert_victim ~= nil then
flow_status_info.alert_type_params.alert_victim = self.alert_victim
alert_type_info.alert_type_params.alert_victim = self.alert_victim
end
return flow_status_info
return alert_type_info
end
-- ##############################################
@ -95,22 +95,6 @@ end
-- ##############################################
function Alert:trigger_status(cli_score, srv_score, flow_score)
local alerts_api = require "alerts_api"
if not self.meta.status_key then
traceError(TRACE_ERROR, TRACE_CONSOLE, "alert.alert_error.configuration.no_status_key")
end
if not self._check_alert_data() then
return
end
alerts_api.trigger_status(self:_build_flow_status_info(), self.alert_severity, cli_score, srv_score, flow_score)
end
-- ##############################################
function Alert:trigger(entity_info, when, cur_alerts)
local alerts_api = require "alerts_api"

View file

@ -333,7 +333,6 @@ end
-- See alert_consts.resetDefinitions()
alert_consts.alert_types = {}
local alerts_by_id = {} -- All available alerts keyed by alert id
local alerts_by_flow_status_id = {} -- All available FLOW alerts keyed by flow status id
local function loadAlertsDefs()
if(false) then
@ -399,36 +398,27 @@ function alert_consts.loadDefinition(def_script, mod_fname, script_path)
-- Check the required metadata fields
for _, k in pairs(required_fields) do
if(def_script.meta[k] == nil) then
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Missing required field '%s' in %s from %s", k, mod_fname, script_path))
return(false)
end
if(def_script.meta[k] == nil) then
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Missing required field '%s' in %s from %s", k, mod_fname, script_path))
return(false)
end
end
-- Sanity check: make sure this is a valid alert key
local parsed_alert_key, status = alert_keys.parse_alert_key(def_script.meta.alert_key)
if not parsed_alert_key then
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Invalid alert key specified %s in %s from %s", status, mod_fname, script_path))
return(false)
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Invalid alert key specified %s in %s from %s", status, mod_fname, script_path))
return(false)
end
if(alerts_by_id[parsed_alert_key] ~= nil) then
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Alert key %d redefined, skipping in %s from %s", parsed_alert_key, mod_fname, script_path))
return(false)
end
if def_script.meta.status_key and alerts_by_flow_status_id[def_script.meta.status_key] then
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Status key %d redefined, skipping in %s from %s", def_script.meta.status_key, mod_fname, script_path))
return(false)
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Alert key %d redefined, skipping in %s from %s", parsed_alert_key, mod_fname, script_path))
return(false)
end
def_script.meta.alert_key = parsed_alert_key
alert_consts.alert_types[mod_fname] = def_script
alerts_by_id[parsed_alert_key] = mod_fname
if def_script.meta.status_key then
-- Add the module to the modules table keyd by flow status - if flow status is present for this alert
alerts_by_flow_status_id[def_script.meta.status_key] = mod_fname
end
-- Success
return(true)
@ -453,23 +443,6 @@ function alert_consts.alertTypeLabel(v, nohtml)
return(i18n("unknown"))
end
-- ##############################################
-- @brief Returns the label of an alert, given the flow status the alert is associated to
function alert_consts.statusTypeLabel(flow_status_key, nohtml)
if flow_status_key == 0 then
return i18n("flows_page.normal")
end
local alert_key = alert_consts.flowStatusTypeRaw(flow_status_key)
if alert_key then
return alert_consts.alertTypeLabel(alert_consts.alertType(alert_key), nohtml)
end
return i18n("unknown")
end
-- ##############################################
@ -477,12 +450,12 @@ end
-- @param `status info`, A human readable (localized) status info
-- @param `alerted_severity`, Integer severity of the alert associated to this status
-- @return The HTML with icon and ALT text, or empty if no icon is available
function alert_consts.statusTypeIcon(status_info, alerted_severity)
function alert_consts.alertTypeIcon(alert_info, alerted_severity)
local severity = alert_consts.alertSeverityById(alerted_severity)
if severity then
local alert_consts = require "alert_consts"
return "<i class='"..severity.icon.."' title='"..noHtml(alert_consts.statusTypeLabel(status_info, true)) .."'></i> "
return "<i class='"..severity.icon.."' title='"..noHtml(alert_consts.alertTypeLabel(alert_info, true)) .."'></i> "
end
return ""
@ -570,13 +543,6 @@ function alert_consts.alertTypeRaw(type_id)
return alerts_by_id[type_id]
end
-- ################################################################################
function alert_consts.flowStatusTypeRaw(flow_status_type_id)
flow_status_type_id = tonumber(flow_status_type_id)
return alerts_by_flow_status_id[flow_status_type_id]
end
-- ################################################################################
-- Rename engine -> granulariy

View file

@ -4,10 +4,11 @@
-- ##############################################
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
local alert_keys = require "alert_keys"
local alert_severities = require "alert_severities"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -20,12 +21,19 @@ local alert_blacklisted_country = classes.class(alert)
-- ##############################################
alert_blacklisted_country.meta = {
status_key = status_keys.ntopng.status_blacklisted_country,
alert_key = alert_keys.ntopng.alert_blacklisted_country,
i18n_title = "alerts_dashboard.blacklisted_country",
icon = "fas fa-exclamation",
has_victim = true,
has_attacker = true,
-- Default values
default = {
-- Default severity, must be one of `alert_severities` and can overridden from the UI
severity = alert_severities.error,
-- Fitlters to be applied on the alert, e.g., cli_port=23
filters = {},
}
}
-- ##############################################
@ -37,16 +45,9 @@ alert_blacklisted_country.meta = {
-- @param cli_blacklisted Boolean indicating whether the client belongs to a blacklisted country
-- @param srv_blacklisted Boolean indicating whether the server belongs to a blacklisted country
-- @return A table with the alert built
function alert_blacklisted_country:init(cli_country, srv_country, cli_blacklisted, srv_blacklisted)
function alert_blacklisted_country:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
cli_country = cli_country,
srv_country = srv_country,
cli_blacklisted = cli_blacklisted,
srv_blacklisted = srv_blacklisted,
}
end
-- #######################################################

View file

@ -7,7 +7,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
local format_utils = require "format_utils"
-- Import the classes library.
local classes = require "classes"
@ -21,8 +20,7 @@ local alert_connection_issues = classes.class(alert)
-- ##############################################
alert_connection_issues.meta = {
status_key = status_keys.ntopng.status_tcp_connection_issues,
alert_key = alert_keys.ntopng.alert_connection_issues,
alert_key = alert_keys.ntopng.alert_tcp_connection_issues,
i18n_title = "alerts_dashboard.connection_issues",
icon = "fas fa-exclamation",
}
@ -38,18 +36,9 @@ alert_connection_issues.meta = {
-- @param client_issues A boolean indicating if the client has connection issues
-- @param server_issues A boolean indicating if the server has connection issues
-- @return A table with the alert built
function alert_connection_issues:init(tcp_stats, cli2srv_pkts, srv2cli_pkts, is_severe, client_issues, server_issues)
function alert_connection_issues:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
tcp_stats = tcp_stats,
cli2srv_pkts = cli2srv_pkts,
srv2cli_pkts = srv2cli_pkts,
is_severe = is_severe,
client_issues = client_issues,
server_issues = server_issues,
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_data_exfiltration = classes.class(alert)
-- ##############################################
alert_data_exfiltration.meta = {
status_key = status_keys.ntopng.status_data_exfiltration,
alert_key = alert_keys.ntopng.alert_data_exfiltration,
i18n_title = "flow_details.data_exfiltration",
icon = "fas fa-exclamation",
@ -32,10 +30,6 @@ alert_data_exfiltration.meta = {
function alert_data_exfiltration:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -7,7 +7,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -20,7 +19,6 @@ local alert_device_protocol_not_allowed = classes.class(alert)
-- ##############################################
alert_device_protocol_not_allowed.meta = {
status_key = status_keys.ntopng.status_device_protocol_not_allowed,
alert_key = alert_keys.ntopng.alert_device_protocol_not_allowed,
i18n_title = "alerts_dashboard.suspicious_device_protocol",
icon = "fas fa-exclamation",
@ -37,16 +35,9 @@ alert_device_protocol_not_allowed.meta = {
-- @param devproto_forbidden_peer A string with the forbidden peer, one of 'cli' or 'srv'
-- @param devproto_forbidden_id The nDPI ID of the forbidden application protocol
-- @return A table with the alert built
function alert_device_protocol_not_allowed:init(cli_devtype, srv_devtype, devproto_forbidden_peer, devproto_forbidden_id)
function alert_device_protocol_not_allowed:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
["cli.devtype"] = cli_devtype,
["srv.devtype"] = srv_devtype,
devproto_forbidden_peer = devproto_forbidden_peer,
devproto_forbidden_id = devproto_forbidden_id
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_dns_data_exfiltration = classes.class(alert)
-- ##############################################
alert_dns_data_exfiltration.meta = {
status_key = status_keys.ntopng.status_dns_data_exfiltration,
alert_key = alert_keys.ntopng.alert_dns_data_exfiltration,
i18n_title = "flow_details.dns_data_exfiltration",
icon = "fas fa-exclamation",
@ -31,10 +29,6 @@ alert_dns_data_exfiltration.meta = {
function alert_dns_data_exfiltration:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_dns_invalid_query = classes.class(alert)
-- ##############################################
alert_dns_invalid_query.meta = {
status_key = status_keys.ntopng.status_dns_invalid_query,
alert_key = alert_keys.ntopng.alert_dns_invalid_query,
i18n_title = "flow_details.dns_invalid_query",
icon = "fas fa-exclamation",
@ -31,10 +29,6 @@ alert_dns_invalid_query.meta = {
function alert_dns_invalid_query:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -8,7 +8,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -16,14 +15,13 @@ local alert = require "alert"
-- ##############################################
local alert_elephant_local_to_remote = classes.class(alert)
local alert_elephant_flow = classes.class(alert)
-- ##############################################
alert_elephant_local_to_remote.meta = {
status_key = status_keys.ntopng.status_elephant_local_to_remote,
alert_key = alert_keys.ntopng.alert_elephant_local_to_remote,
i18n_title = "flow_details.elephant_flow_l2r",
alert_elephant_flow.meta = {
alert_key = alert_keys.ntopng.alert_elephant_flow,
i18n_title = "flow_details.elephant_flow",
icon = "fas fa-exclamation",
}
@ -33,14 +31,9 @@ alert_elephant_local_to_remote.meta = {
-- @param l2r_threshold Local-to-Remote threshold, in bytes, for a flow to be considered an elephant
-- @param r2l_threshold Remote-to-Local threshold, in bytes, for a flow to be considered an elephant
-- @return A table with the alert built
function alert_elephant_local_to_remote:init(l2r_threshold, r2l_threshold)
function alert_elephant_flow:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
["elephant.l2r_threshold"] = l2r_threshold,
["elephant.r2l_threshold"] = r2l_threshold,
}
end
-- #######################################################
@ -50,12 +43,12 @@ end
-- @param alert The alert description table, including alert data such as the generating entity, timestamp, granularity, type
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function alert_elephant_local_to_remote.format(ifid, alert, alert_type_params)
return formatElephantFlowStatus(alert_type_params, true --[[ l2r ]])
function alert_elephant_flow.format(ifid, alert, alert_type_params)
return formatElephantAlertType(alert_type_params)
end
-- #######################################################
return alert_elephant_local_to_remote
return alert_elephant_flow
-- #######################################################

View file

@ -3,7 +3,6 @@
--
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -17,7 +16,6 @@ local external_alert = classes.class(alert)
external_alert.meta = {
alert_key = alert_keys.ntopng.alert_external,
status_key = status_keys.ntopng.status_external_alert,
i18n_title = "alerts_dashboard.external_alert",
icon = "fas fa-eye",
status_keep_increasing_scores = true, -- Every time an external alert is set, scores are increased accordingly
@ -28,11 +26,9 @@ external_alert.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param info A generic table decoded from a JSON originated at the external alert source
-- @return A table with the alert built
function external_alert:init(info)
function external_alert:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = info
end
-- #######################################################

View file

@ -7,7 +7,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -20,8 +19,7 @@ local alert_flow_blacklisted = classes.class(alert)
-- ##############################################
alert_flow_blacklisted.meta = {
status_key = status_keys.ntopng.status_blacklisted,
alert_key = alert_keys.ntopng.alert_flow_blacklisted,
alert_key = alert_keys.ntopng.alert_blacklisted,
i18n_title = "alerts_dashboard.blacklisted_flow",
icon = "fas fa-exclamation",
has_victim = true,
@ -33,13 +31,9 @@ alert_flow_blacklisted.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param info A flow info table fetched with `flow.getBlacklistedInfo()`
-- @return A table with the alert built
function alert_flow_blacklisted:init(info)
function alert_flow_blacklisted:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
alert_type_params = info,
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_flow_blocked = classes.class(alert)
-- ##############################################
alert_flow_blocked.meta = {
status_key = status_keys.ntopng.status_blocked, -- A flow status key
alert_key = alert_keys.ntopng.alert_flow_blocked,
i18n_title = "flow_details.flow_blocked_by_bridge",
icon = "fas fa-exclamation",
@ -31,10 +29,6 @@ alert_flow_blocked.meta = {
function alert_flow_blocked:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -1,14 +1,13 @@
--
-- (C) 2019-21 - ntop.org
--
--
-- (C) 2019-21 - ntop.org
--
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local format_utils = require("format_utils")
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -16,30 +15,27 @@ local alert = require "alert"
-- ##############################################
local alert_elephant_remote_to_local = classes.class(alert)
local alert_flow_low_goodput = classes.class(alert)
-- ##############################################
alert_elephant_remote_to_local.meta = {
status_key = status_keys.ntopng.status_elephant_remote_to_local,
alert_key = alert_keys.ntopng.alert_elephant_remote_to_local,
i18n_title = "flow_details.elephant_flow_r2l",
alert_flow_low_goodput.meta = {
alert_key = alert_keys.ntopng.alert_low_goodput,
i18n_title = "alerts_dashboard.flow_low_goodput",
icon = "fas fa-exclamation",
}
-- #######################################################
-- ##############################################
-- @brief Prepare an alert table used to generate the alert
-- @param l2r_threshold Local-to-Remote threshold, in bytes, for a flow to be considered an elephant
-- @param r2l_threshold Remote-to-Local threshold, in bytes, for a flow to be considered an elephant
-- @param alert_severity A severity as defined in `alert_severities`
-- @return A table with the alert built
function alert_elephant_remote_to_local:init(l2r_threshold, r2l_threshold)
function alert_flow_low_goodput:init(goodput_ratio)
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
["elephant.l2r_threshold"] = l2r_threshold,
["elephant.r2l_threshold"] = r2l_threshold,
goodput_ratio = goodput_ratio
}
end
@ -50,12 +46,12 @@ end
-- @param alert The alert description table, including alert data such as the generating entity, timestamp, granularity, type
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function alert_elephant_remote_to_local.format(ifid, alert, alert_type_params)
return formatElephantFlowStatus(alert_type_params, false --[[ r2l ]])
function alert_flow_low_goodput.format(ifid, alert, alert_type_params)
if alert_type_params and alert_type_params.goodput_ratio then
return i18n("flow_details.flow_low_goodput", { ratio = format_utils.round(alert_type_params.goodput_ratio, 2) })
end
end
-- #######################################################
return alert_elephant_remote_to_local
-- #######################################################
return alert_flow_low_goodput

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local flow_risk_utils = require "flow_risk_utils"
@ -21,7 +20,6 @@ local alert_flow_risk = classes.class(alert)
-- ##############################################
alert_flow_risk.meta = {
status_key = status_keys.ntopng.status_flow_risk,
alert_key = alert_keys.ntopng.alert_flow_risk,
i18n_title = "alerts_dashboard.flow_risk",
icon = "fas fa-exclamation",
@ -32,13 +30,9 @@ alert_flow_risk.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param risk_id Integer nDPI flow risk identifier
-- @return A table with the alert built
function alert_flow_risk:init(risk_id)
function alert_flow_risk:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
risk_id = risk_id
}
end
-- #######################################################

View file

@ -15,13 +15,13 @@ local alert = require "alert"
-- ##############################################
local alert_iec104_error = classes.class(alert)
local alert_iec_invalid_transition = classes.class(alert)
-- ##############################################
alert_iec104_error.meta = {
alert_key = alert_keys.ntopng.alert_iec104_error,
i18n_title = "alerts_dashboard.iec104_error",
alert_iec_invalid_transition.meta = {
alert_key = alert_keys.ntopng.alert_iec_invalid_transition,
i18n_title = "alerts_dashboard.iec_invalid_transition",
icon = "fas fa-subway",
}
@ -30,13 +30,9 @@ alert_iec104_error.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param last_error A string with the lastest influxdb error
-- @return A table with the alert built
function alert_iec104_error:init(last_error)
function alert_iec_invalid_transition:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
error_msg = last_error
}
end
-- #######################################################
@ -46,7 +42,7 @@ end
-- @param alert The alert description table, including alert data such as the generating entity, timestamp, granularity, type
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function alert_iec104_error.format(ifid, alert, alert_type_params)
function alert_iec_invalid_transition.format(ifid, alert, alert_type_params)
local msg = json.decode(alert_type_params.error_msg)
local vlanId = alert.vlanId or 0
local client = ip2label(msg.client.ip, msg.vlanId)
@ -71,4 +67,4 @@ end
-- #######################################################
return alert_iec104_error
return alert_iec_invalid_transition

View file

@ -0,0 +1,63 @@
--
-- (C) 2019-21 - ntop.org
--
-- ##############################################
local alert_keys = require "alert_keys"
local json = require "dkjson"
local format_utils = require "format_utils"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
local alert = require "alert"
-- ##############################################
local alert_iec_unexpected_type_id = classes.class(alert)
-- ##############################################
alert_iec_unexpected_type_id.meta = {
alert_key = alert_keys.ntopng.alert_iec_unexpected_type_id,
i18n_title = "alerts_dashboard.iec_unexpected_type_id",
icon = "fas fa-subway",
}
-- ##############################################
-- @brief Prepare an alert table used to generate the alert
-- @param last_error A string with the lastest influxdb error
-- @return A table with the alert built
function alert_iec_unexpected_type_id:init()
-- Call the parent constructor
self.super:init()
end
-- #######################################################
-- @brief Format an alert into a human-readable string
-- @param ifid The integer interface id of the generated alert
-- @param alert The alert description table, including alert data such as the generating entity, timestamp, granularity, type
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function alert_iec_unexpected_type_id.format(ifid, alert, alert_type_params)
local msg = json.decode(alert_type_params.error_msg)
local rsp = "[CauseTX: "..msg.cause_tx.."][TypeId: "..msg.type_id.."][ASDU: ".. msg.asdu.."][Negative: "
if(msg.negatiive == false) then
rsp = rsp .. "True]"
else
rsp = rsp .. "False]"
end
-- tprint(rsp)
return(rsp)
end
-- #######################################################
return alert_iec_unexpected_type_id

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_internals = classes.class(alert)
-- ##############################################
alert_internals.meta = {
status_key = status_keys.ntopng.status_not_purged,
alert_key = alert_keys.ntopng.alert_internals,
i18n_title = "flow_details.not_purged",
icon = "fas fa-exclamation",

View file

@ -7,7 +7,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -20,7 +19,6 @@ local alert_known_proto_on_non_std_port = classes.class(alert)
-- ##############################################
alert_known_proto_on_non_std_port.meta = {
status_key = status_keys.ntopng.status_known_proto_on_non_std_port,
alert_key = alert_keys.ntopng.alert_known_proto_on_non_std_port,
i18n_title = "alerts_dashboard.known_proto_on_non_std_port",
icon = "fas fa-exclamation",
@ -32,11 +30,9 @@ alert_known_proto_on_non_std_port.meta = {
-- @param alert_severity A severity as defined in `alert_severities`
-- @param info A lua table containing flow information obtained with `flow.getInfo()`
-- @return A table with the alert built
function alert_known_proto_on_non_std_port:init(info)
function alert_known_proto_on_non_std_port:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = info
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_longlived = classes.class(alert)
-- ##############################################
alert_longlived.meta = {
status_key = status_keys.ntopng.status_longlived,
alert_key = alert_keys.ntopng.alert_longlived,
i18n_title = "flow_details.longlived_flow",
icon = "fas fa-exclamation",
@ -29,13 +27,9 @@ alert_longlived.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param longlived_threshold Threshold, in seconds, for a flow to be considered longlived
-- @return A table with the alert built
function alert_longlived:init(longlived_threshold)
function alert_longlived:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
["longlived.threshold"] = longlived_threshold
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_malicious_signature = classes.class(alert)
-- ##############################################
alert_malicious_signature.meta = {
status_key = status_keys.ntopng.status_malicious_signature, -- A flow status key
alert_key = alert_keys.ntopng.alert_malicious_signature,
i18n_title = "alerts_dashboard.malicious_signature_detected",
icon = "fas fa-ban",
@ -31,10 +29,6 @@ alert_malicious_signature.meta = {
function alert_malicious_signature:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_dns_suspicious_traffic = classes.class(alert)
-- ##############################################
alert_ndpi_dns_suspicious_traffic.meta = {
status_key = status_keys.ntopng.status_ndpi_dns_suspicious_traffic,
alert_key = alert_keys.ntopng.alert_ndpi_dns_suspicious_traffic,
i18n_title = "alerts_dashboard.ndpi_dns_suspicious_traffic_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_dns_suspicious_traffic.meta = {
function alert_ndpi_dns_suspicious_traffic:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_http_numeric_ip_host = classes.class(alert)
-- ##############################################
alert_ndpi_http_numeric_ip_host.meta = {
status_key = status_keys.ntopng.status_ndpi_http_numeric_ip_host,
alert_key = alert_keys.ntopng.alert_ndpi_http_numeric_ip_host,
i18n_title = "alerts_dashboard.ndpi_http_numeric_ip_host_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_http_numeric_ip_host.meta = {
function alert_ndpi_http_numeric_ip_host:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_http_suspicious_header = classes.class(alert)
-- ##############################################
alert_ndpi_http_suspicious_header.meta = {
status_key = status_keys.ntopng.status_ndpi_http_suspicious_header,
alert_key = alert_keys.ntopng.alert_ndpi_http_suspicious_header,
i18n_title = "alerts_dashboard.ndpi_http_suspicious_header_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_http_suspicious_header.meta = {
function alert_ndpi_http_suspicious_header:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_http_suspicious_url = classes.class(alert)
-- ##############################################
alert_ndpi_http_suspicious_url.meta = {
status_key = status_keys.ntopng.status_ndpi_http_suspicious_url,
alert_key = alert_keys.ntopng.alert_ndpi_http_suspicious_url,
i18n_title = "alerts_dashboard.ndpi_http_suspicious_url_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_http_suspicious_url.meta = {
function alert_ndpi_http_suspicious_url:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_http_suspicious_user_agent = classes.class(alert)
-- ##############################################
alert_ndpi_http_suspicious_user_agent.meta = {
status_key = status_keys.ntopng.status_ndpi_http_suspicious_user_agent,
alert_key = alert_keys.ntopng.alert_ndpi_http_suspicious_user_agent,
i18n_title = "alerts_dashboard.ndpi_http_suspicious_user_agent_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_http_suspicious_user_agent.meta = {
function alert_ndpi_http_suspicious_user_agent:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_malformed_packet = classes.class(alert)
-- ##############################################
alert_ndpi_malformed_packet.meta = {
status_key = status_keys.ntopng.status_ndpi_malformed_packet,
alert_key = alert_keys.ntopng.alert_ndpi_malformed_packet,
i18n_title = "alerts_dashboard.ndpi_malformed_packet_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_malformed_packet.meta = {
function alert_ndpi_malformed_packet:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_smb_insecure_version = classes.class(alert)
-- ##############################################
alert_ndpi_smb_insecure_version.meta = {
status_key = status_keys.ntopng.status_ndpi_smb_insecure_version,
alert_key = alert_keys.ntopng.alert_ndpi_smb_insecure_version,
i18n_title = "alerts_dashboard.ndpi_smb_insecure_version_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_smb_insecure_version.meta = {
function alert_ndpi_smb_insecure_version:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_ssh_obsolete = classes.class(alert)
-- ##############################################
alert_ndpi_ssh_obsolete.meta = {
status_key = status_keys.ntopng.status_ndpi_ssh_obsolete,
alert_key = alert_keys.ntopng.alert_ndpi_ssh_obsolete,
i18n_title = "alerts_dashboard.ndpi_ssh_obsolete_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_ssh_obsolete.meta = {
function alert_ndpi_ssh_obsolete:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_suspicious_dga_domain = classes.class(alert)
-- ##############################################
alert_ndpi_suspicious_dga_domain.meta = {
status_key = status_keys.ntopng.status_ndpi_suspicious_dga_domain,
alert_key = alert_keys.ntopng.alert_ndpi_suspicious_dga_domain,
i18n_title = "alerts_dashboard.ndpi_suspicious_dga_domain_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_suspicious_dga_domain.meta = {
function alert_ndpi_suspicious_dga_domain:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_tls_missing_sni = classes.class(alert)
-- ##############################################
alert_ndpi_tls_missing_sni.meta = {
status_key = status_keys.ntopng.status_ndpi_tls_missing_sni,
alert_key = alert_keys.ntopng.alert_ndpi_tls_missing_sni,
i18n_title = "alerts_dashboard.ndpi_tls_missing_sni_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_tls_missing_sni.meta = {
function alert_ndpi_tls_missing_sni:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_tls_not_carrying_https = classes.class(alert)
-- ##############################################
alert_ndpi_tls_not_carrying_https.meta = {
status_key = status_keys.ntopng.status_ndpi_tls_not_carrying_https,
alert_key = alert_keys.ntopng.alert_ndpi_tls_not_carrying_https,
i18n_title = "alerts_dashboard.ndpi_tls_not_carrying_https_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_tls_not_carrying_https.meta = {
function alert_ndpi_tls_not_carrying_https:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_tls_suspicious_esni_usage = classes.class(alert)
-- ##############################################
alert_ndpi_tls_suspicious_esni_usage.meta = {
status_key = status_keys.ntopng.status_ndpi_tls_suspicious_esni_usage,
alert_key = alert_keys.ntopng.alert_ndpi_tls_suspicious_esni_usage,
i18n_title = "alerts_dashboard.ndpi_tls_suspicious_esni_usage_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_tls_suspicious_esni_usage.meta = {
function alert_ndpi_tls_suspicious_esni_usage:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_unsafe_protocol = classes.class(alert)
-- ##############################################
alert_ndpi_unsafe_protocol.meta = {
status_key = status_keys.ntopng.status_ndpi_unsafe_protocol,
alert_key = alert_keys.ntopng.alert_ndpi_unsafe_protocol,
i18n_title = "alerts_dashboard.ndpi_unsafe_protocol_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_unsafe_protocol.meta = {
function alert_ndpi_unsafe_protocol:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_url_possible_rce_injection = classes.class(alert)
-- ##############################################
alert_ndpi_url_possible_rce_injection.meta = {
status_key = status_keys.ntopng.status_ndpi_url_possible_rce_injection,
alert_key = alert_keys.ntopng.alert_ndpi_url_possible_rce_injection,
i18n_title = "alerts_dashboard.ndpi_url_possible_rce_injection_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_url_possible_rce_injection.meta = {
function alert_ndpi_url_possible_rce_injection:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_url_possible_sql_injection = classes.class(alert)
-- ##############################################
alert_ndpi_url_possible_sql_injection.meta = {
status_key = status_keys.ntopng.status_ndpi_url_possible_sql_injection,
alert_key = alert_keys.ntopng.alert_ndpi_url_possible_sql_injection,
i18n_title = "alerts_dashboard.ndpi_url_possible_sql_injection_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_url_possible_sql_injection.meta = {
function alert_ndpi_url_possible_sql_injection:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -6,7 +6,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -19,7 +18,6 @@ local alert_ndpi_url_possible_xss = classes.class(alert)
-- ##############################################
alert_ndpi_url_possible_xss.meta = {
status_key = status_keys.ntopng.status_ndpi_url_possible_xss,
alert_key = alert_keys.ntopng.alert_ndpi_url_possible_xss,
i18n_title = "alerts_dashboard.ndpi_url_possible_xss_title",
icon = "fas fa-exclamation",
@ -32,8 +30,6 @@ alert_ndpi_url_possible_xss.meta = {
function alert_ndpi_url_possible_xss:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,8 +17,7 @@ local alert_potentially_dangerous_protocol = classes.class(alert)
-- ##############################################
alert_potentially_dangerous_protocol.meta = {
status_key = status_keys.ntopng.status_potentially_dangerous,
alert_key = alert_keys.ntopng.alert_potentially_dangerous_protocol,
alert_key = alert_keys.ntopng.alert_potentially_dangerous,
i18n_title = "flow_details.potentially_dangerous_protocol",
icon = "fas fa-exclamation",
}
@ -31,10 +29,6 @@ alert_potentially_dangerous_protocol.meta = {
function alert_potentially_dangerous_protocol:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -9,7 +9,6 @@ package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local format_utils = require "format_utils"
local json = require("dkjson")
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -22,7 +21,6 @@ local alert_remote_to_local_insecure_proto = classes.class(alert)
-- ##############################################
alert_remote_to_local_insecure_proto.meta = {
status_key = status_keys.ntopng.status_remote_to_local_insecure_proto,
alert_key = alert_keys.ntopng.alert_remote_to_local_insecure_proto,
i18n_title = "alerts_dashboard.remote_to_local_insecure_proto",
icon = "fas fa-exclamation",
@ -34,32 +32,18 @@ alert_remote_to_local_insecure_proto.meta = {
-- @param one_flow_param The first alert param
-- @param another_flow_param The second alert param
-- @return A table with the alert built
function alert_remote_to_local_insecure_proto:init(proto, category_name, breed_or_category)
function alert_remote_to_local_insecure_proto:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
proto = proto,
category_name = category_name,
breed_or_category = breed_or_category,
}
end
-- #######################################################
function alert_remote_to_local_insecure_proto.format(ifid, alert, alert_type_params)
if breed_or_category == false then
return i18n("alert_messages.remote_to_local_insecure_proto_category", {
proto = alert_type_params.category_name,
proto_id = alert_type_params.proto,
})
else
return i18n("alert_messages.remote_to_local_insecure_proto_breed", {
proto = alert_type_params.proto,
})
end
return i18n("alert_messages.remote_to_local_insecure_proto", {
ndpi_breed = formatBreed(alert_type_params.ndpi_breed_name),
ndpi_category = alert_type_params.ndpi_category_name,
})
end
-- #######################################################

View file

@ -9,7 +9,6 @@ package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local format_utils = require "format_utils"
local json = require("dkjson")
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -22,7 +21,6 @@ local alert_remote_to_remote = classes.class(alert)
-- ##############################################
alert_remote_to_remote.meta = {
status_key = status_keys.ntopng.status_remote_to_remote,
alert_key = alert_keys.ntopng.alert_remote_to_remote,
i18n_title = "alerts_dashboard.remote_to_remote",
icon = "fas fa-exclamation",
@ -35,9 +33,6 @@ alert_remote_to_remote.meta = {
function alert_remote_to_remote:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
}
end
-- #######################################################

View file

@ -32,14 +32,9 @@ alert_request_reply_ratio.meta = {
-- @param requests The number of requests
-- @param replies The number of replies
-- @return A table with the alert built
function alert_request_reply_ratio:init(requests, replies)
function alert_request_reply_ratio:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
requests = requests,
replies = replies,
}
end
-- #######################################################

View file

@ -7,7 +7,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!

View file

@ -7,7 +7,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -20,7 +19,6 @@ local alert_suspicious_file_transfer = classes.class(alert)
-- ##############################################
alert_suspicious_file_transfer.meta = {
status_key = status_keys.ntopng.status_suspicious_file_transfer,
alert_key = alert_keys.ntopng.alert_suspicious_file_transfer,
i18n_title = "alerts_dashboard.suspicious_file_transfer",
icon = "fas fa-file-download",
@ -32,11 +30,9 @@ alert_suspicious_file_transfer.meta = {
-- @param one_flow_param The first alert param
-- @param another_flow_param The second alert param
-- @return A table with the alert built
function alert_suspicious_file_transfer:init(http_info)
function alert_suspicious_file_transfer:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = http_info
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_suspicious_tcp_probing = classes.class(alert)
-- ##############################################
alert_suspicious_tcp_probing.meta = {
status_key = status_keys.ntopng.status_suspicious_tcp_probing,
alert_key = alert_keys.ntopng.alert_suspicious_tcp_probing,
i18n_title = "flow_details.suspicious_tcp_probing",
icon = "fas fa-exclamation",
@ -31,10 +29,6 @@ alert_suspicious_tcp_probing.meta = {
function alert_suspicious_tcp_probing:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_suspicious_tcp_syn_probing = classes.class(alert)
-- ##############################################
alert_suspicious_tcp_syn_probing.meta = {
status_key = status_keys.ntopng.status_suspicious_tcp_syn_probing,
alert_key = alert_keys.ntopng.alert_suspicious_tcp_syn_probing,
i18n_title = "flow_details.suspicious_tcp_syn_probing",
icon = "fas fa-exclamation",
@ -31,10 +29,6 @@ alert_suspicious_tcp_syn_probing.meta = {
function alert_suspicious_tcp_syn_probing:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_tcp_connection_refused = classes.class(alert)
-- ##############################################
alert_tcp_connection_refused.meta = {
status_key = status_keys.ntopng.status_tcp_connection_refused,
alert_key = alert_keys.ntopng.alert_tcp_connection_refused,
i18n_title = "flow_details.tcp_connection_refused",
icon = "fas fa-exclamation",
@ -31,10 +29,6 @@ alert_tcp_connection_refused.meta = {
function alert_tcp_connection_refused:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_tls_certificate_expired = classes.class(alert)
-- ##############################################
alert_tls_certificate_expired.meta = {
status_key = status_keys.ntopng.status_tls_certificate_expired,
alert_key = alert_keys.ntopng.alert_tls_certificate_expired,
i18n_title = "flow_details.tls_certificate_expired",
icon = "fas fa-exclamation",
@ -29,16 +27,9 @@ alert_tls_certificate_expired.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param tls_info A lua table with TLS info gererated calling `flow.getTLSInfo()`
-- @return A table with the alert built
function alert_tls_certificate_expired:init(tls_info)
function alert_tls_certificate_expired:init()
-- Call the parent constructor
self.super:init()
tls_info = tls_info or {}
self.alert_type_params = {
["tls_crt.notBefore"] = tls_info["protos.tls.notBefore"],
["tls_crt.notAfter"] = tls_info["protos.tls.notAfter"],
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_tls_certificate_mismatch = classes.class(alert)
-- ##############################################
alert_tls_certificate_mismatch.meta = {
status_key = status_keys.ntopng.status_tls_certificate_mismatch,
alert_key = alert_keys.ntopng.alert_tls_certificate_mismatch,
i18n_title = "flow_details.tls_certificate_mismatch",
icon = "fas fa-exclamation",
@ -29,18 +27,9 @@ alert_tls_certificate_mismatch.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param tls_info A lua table with TLS info gererated calling `flow.getTLSInfo()`
-- @return A table with the alert built
function alert_tls_certificate_mismatch:init(tls_info)
function alert_tls_certificate_mismatch:init()
-- Call the parent constructor
self.super:init()
tls_info = tls_info or {}
local server_cn = tls_info["protos.tls.server_names"] or ""
local client_cn = tls_info["protos.tls.client_requested_server_name"] or ""
self.alert_type_params = {
["tls_crt.cli"] = client_cn,
["tls_crt.srv"] = server_cn,
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_tls_certificate_selfsigned = classes.class(alert)
-- ##############################################
alert_tls_certificate_selfsigned.meta = {
status_key = status_keys.ntopng.status_tls_certificate_selfsigned,
alert_key = alert_keys.ntopng.alert_tls_certificate_selfsigned,
i18n_title = "flow_details.tls_certificate_selfsigned",
icon = "fas fa-exclamation",
@ -29,15 +27,9 @@ alert_tls_certificate_selfsigned.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param tls_info A lua table with TLS info gererated calling `flow.getTLSInfo()`
-- @return A table with the alert built
function alert_tls_certificate_selfsigned:init(tls_info)
function alert_tls_certificate_selfsigned:init()
-- Call the parent constructor
self.super:init()
tls_info = tls_info or {}
self.alert_type_params = {
["tls_crt.issuerDN"] = tls_info["protos.tls.issuerDN"] or "",
}
end
-- #######################################################
@ -55,7 +47,15 @@ function alert_tls_certificate_selfsigned.format(ifid, alert, alert_type_params)
local crts = {}
crts[#crts + 1] = alert_type_params["tls_crt.issuerDN"]
return string.format("[Issuer/Subject: %s]", table.concat(crts, " - "))
if alert_type_params["protos.tls.issuerDN"] then
crts[#crts + 1] = "Issuer: "..alert_type_params["protos.tls.issuerDN"]
end
if alert_type_params["protos.tls.subjectDN"] then
crts[#crts + 1] = "Subject: "..alert_type_params["protos.tls.subjectDN"]
end
return string.format("%s", table.concat(crts, " / "))
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_tls_old_protocol_version = classes.class(alert)
-- ##############################################
alert_tls_old_protocol_version.meta = {
status_key = status_keys.ntopng.status_tls_old_protocol_version,
alert_key = alert_keys.ntopng.alert_tls_old_protocol_version,
i18n_title = "flow_details.tls_old_protocol_version",
icon = "fas fa-exclamation",
@ -29,13 +27,9 @@ alert_tls_old_protocol_version.meta = {
-- @brief Prepare an alert table used to generate the alert
-- @param tls_version A number indicating the TLS version detected, or nil when version is not available
-- @return A table with the alert built
function alert_tls_old_protocol_version:init(tls_version)
function alert_tls_old_protocol_version:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
tls_version = tls_version,
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_tls_unsafe_ciphers = classes.class(alert)
-- ##############################################
alert_tls_unsafe_ciphers.meta = {
status_key = status_keys.ntopng.status_tls_unsafe_ciphers,
alert_key = alert_keys.ntopng.alert_tls_unsafe_ciphers,
i18n_title = "flow_details.tls_unsafe_ciphers",
icon = "fas fa-exclamation",
@ -31,10 +29,6 @@ alert_tls_unsafe_ciphers.meta = {
function alert_tls_unsafe_ciphers:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
-- No params
}
end
-- #######################################################

View file

@ -7,7 +7,6 @@
local alert_keys = require "alert_keys"
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -20,7 +19,6 @@ local alert_udp_unidirectional = classes.class(alert)
-- ##############################################
alert_udp_unidirectional.meta = {
status_key = status_keys.ntopng.status_udp_unidirectional,
alert_key = alert_keys.ntopng.alert_udp_unidirectional,
i18n_title = "flow_details.udp_unidirectional",
icon = "fas fa-info-circle",
@ -33,8 +31,6 @@ alert_udp_unidirectional.meta = {
function alert_udp_unidirectional:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################

View file

@ -62,4 +62,4 @@ end
-- #######################################################
return alert_unexpected_behaviour
return alert_unexpected_behaviour

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_unexpected_dhcp_server = classes.class(alert)
-- ##############################################
alert_unexpected_dhcp_server.meta = {
status_key = status_keys.ntopng.status_unexpected_dhcp_server,
alert_key = alert_keys.ntopng.alert_unexpected_dhcp_server,
i18n_title = "unexpected_dhcp.alert_unexpected_dhcp_title",
icon = "fas fa-exclamation",
@ -32,14 +30,9 @@ alert_unexpected_dhcp_server.meta = {
-- @param one_flow_param The first alert param
-- @param another_flow_param The second alert param
-- @return A table with the alert built
function alert_unexpected_dhcp_server:init(client_ip, server_ip)
function alert_unexpected_dhcp_server:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
client_ip = client_ip,
server_ip = server_ip
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_unexpected_dns_server = classes.class(alert)
-- ##############################################
alert_unexpected_dns_server.meta = {
status_key = status_keys.ntopng.status_unexpected_dns_server,
alert_key = alert_keys.ntopng.alert_unexpected_dns_server,
i18n_title = "unexpected_dns.alert_unexpected_dns_title",
icon = "fas fa-exclamation",
@ -32,14 +30,9 @@ alert_unexpected_dns_server.meta = {
-- @param one_flow_param The first alert param
-- @param another_flow_param The second alert param
-- @return A table with the alert built
function alert_unexpected_dns_server:init(client_ip, server_ip)
function alert_unexpected_dns_server:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
client_ip = client_ip,
server_ip = server_ip
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_unexpected_ntp_server = classes.class(alert)
-- ##############################################
alert_unexpected_ntp_server.meta = {
status_key = status_keys.ntopng.status_unexpected_ntp_server,
alert_key = alert_keys.ntopng.alert_unexpected_ntp_server,
i18n_title = "unexpected_ntp.alert_unexpected_ntp_title",
icon = "fas fa-exclamation",
@ -32,14 +30,9 @@ alert_unexpected_ntp_server.meta = {
-- @param one_flow_param The first alert param
-- @param another_flow_param The second alert param
-- @return A table with the alert built
function alert_unexpected_ntp_server:init(client_ip, server_ip)
function alert_unexpected_ntp_server:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
client_ip = client_ip,
server_ip = server_ip
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_unexpected_smtp_server = classes.class(alert)
-- ##############################################
alert_unexpected_smtp_server.meta = {
status_key = status_keys.ntopng.status_unexpected_smtp_server,
alert_key = alert_keys.ntopng.alert_unexpected_smtp_server,
i18n_title = "unexpected_smtp.alert_unexpected_smtp_title",
icon = "fas fa-exclamation",
@ -28,14 +26,9 @@ alert_unexpected_smtp_server.meta = {
-- ##############################################
function alert_unexpected_smtp_server:init(client_ip, server_ip)
function alert_unexpected_smtp_server:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
client_ip = client_ip,
server_ip = server_ip
}
end
-- #######################################################

View file

@ -5,7 +5,6 @@
-- ##############################################
local alert_keys = require "alert_keys"
local status_keys = require "status_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
@ -18,7 +17,6 @@ local alert_web_mining = classes.class(alert)
-- ##############################################
alert_web_mining.meta = {
status_key = status_keys.ntopng.status_web_mining_detected,
alert_key = alert_keys.ntopng.alert_web_mining,
i18n_title = "alerts_dashboard.web_mining",
icon = "fab fa-bitcoin",
@ -33,8 +31,6 @@ alert_web_mining.meta = {
function alert_web_mining:init()
-- Call the parent constructor
self.super:init()
self.alert_type_params = {}
end
-- #######################################################
@ -49,4 +45,4 @@ return alert_web_mining
--
-- (C) 2019-20 - ntop.
-- (C) 2019-20 - ntop.

View file

@ -0,0 +1,49 @@
--
-- (C) 2019-21 - ntop.org
--
-- ##############################################
local alert_keys = require "alert_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
local alert = require "alert"
-- ##############################################
local alert_zero_tcp_window = classes.class(alert)
-- ##############################################
alert_zero_tcp_window.meta = {
alert_key = alert_keys.ntopng.alert_zero_tcp_window,
i18n_title = "zero_tcp_window.zero_tcp_window_title",
icon = "fas fa-arrow-circle-up",
}
-- ##############################################
-- @brief Prepare an alert table used to generate the alert
-- @param one_flow_param The first alert param
-- @param another_flow_param The second alert param
-- @return A table with the alert built
function alert_zero_tcp_window:init(is_client, is_server)
-- Call the parent constructor
self.super:init()
end
-- #######################################################
-- @brief Format an alert into a human-readable string
-- @param ifid The integer interface id of the generated alert
-- @param alert The alert description table, including alert data such as the generating entity, timestamp, granularity, type
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function alert_zero_tcp_window.format(ifid, alert, alert_type_params)
return i18n("zero_tcp_window.status_zero_tcp_window_description")
end
-- #######################################################
return alert_zero_tcp_window

View file

@ -0,0 +1,189 @@
--
-- (C) 2017-21 - ntop.org
--
-- Module to keep things in common across alert_exclusions of various type
local dirs = ntop.getDirs()
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
require "lua_utils"
local alert_consts = require "alert_consts"
local json = require "dkjson"
-- ##############################################
local alert_exclusions = {}
-- ##############################################
local function _get_alert_exclusions_prefix_key()
local key = string.format("ntopng.prefs.alert_exclusions")
return key
end
-- ##############################################
local function _get_alert_exclusions_lock_key()
local key = string.format("ntopng.cache.alert_exclusions.alert_exclusions_lock")
return key
end
-- ##############################################
local function _lock()
local max_lock_duration = 5 -- seconds
local max_lock_attempts = 5 -- give up after at most this number of attempts
local lock_key = _get_alert_exclusions_lock_key()
for i = 1, max_lock_attempts do
local value_set = ntop.setnxCache(lock_key, "1", max_lock_duration)
if value_set then
return true -- lock acquired
end
ntop.msleep(1000)
end
return false -- lock not acquired
end
-- ##############################################
local function _unlock()
ntop.delCache(_get_alert_exclusions_lock_key())
end
-- ##############################################
local function _check_host_ip_alert_key(host_ip, alert_key)
if not isIPv4(host_ip) and not isIPv6(host_ip) then
-- Invalid host submitted
return false
end
if not alert_consts.alertTypeRaw(tonumber(alert_key)) then
-- Invalid alert key submitted
return false
end
return true
end
-- ##############################################
local function _get_configured_alert_exclusions()
local excl_key = _get_alert_exclusions_prefix_key()
local configured_excl_str = ntop.getPref(excl_key)
local configured_excl = json.decode(configured_excl_str) or {}
return configured_excl
end
-- ##############################################
local function _set_configured_alert_exclusions(exclusions)
local excl_key = _get_alert_exclusions_prefix_key()
ntop.setPref(excl_key, json.encode(exclusions)) -- Add the preference
ntop.reloadAlertExclusions() -- Tell ntopng to reload
end
-- ##############################################
--@brief Enables or disables an alert for an `host_ip`
local function _toggle_alert(host_ip, alert_key, disable)
local ret = false
if not _check_host_ip_alert_key(host_ip, alert_key) then
-- Invalid params submitted
return false
end
local locked = _lock()
if locked then
-- In JSON, keys are always strings
alert_key = tostring(alert_key)
local do_persist = false
local exclusions = _get_configured_alert_exclusions()
-- Add an entry for the current alert key, if currently existing exclusions don't already have it
if not exclusions[alert_key] then
exclusions[alert_key] = {excluded_hosts = {}}
end
-- Add an entry for excluded_hosts, if the currently existing exclusions don't already have it
if not exclusions[alert_key]["excluded_hosts"] then
exclusions[alert_key]["excluded_hosts"] = {}
end
-- Now check if there is actually some work to do
if not disable and exclusions[alert_key]["excluded_hosts"][host_ip] then
-- Enable an host_ip that was disabled
exclusions[alert_key]["excluded_hosts"][host_ip] = nil
do_persist = true
elseif disable and not exclusions[alert_key]["excluded_hosts"][host_ip] then
-- Disable an host_ip that was not already disabled
exclusions[alert_key]["excluded_hosts"][host_ip] = { --[[ Currently empty, will possibly contain values in the future, e.g., as_cli, as_srv--]]}
do_persist = true
end
if do_persist then
_set_configured_alert_exclusions(exclusions)
end
ret = true
_unlock()
end
return ret
end
-- ##############################################
--@brief Marks an alert as disabled for a given `host_ip`
--@return True, if alert is disabled with success, false otherwise
function alert_exclusions.disable_alert(host_ip, alert_key)
return _toggle_alert(host_ip, alert_key, true --[[ disable --]])
end
-- ##############################################
--@brief Marks an alert as enabled for a given `host_ip`
--@return True, if alert is enabled with success, false otherwise
function alert_exclusions.enable_alert(host_ip, alert_key)
return _toggle_alert(host_ip, alert_key, false --[[ enable --]])
end
-- ##############################################
-- @brief Returns true if `host_ip` has the alert identified with `alert_key` disabled
function alert_exclusions.has_disabled_alert(host_ip, alert_key)
local exclusions = _get_configured_alert_exclusions()
alert_key = tostring(alert_key)
return not not (exclusions[alert_key] and exclusions[alert_key]["excluded_hosts"] and exclusions[alert_key]["excluded_hosts"][host_ip])
end
-- ##############################################
-- @brief Delete all alert_exclusions
function alert_exclusions.cleanup()
local locked = _lock()
if locked then
local excl_key = _get_alert_exclusions_prefix_key()
ntop.delCache(excl_key)
ntop.reloadAlertExclusions() -- Tell ntopng to reload
_unlock()
end
end
-- ##############################################
return alert_exclusions

View file

@ -11,126 +11,141 @@ local NO_PEN = 0
-- ##############################################
local BASE_ID = 1024 -- This is the first id reserved for non-flow-statuses.
-- ##############################################
local alert_keys = {
ntopng = {
alert_blacklisted_country = {NO_PEN, 1},
alert_broadcast_domain_too_large = {NO_PEN, 2},
alert_device_connection = {NO_PEN, 3},
alert_device_disconnection = {NO_PEN, 4},
alert_device_protocol_not_allowed = {NO_PEN, 5},
alert_dropped_alerts = {NO_PEN, 6},
alert_external = {NO_PEN, 7},
alert_flow_blacklisted = {NO_PEN, 8},
alert_flow_blocked = {NO_PEN, 9},
alert_flow_misbehaviour = {NO_PEN, 10}, -- No longer used
alert_flows_flood = {NO_PEN, 11}, -- No longer used, check alert_flows_flood_attacker and alert_flows_flood_victim
alert_ghost_network = {NO_PEN, 12},
alert_host_pool_connection = {NO_PEN, 13},
alert_host_pool_disconnection = {NO_PEN, 14},
alert_influxdb_dropped_points = {NO_PEN, 15},
alert_influxdb_error = {NO_PEN, 16},
alert_influxdb_export_failure = {NO_PEN, 17},
alert_internals = {NO_PEN, 18},
alert_ip_outsite_dhcp_range = {NO_PEN, 19},
alert_list_download_failed = {NO_PEN, 20},
alert_login_failed = {NO_PEN, 21},
alert_mac_ip_association_change = {NO_PEN, 22},
alert_malicious_signature = {NO_PEN, 23},
alert_misbehaving_flows_ratio = {NO_PEN, 24},
alert_misconfigured_app = {NO_PEN, 25},
alert_new_device = {NO_PEN, 26}, -- No longer used
alert_nfq_flushed = {NO_PEN, 27},
alert_none = {NO_PEN, 28}, -- No longer used
alert_periodic_activity_not_executed = {NO_PEN, 29},
alert_am_threshold_cross = {NO_PEN, 30},
alert_port_duplexstatus_change = {NO_PEN, 31},
alert_port_errors = {NO_PEN, 32},
alert_port_load_threshold_exceeded = {NO_PEN, 33},
alert_port_mac_changed = {NO_PEN, 34},
alert_port_status_change = {NO_PEN, 35},
alert_potentially_dangerous_protocol = {NO_PEN, 36},
alert_process_notification = {NO_PEN, 37},
alert_quota_exceeded = {NO_PEN, 38},
alert_remote_to_remote = {NO_PEN, 39},
alert_request_reply_ratio = {NO_PEN, 40},
alert_slow_periodic_activity = {NO_PEN, 41},
alert_slow_purge = {NO_PEN, 42},
alert_snmp_device_reset = {NO_PEN, 43},
alert_snmp_topology_changed = {NO_PEN, 44},
alert_suspicious_activity = {NO_PEN, 45}, -- No longer used
alert_tcp_syn_flood = {NO_PEN, 46}, -- No longer used, check alert_tcp_syn_flood_attacker and alert_tcp_syn_flood_victim
alert_tcp_syn_scan = {NO_PEN, 47}, -- No longer used, check alert_tcp_syn_scan_attacker and alert_tcp_syn_scan_victim
alert_test_failed = {NO_PEN, 48},
alert_threshold_cross = {NO_PEN, 49},
alert_too_many_drops = {NO_PEN, 50},
alert_udp_unidirectional = {NO_PEN, 51},
alert_unresponsive_device = {NO_PEN, 52},
alert_user_activity = {NO_PEN, 53},
alert_user_script_calls_drops = {NO_PEN, 54},
alert_web_mining = {NO_PEN, 55},
alert_connection_issues = {NO_PEN, 56},
alert_suspicious_file_transfer = {NO_PEN, 57},
alert_known_proto_on_non_std_port = {NO_PEN, 58},
alert_host_log = {NO_PEN, 59},
alert_attack_mitigation_via_snmp = {NO_PEN, 60},
alert_iec104_error = {NO_PEN, 61},
alert_flow_risk = {NO_PEN, 62},
alert_unexpected_dns_server = {NO_PEN, 63},
alert_unexpected_smtp_server = {NO_PEN, 64},
alert_unexpected_dhcp_server = {NO_PEN, 65},
alert_unexpected_ntp_server = {NO_PEN, 66},
alert_too_many_retransmissions = {NO_PEN, 67}, -- No longer used
alert_lateral_movement = {NO_PEN, 68},
alert_list_download_succeeded = {NO_PEN, 69},
alert_no_if_activity = {NO_PEN, 70}, -- scripts/plugins/alerts/internals/no_if_activity
alert_zero_tcp_window = {NO_PEN, 71},
alert_flow_low_goodput = {NO_PEN, 72},
alert_unexpected_new_device = {NO_PEN, 73}, -- scripts/plugins/alerts/security/unexpected_new_device
alert_shell_script_executed = {NO_PEN, 74}, -- scripts/plugins/endpoints/shell_alert_endpoint
alert_periodicity_update = {NO_PEN, 75}, -- pro/scripts/enterprise_l_plugins/alerts/network/periodicity_update
alert_dns_positive_error_ratio = {NO_PEN, 76}, -- pro/scripts/enterprise_l_plugins/alerts/network/dns_positive_error_ratio
alert_elephant_local_to_remote = {NO_PEN, 77},
alert_elephant_remote_to_local = {NO_PEN, 78},
alert_longlived = {NO_PEN, 79},
alert_tls_old_protocol_version = {NO_PEN, 80},
alert_tls_certificate_mismatch = {NO_PEN, 81},
alert_tls_certificate_expired = {NO_PEN, 82},
alert_tls_unsafe_ciphers = {NO_PEN, 83},
alert_tls_certificate_selfsigned = {NO_PEN, 84},
alert_data_exfiltration = {NO_PEN, 85},
alert_dns_data_exfiltration = {NO_PEN, 86},
alert_tcp_connection_refused = {NO_PEN, 87},
alert_suspicious_tcp_syn_probing = {NO_PEN, 88},
alert_suspicious_tcp_probing = {NO_PEN, 89},
alert_dns_invalid_query = {NO_PEN, 90},
alert_iec_invalid_transition = {NO_PEN, 91},
alert_fail2ban_executed = {NO_PEN, 92}, -- pro/scripts/pro_plugins/endpoints/fail2ban_alert_endpoint
alert_flows_flood_attacker = {NO_PEN, 93},
alert_flows_flood_victim = {NO_PEN, 94},
alert_tcp_syn_flood_attacker = {NO_PEN, 95},
alert_tcp_syn_flood_victim = {NO_PEN, 96},
alert_tcp_syn_scan_attacker = {NO_PEN, 97},
alert_tcp_syn_scan_victim = {NO_PEN, 98},
alert_remote_to_local_insecure_proto = {NO_PEN, 99},
alert_contacted_peers = {NO_PEN, 100},
alert_unexpected_behaviour = {NO_PEN, 101},
alert_ndpi_url_possible_xss = {NO_PEN, 102},
alert_ndpi_url_possible_sql_injection = {NO_PEN, 103},
alert_ndpi_url_possible_rce_injection = {NO_PEN, 104},
alert_ndpi_http_suspicious_user_agent = {NO_PEN, 105},
alert_ndpi_http_numeric_ip_host = {NO_PEN, 106},
alert_ndpi_http_suspicious_url = {NO_PEN, 107},
alert_ndpi_http_suspicious_header = {NO_PEN, 108},
alert_ndpi_tls_not_carrying_https = {NO_PEN, 109},
alert_ndpi_suspicious_dga_domain = {NO_PEN, 110},
alert_ndpi_malformed_packet = {NO_PEN, 111},
alert_ndpi_ssh_obsolete = {NO_PEN, 112},
alert_ndpi_smb_insecure_version = {NO_PEN, 113},
alert_ndpi_tls_suspicious_esni_usage = {NO_PEN, 114},
alert_ndpi_unsafe_protocol = {NO_PEN, 115},
alert_ndpi_dns_suspicious_traffic = {NO_PEN, 116},
alert_ndpi_tls_missing_sni = {NO_PEN, 117},
-- First 1024 (0 to 1023) IDs reserved for flow status alerts.
-- Flow statuses are a Bitmap of 128 bits. 1024 is just to keep a safe margin
-- and possibly enlarge Bitmap in the future
-- NOTE: Keep them in sync with ntop_typedefs.h FlowAlertType
alert_normal = {NO_PEN, 0},
alert_blacklisted = {NO_PEN, 1},
alert_blacklisted_country = {NO_PEN, 2},
alert_flow_blocked = {NO_PEN, 3},
alert_data_exfiltration = {NO_PEN, 4},
alert_device_protocol_not_allowed = {NO_PEN, 5},
alert_dns_data_exfiltration = {NO_PEN, 6},
alert_dns_invalid_query = {NO_PEN, 7},
alert_elephant_flow = {NO_PEN, 8},
alert_elephant_remote_to_local = {NO_PEN, 9}, -- No longer used, can be recycled
alert_external = {NO_PEN, 10},
alert_longlived = {NO_PEN, 11},
alert_low_goodput = {NO_PEN, 12},
alert_malicious_signature = {NO_PEN, 13},
alert_internals = {NO_PEN, 14},
alert_potentially_dangerous = {NO_PEN, 15},
alert_remote_to_remote = {NO_PEN, 16},
alert_suspicious_tcp_probing = {NO_PEN, 17},
alert_suspicious_tcp_syn_probing = {NO_PEN, 18},
alert_tcp_connection_issues = {NO_PEN, 19},
alert_tcp_connection_refused = {NO_PEN, 20},
alert_tcp_severe_connection_issues = {NO_PEN, 21},
alert_tls_certificate_expired = {NO_PEN, 22},
alert_tls_certificate_mismatch = {NO_PEN, 23},
alert_tls_old_protocol_version = {NO_PEN, 24},
alert_tls_unsafe_ciphers = {NO_PEN, 25},
alert_udp_unidirectional = {NO_PEN, 26},
alert_web_mining = {NO_PEN, 27},
alert_tls_certificate_selfsigned = {NO_PEN, 28},
alert_suspicious_file_transfer = {NO_PEN, 29},
alert_known_proto_on_non_std_port = {NO_PEN, 30},
alert_flow_risk = {NO_PEN, 31},
alert_unexpected_dhcp_server = {NO_PEN, 32},
alert_unexpected_dns_server = {NO_PEN, 33},
alert_unexpected_smtp_server = {NO_PEN, 34},
alert_unexpected_ntp_server = {NO_PEN, 35},
alert_zero_tcp_window = {NO_PEN, 36},
alert_iec_invalid_transition = {NO_PEN, 37},
alert_remote_to_local_insecure_proto = {NO_PEN, 38},
alert_ndpi_url_possible_xss = {NO_PEN, 39},
alert_ndpi_url_possible_sql_injection = {NO_PEN, 40},
alert_ndpi_url_possible_rce_injection = {NO_PEN, 41},
alert_ndpi_http_suspicious_user_agent = {NO_PEN, 42},
alert_ndpi_http_numeric_ip_host = {NO_PEN, 43},
alert_ndpi_http_suspicious_url = {NO_PEN, 44},
alert_ndpi_http_suspicious_header = {NO_PEN, 45},
alert_ndpi_tls_not_carrying_https = {NO_PEN, 46},
alert_ndpi_suspicious_dga_domain = {NO_PEN, 47},
alert_ndpi_malformed_packet = {NO_PEN, 48},
alert_ndpi_ssh_obsolete = {NO_PEN, 49},
alert_ndpi_smb_insecure_version = {NO_PEN, 50},
alert_ndpi_tls_suspicious_esni_usage = {NO_PEN, 51},
alert_ndpi_unsafe_protocol = {NO_PEN, 52},
alert_ndpi_dns_suspicious_traffic = {NO_PEN, 53},
alert_ndpi_tls_missing_sni = {NO_PEN, 54},
alert_iec_unexpected_type_id = {NO_PEN, 55},
-- NOTE: for flow alerts not not go beyond the size of Bitmap alert_map inside Flow.h (currently 128)
--
-- Here we have statuses >= 1024 that are reserved for non-flows
--
alert_broadcast_domain_too_large = {NO_PEN, BASE_ID },
alert_device_connection = {NO_PEN, BASE_ID + 1 },
alert_device_disconnection = {NO_PEN, BASE_ID + 2 },
alert_dropped_alerts = {NO_PEN, BASE_ID + 3 },
alert_flow_misbehaviour = {NO_PEN, BASE_ID + 4 }, -- No longer used
alert_flows_flood = {NO_PEN, BASE_ID + 5 }, -- No longer used, check alert_flows_flood_attacker and alert_flows_flood_victim
alert_ghost_network = {NO_PEN, BASE_ID + 6 },
alert_host_pool_connection = {NO_PEN, BASE_ID + 7 },
alert_host_pool_disconnection = {NO_PEN, BASE_ID + 8 },
alert_influxdb_dropped_points = {NO_PEN, BASE_ID + 9 },
alert_influxdb_error = {NO_PEN, BASE_ID + 10},
alert_influxdb_export_failure = {NO_PEN, BASE_ID + 11},
alert_ip_outsite_dhcp_range = {NO_PEN, BASE_ID + 13},
alert_list_download_failed = {NO_PEN, BASE_ID + 14},
alert_login_failed = {NO_PEN, BASE_ID + 15},
alert_mac_ip_association_change = {NO_PEN, BASE_ID + 16},
alert_misbehaving_flows_ratio = {NO_PEN, BASE_ID + 17},
alert_misconfigured_app = {NO_PEN, BASE_ID + 18},
alert_new_device = {NO_PEN, BASE_ID + 19}, -- No longer used
alert_nfq_flushed = {NO_PEN, BASE_ID + 20},
alert_none = {NO_PEN, BASE_ID + 21}, -- No longer used
alert_periodic_activity_not_executed = {NO_PEN, BASE_ID + 22},
alert_am_threshold_cross = {NO_PEN, BASE_ID + 23},
alert_port_duplexstatus_change = {NO_PEN, BASE_ID + 24},
alert_port_errors = {NO_PEN, BASE_ID + 25},
alert_port_load_threshold_exceeded = {NO_PEN, BASE_ID + 26},
alert_port_mac_changed = {NO_PEN, BASE_ID + 27},
alert_port_status_change = {NO_PEN, BASE_ID + 28},
alert_process_notification = {NO_PEN, BASE_ID + 29},
alert_quota_exceeded = {NO_PEN, BASE_ID + 30},
alert_request_reply_ratio = {NO_PEN, BASE_ID + 31},
alert_slow_periodic_activity = {NO_PEN, BASE_ID + 32},
alert_slow_purge = {NO_PEN, BASE_ID + 33},
alert_snmp_device_reset = {NO_PEN, BASE_ID + 34},
alert_snmp_topology_changed = {NO_PEN, BASE_ID + 35},
alert_suspicious_activity = {NO_PEN, BASE_ID + 36}, -- No longer used
alert_tcp_syn_flood = {NO_PEN, BASE_ID + 37}, -- No longer used, check alert_tcp_syn_flood_attacker and alert_tcp_syn_flood_victim
alert_tcp_syn_scan = {NO_PEN, BASE_ID + 38}, -- No longer used, check alert_tcp_syn_scan_attacker and alert_tcp_syn_scan_victim
alert_test_failed = {NO_PEN, BASE_ID + 39},
alert_threshold_cross = {NO_PEN, BASE_ID + 40},
alert_too_many_drops = {NO_PEN, BASE_ID + 41},
alert_unresponsive_device = {NO_PEN, BASE_ID + 42},
alert_user_activity = {NO_PEN, BASE_ID + 43},
alert_user_script_calls_drops = {NO_PEN, BASE_ID + 44},
alert_host_log = {NO_PEN, BASE_ID + 45},
alert_attack_mitigation_via_snmp = {NO_PEN, BASE_ID + 46},
alert_iec104_error = {NO_PEN, BASE_ID + 47}, -- No longer used
alert_lateral_movement = {NO_PEN, BASE_ID + 48},
alert_list_download_succeeded = {NO_PEN, BASE_ID + 49},
alert_no_if_activity = {NO_PEN, BASE_ID + 50}, -- scripts/plugins/alerts/internals/no_if_activity
alert_unexpected_new_device = {NO_PEN, BASE_ID + 51}, -- scripts/plugins/alerts/security/unexpected_new_device
alert_shell_script_executed = {NO_PEN, BASE_ID + 52}, -- scripts/plugins/endpoints/shell_alert_endpoint
alert_periodicity_update = {NO_PEN, BASE_ID + 53}, -- pro/scripts/enterprise_l_plugins/alerts/network/periodicity_update
alert_dns_positive_error_ratio = {NO_PEN, BASE_ID + 54}, -- pro/scripts/enterprise_l_plugins/alerts/network/dns_positive_error_ratio
alert_fail2ban_executed = {NO_PEN, BASE_ID + 55}, -- pro/scripts/pro_plugins/endpoints/fail2ban_alert_endpoint
alert_flows_flood_attacker = {NO_PEN, BASE_ID + 56},
alert_flows_flood_victim = {NO_PEN, BASE_ID + 57},
alert_tcp_syn_flood_attacker = {NO_PEN, BASE_ID + 58},
alert_tcp_syn_flood_victim = {NO_PEN, BASE_ID + 59},
alert_tcp_syn_scan_attacker = {NO_PEN, BASE_ID + 60},
alert_tcp_syn_scan_victim = {NO_PEN, BASE_ID + 61},
alert_contacted_peers = {NO_PEN, BASE_ID + 62},
alert_unexpected_behaviour = {NO_PEN, BASE_ID + 63},
-- Add here additional keys for alerts generated
-- by ntopng plugins

View file

@ -9,12 +9,43 @@ local json = require "dkjson"
local rest_utils = require "rest_utils"
local user_scripts = require "user_scripts"
local alert_utils = require "alert_utils"
local alert_exclusions = require "alert_exclusions"
local alert_rest_utils = {}
-- #################################
-- @brief exclude an alert using the parameters that the POST has
function _exclude_flow_alert(additional_filters, delete_alerts)
local success = false
local alert_key = tonumber(_POST["alert_key"])
local alert_addr = _POST["alert_addr"]
if alert_key and alert_addr then
success = true
end
if success then
if alert_addr then
alert_exclusions.disable_alert(alert_addr, alert_key)
if delete_alerts == "true" then
alert_utils.deleteFlowAlertsMatching(alert_addr, alert_key)
end
end
end
if success then
rc = rest_utils.consts.success.ok
rest_utils.answer(rc)
else
rc = rest_utils.consts.err.invalid_args
rest_utils.answer(rc)
end
end
-- #################################
-- @brief exclude an alert using the parameters that the POST has
function alert_rest_utils.exclude_alert()
-- POST parameters
@ -31,11 +62,15 @@ function alert_rest_utils.exclude_alert()
-- Parameters used for the rest answer
local rc = ""
local res = ""
if subdir == "flow" then
return _exclude_flow_alert(additional_filters, delete_alerts)
end
-- Checking that all parameters where given to the POST
if not additional_filters or not subdir or not script_key then
rest_utils.answer(rest_utils.consts.err.invalid_args)
return
return
end
-- Getting the parameters

View file

@ -443,6 +443,25 @@ end
-- #################################
--@brief Deletes all stored alerts matching an host and an IP
-- @return nil
function alert_utils.deleteFlowAlertsMatching(host_ip, alert_key)
local res = {}
local statement = "DELETE "
-- This is to match elements inside the alert_json
local where = {
string.format("(cli_addr = '%s' OR srv_addr = '%s')", host_ip, host_ip),
string.format("alert_type = %u", alert_key),
}
where = table.concat(where, " AND ")
res = interface.queryFlowAlertsRaw(statement, where, nil, true)
end
-- #################################
-- this function returns an object with parameters specific for one tab
function alert_utils.getTabParameters(_get, what)
local opts = {}
@ -508,24 +527,24 @@ end
-- #################################
-- Return more information for the flow alert description
local function getFlowStatusInfo(record, status_info)
local function getAlertTypeInfo(record, alert_info)
local res = ""
local l7proto_name = interface.getnDPIProtoName(tonumber(record["l7_proto"]) or 0)
if l7proto_name == "ICMP" then -- is ICMPv4
-- TODO: old format - remove when the all the flow alers will be generated in lua
local type_code = {type = status_info["icmp.icmp_type"], code = status_info["icmp.icmp_code"]}
local type_code = {type = alert_info["icmp.icmp_type"], code = alert_info["icmp.icmp_code"]}
if table.empty(type_code) and status_info["icmp"] then
if table.empty(type_code) and alert_info["icmp"] then
-- This is the new format created when setting the alert from lua
type_code = {type = status_info["icmp"]["type"], code = status_info["icmp"]["code"]}
type_code = {type = alert_info["icmp"]["type"], code = alert_info["icmp"]["code"]}
end
if status_info["icmp.unreach.src_ip"] then -- TODO: old format to be removed
res = string.format("[%s]", i18n("icmp_page.icmp_port_unreachable_extra", {unreach_host=status_info["icmp.unreach.dst_ip"], unreach_port=status_info["icmp.unreach.dst_port"], unreach_protocol = l4_proto_to_string(status_info["icmp.unreach.protocol"])}))
elseif status_info["icmp"] and status_info["icmp"]["unreach"] then -- New format
res = string.format("[%s]", i18n("icmp_page.icmp_port_unreachable_extra", {unreach_host=status_info["icmp"]["unreach"]["dst_ip"], unreach_port=status_info["icmp"]["unreach"]["dst_port"], unreach_protocol = l4_proto_to_string(status_info["icmp"]["unreach"]["protocol"])}))
if alert_info["icmp.unreach.src_ip"] then -- TODO: old format to be removed
res = string.format("[%s]", i18n("icmp_page.icmp_port_unreachable_extra", {unreach_host=alert_info["icmp.unreach.dst_ip"], unreach_port=alert_info["icmp.unreach.dst_port"], unreach_protocol = l4_proto_to_string(alert_info["icmp.unreach.protocol"])}))
elseif alert_info["icmp"] and alert_info["icmp"]["unreach"] then -- New format
res = string.format("[%s]", i18n("icmp_page.icmp_port_unreachable_extra", {unreach_host=alert_info["icmp"]["unreach"]["dst_ip"], unreach_port=alert_info["icmp"]["unreach"]["dst_port"], unreach_protocol = l4_proto_to_string(alert_info["icmp"]["unreach"]["protocol"])}))
else
res = string.format("[%s]", icmp_utils.get_icmp_label(4 --[[ ipv4 --]], type_code["type"], type_code["code"]))
end
@ -548,8 +567,8 @@ local function formatRawFlow(ifid, alert, alert_json)
end
-- TODO: adapter just to be compatible with old alerts, can be removed at some point
if alert_json["status_info"] then
alert_json = json.decode(alert_json["status_info"])
if alert_json["alert_info"] then
alert_json = json.decode(alert_json["alert_info"])
end
-- active flow lookup
@ -606,7 +625,7 @@ local function formatRawFlow(ifid, alert, alert_json)
end
if alert_json then
flow = flow..getFlowStatusInfo(alert, alert_json)
flow = flow..getAlertTypeInfo(alert, alert_json)
end
return flow
@ -944,12 +963,11 @@ function alert_utils.drawAlertTables(has_past_alerts, has_engaged_alerts, has_fl
template.gen("modal_alert_filter_dialog.html", {
dialog={
id = "filter_alert_dialog",
action = "filterAlertByFilters(subdir, script_key)",
action = "filterAlertByFilters(subdir, script_key, alert_key)",
title = i18n("show_alerts.filter_alert"),
message = i18n("show_alerts.confirm_filter_alert"),
delete_message = i18n("show_alerts.confirm_delete_filtered_alerts"),
field_input_title = i18n("current_filter"),
delete_alerts = i18n("delete_alerts"),
delete_alerts = i18n("delete_disabled_alerts"),
alert_filter = "default_filter",
confirm = i18n("filter"),
confirm_button = "btn-warning",
@ -958,6 +976,23 @@ function alert_utils.drawAlertTables(has_past_alerts, has_engaged_alerts, has_fl
)
-- Filtering for flow alerts
print(
template.gen("modal_flow_alerts_filter_dialog.html", {
dialog={
id = "flow_alerts_filter_dialog",
action = "filterFlowAlerts(alert_key)",
title = i18n("show_alerts.filter_alert"),
message = i18n("show_alerts.confirm_filter_alert"),
delete_message = i18n("show_alerts.confirm_delete_filtered_alerts"),
delete_alerts = i18n("delete_disabled_alerts"),
alert_filter = "default_filter",
confirm = i18n("filter"),
confirm_button = "btn-warning",
}
})
)
print(
template.gen("modal_confirm_dialog.html", {
@ -1089,7 +1124,7 @@ function deleteAlertById(alert_key) {
form.appendTo('body').submit();
}
function filterAlertByFilters(subdir, script_key) {
function filterAlertByFilters(subdir, script_key, alert_key) {
$.ajax({
type: 'POST',
contentType: "application/json",
@ -1099,6 +1134,7 @@ function filterAlertByFilters(subdir, script_key) {
filters: document.getElementById("name_input").value,
subdir: subdir,
script_key: script_key,
alert_key: alert_key,
status: getCurrentStatus(),
delete_alerts: $('#delete_alert_switch').prop('checked'),
csrf: "]] print(ntop.getRandomCSRFValue()) print[[",
@ -1115,6 +1151,31 @@ function filterAlertByFilters(subdir, script_key) {
});
}
function filterFlowAlerts(alert_key) {
$.ajax({
type: 'POST',
contentType: "application/json",
dataType: "json",
url: `${http_prefix}/lua/rest/v1/edit/user_script/filter.lua`,
data: JSON.stringify({
alert_addr: $("input[name='alert_addr']:checked").val(),
subdir: "flow",
alert_key: alert_key,
delete_alerts: $('#delete_flow_alerts_switch').prop('checked'),
csrf: "]] print(ntop.getRandomCSRFValue()) print[[",
}),
success: function(rsp) {
let get_params = NtopUtils.paramsExtend(]] print(tableToJsObject(alert_utils.getTabParameters(url_params, nil))) print[[, {status:getCurrentStatus()});
get_params.csrf = "]] print(ntop.getRandomCSRFValue()) print[[";
let form = NtopUtils.paramsToForm('<form method="post"></form>', get_params);
form.appendTo('body').submit();
},
error: function(rsp) {
$("#filter_alert_dialog_error").text(rsp.responseJSON.rsp).show();
},
});
}
var alert_to_toggle = null;
var alert_to_release = null;
@ -1386,8 +1447,18 @@ function releaseAlert(idx) {
var data = table_data[row_id];
var explorer_url = data["column_explorer"];
if(data["column_filter"]) {
datatableAddFilterButtonCallback.bind(this)(10, "subdir = '" + data["column_subdir"] + "'; script_key = '" + data["column_script_key"] + "'; $('#name_input').attr('value', '" + data["column_filter"] + "'); $('#filter_alert_dialog').modal('show');", "<i class='fas fa-bell-slash'></i>", "]] print(i18n("filter")) print[[");
if(data["column_filter"] && data["column_subdir"] == "flow") {
/* Extract client and server address that come into column_filter concatenated with a pipe */
const cli_srv_addr = data["column_filter"].split('|'), cli_addr = cli_srv_addr[0], srv_addr = cli_srv_addr[1];
/* Populate client and server radio buttons */
const srv_radio = " $('#srv_radio').attr('value', '" + srv_addr + "'); $('#srv_addr').html('" + srv_addr + "'); ";
const cli_radio = " $('#cli_radio').attr('value', '" + cli_addr + "'); $('#cli_addr').html('" + cli_addr + "'); ";
const alert_label = "$('.alert_label').html('" + data["column_type_str"] + "'); ";
console.log(alert_label);
datatableAddFilterButtonCallback.bind(this)(10, "alert_key = '" + data["column_type_id"] + "'; " + alert_label + srv_radio + cli_radio + " $('#flow_alerts_filter_dialog').modal('show');", "<i class='fas fa-bell-slash'></i>", "]] print(i18n("filter")) print[[");
} else if(data["column_filter"]) {
datatableAddFilterButtonCallback.bind(this)(10, "alert_key = '" + data["column_type_id"] + "'; alert_label = $('.alert_label').html('" + data["column_type_str"] + "'); subdir = '" + data["column_subdir"] + "'; script_key = '" + data["column_script_key"] + "'; $('#name_input').attr('value', '" + data["column_filter"] + "'); $('#filter_alert_dialog').modal('show');", "<i class='fas fa-bell-slash'></i>", "]] print(i18n("filter")) print[[");
} else if(data["column_filter_disabled"]) {
datatableAddFilterButtonCallback.bind(this)(10, "subdir = ''; script_key = '';", "<i class='fas fa-bell-slash'></i>", "]] print(i18n("filter")) print[[", false); }
@ -1893,7 +1964,7 @@ end
-- #################################
function alert_utils.getConfigsetAlertLink(alert_json)
local info = alert_json.alert_generation or (alert_json.status_info and alert_json.status_info.alert_generation)
local info = alert_json.alert_generation or (alert_json.alert_info and alert_json.alert_info.alert_generation)
if(info and isAdministrator()) then
return(' <a href="'.. ntop.getHttpPrefix() ..'/lua/admin/edit_configset.lua?'..

View file

@ -153,15 +153,6 @@ local function addAlertHostInfo(triggered)
end
end
-- ##############################################
--! @param type_info data returned by one of the type_info building functions
function alerts_api.trigger_status(type_info, alert_severity, cli_score, srv_score, flow_score)
type_info.status_type.alert_severity = alert_severity
flow.triggerStatus(type_info, flow_score, cli_score, srv_score)
end
-- ##############################################
--@brief Check if the `alert` belongs to an exclusion list

View file

@ -0,0 +1,102 @@
--
-- (C) 2013-21 - ntop.org
--
local dirs = ntop.getDirs()
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local alert_consts = require "alert_consts"
local alert_severities = require "alert_severities"
-- ##############################################
local alerts_config = {}
-- ##############################################
local CONFIGSET_KEY = "ntopng.prefs.alerts_config.configset_v1" -- Keep in sync with ntop_defines.h FLOW_CALLBACKS_CONFIG
-- ##############################################
local function saveConfigset(configset)
local v = json.encode(configset)
ntop.setCache(CONFIGSET_KEY, v)
-- Reload the periodic scripts as the configuration has changed
ntop.reloadPeriodicScripts()
-- TODO: Reload flow alerts in C++
-- ntop.reloadFlowAlerts()
return true
end
-- ##############################################
local cached_config_set = nil
-- Return the default config set
-- Note: Other config sets are deprecated
function alerts_config.getConfigset()
if not cached_config_set then
cached_config_set = json.decode(ntop.getCache(CONFIGSET_KEY))
end
return cached_config_set
end
-- ##############################################
-- @brief Initializes a default configuration for user scripts
-- @param overwrite If true, a possibly existing configuration is overwritten with default values
function alerts_config.initDefaultConfig()
-- Current (possibly not-existing, not yet created configset)
local configset = alerts_config.getConfigset() or {}
for alert_type, alert in pairs(alert_consts.alert_types) do
-- Alert metadata, including the alert key
local meta = alert.meta
if not configset[alert_type] then
-- This is a new alert, prepare to fill it with defaults
configset[alert_type] = {}
end
-- Populate config severity
if not configset[alert_type]["severity"] then
-- No severity found in the configuration, let's add a default
local alert_severity = meta.default and meta.default.severity
if not alert_severity then
traceError(TRACE_NORMAL, TRACE_CONSOLE, string.format("Alert %s has no default severity, assuming 'notice'", alert_type))
alert_severity = alert_severities.notice
end
configset[alert_type]["severity"] = alert_severity.severity_id
end
-- Populate config filters
if not configset[alert_type]["filters"] then
-- No filters found in the configuration, let's see if there are default filters and add them
local alert_filters = meta.default and meta.default.filters
configset[alert_type]["filters"] = alert_filters or {}
end
saveConfigset(configset)
end
end
-- ##############################################
function alerts_config.resetConfigset()
cached_config_set = nil
ntop.delCache(CONFIGSET_KEY)
alerts_config.initDefaultConfig()
return(true)
end
-- ##############################################
return(alerts_config)

View file

@ -0,0 +1,441 @@
--
-- (C) 2017-21 - ntop.org
--
-- Module to keep things in common across control_groups of various type
local dirs = ntop.getDirs()
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
require "lua_utils"
local json = require "dkjson"
-- ##############################################
local control_groups = {}
-- ##############################################
-- This is the minimum control_group id which will be used to create new control_groups
control_groups.MIN_ASSIGNED_CONTROL_GROUP_ID = 0
-- ##############################################
local function _get_control_groups_prefix_key()
local key = string.format("ntopng.prefs.control_groups")
return key
end
-- ##############################################
local function _get_control_group_ids_key()
local key = string.format("%s.control_group_ids", _get_control_groups_prefix_key())
return key
end
-- ##############################################
local function _get_control_group_lock_key()
local key = string.format("ntopng.cache.control_groups.control_group_lock")
return key
end
-- ##############################################
local function _get_control_group_details_key(control_group_id)
if not control_group_id then
-- A control_group id is always needed
return nil
end
local key = string.format("%s.control_group_id_%d.details", _get_control_groups_prefix_key(), control_group_id)
return key
end
-- ##############################################
-- @brief Returns an array with all the currently assigned control_group ids
local function _get_assigned_control_group_ids()
local res = {}
local cur_control_group_ids = ntop.getMembersCache(_get_control_group_ids_key())
for _, cur_control_group_id in pairs(cur_control_group_ids) do
cur_control_group_id = tonumber(cur_control_group_id)
res[#res + 1] = cur_control_group_id
end
return res
end
-- ##############################################
local function _assign_control_group_id()
-- OVERRIDE
-- To stay consistent with the old implementation control_groups_nedge.lua
-- control_group_ids are re-used. This means reading the set of currently used control_group
-- ids, and chosing the minimum not available control_group id
-- This method is called from functions which perform locks so
-- there's no risk to assign the same id multiple times
local cur_control_group_ids = _get_assigned_control_group_ids()
local next_control_group_id = control_groups.MIN_ASSIGNED_CONTROL_GROUP_ID
-- Find the first available control_group id which is not in the set
for _, control_group_id in pairsByValues(cur_control_group_ids, asc) do
if control_group_id > next_control_group_id then break end
next_control_group_id = math.max(control_group_id + 1, next_control_group_id)
end
ntop.setMembersCache(_get_control_group_ids_key(), string.format("%d", next_control_group_id))
return next_control_group_id
end
-- ##############################################
local function _lock()
local max_lock_duration = 5 -- seconds
local max_lock_attempts = 5 -- give up after at most this number of attempts
local lock_key = _get_control_group_lock_key()
for i = 1, max_lock_attempts do
local value_set = ntop.setnxCache(lock_key, "1", max_lock_duration)
if value_set then
return true -- lock acquired
end
ntop.msleep(1000)
end
return false -- lock not acquired
end
-- ##############################################
local function _unlock()
ntop.delCache(_get_control_group_lock_key())
end
-- ##############################################
-- @brief Persist control_group details to disk. Possibly assign a control_group id
-- @param control_group_id The control_group_id of the control_group which needs to be persisted. If nil, a new control_group id is assigned
local function _persist(control_group_id, name, members, disabled_alerts)
local control_group_details_key = _get_control_group_details_key(control_group_id)
local control_group_details = {
name = name,
members = members or {},
disabled_alerts = disabled_alerts or {}
}
ntop.setCache(control_group_details_key, json.encode(control_group_details))
ntop.reloadControlGroups()
-- Return the assigned control_group_id
return control_group_id
end
-- ##############################################
function control_groups.add_control_group(name, members)
local locked = _lock()
if locked then
if name and members then
local checks_ok = true
-- Check if duplicate names exist
local same_name_control_group = control_groups.get_control_group_by_name(name)
if same_name_control_group then
checks_ok = false
end
-- Check if members are valid
if check_ok and not control_groups.are_valid_members(members) then
checks_ok = false
end
if checks_ok then
-- All the checks have succeeded
-- Now that everything is ok, the id can be assigned and the control_group can be persisted with the assigned id
control_group_id = _assign_control_group_id()
_persist(control_group_id, name, members)
end
end
_unlock()
end
return control_group_id
end
-- ##############################################
function control_groups.edit_control_group(control_group_id, new_name, new_members)
local ret = false
local locked = _lock()
-- If here, control_group_id has been found
if locked then
-- Make sure the control_group exists
local cur_details = control_groups.get_control_group(control_group_id)
if cur_details and new_name then
local checks_ok = true
if not new_members then
-- In case members have not been sumbitted, new_members
-- are assumed to be the existing members
new_members = cur_details["members"]
end
-- Check if new_name is not the name of any other existing control_group
local same_name_control_group = control_groups.get_control_group_by_name(new_name)
if same_name_control_group and same_name_control_group.control_group_id ~= control_group_id then
checks_ok = false
end
-- Check if members are valid
if checks_ok and not control_groups.are_valid_members(new_members) then
checks_ok = false
end
if checks_ok then
-- If here, all checks are valid and the control_group can be edited
_persist(control_group_id, new_name, new_members, cur_details["disabled_alerts"])
-- Control_Group edited successfully
ret = true
end
end
_unlock()
end
return ret
end
-- ##############################################
--@brief Marks an alert as disabled for a given control group identified with `control_group_id`
--@return True, if alert is disabled with success, false otherwise
function control_groups.disable_control_group_flow_alert(control_group_id, alert_key)
local ret = false
local locked = _lock()
-- If here, control_group_id has been found
if locked then
-- Make sure the control_group exists
local cur_details = control_groups.get_control_group(control_group_id)
if cur_details then
local checks_ok = true
-- Check if alert_key is already disabled
for _, disabled_alert in pairs(cur_details["disabled_alerts"]) do
if tonumber(alert_key) == disabled_alert then
checks_ok = false -- Already present, nothing to do
break
end
end
if checks_ok then
-- Disable the alert
cur_details["disabled_alerts"][#cur_details["disabled_alerts"] + 1] = tonumber(alert_key)
-- If here, all checks are valid and the control_group can be edited
_persist(control_group_id, cur_details["name"], cur_details["members"], cur_details["disabled_alerts"])
-- Control_Group edited successfully
ret = true
end
end
_unlock()
end
return ret
end
-- ##############################################
--@brief Marks an alert as disabled for a given control group identified with `control_group_id`
--@return True, if alert is disabled with success, false otherwise
function control_groups.enable_control_group_flow_alert(control_group_id, alert_key)
local ret = false
local locked = _lock()
-- If here, control_group_id has been found
if locked then
-- Make sure the control_group exists
local cur_details = control_groups.get_control_group(control_group_id)
if cur_details then
local new_disabled_alerts = {}
local checks_ok = false
-- Check if alert_key is among disabled alerts
for _, disabled_alert in pairs(cur_details["disabled_alerts"]) do
if tonumber(alert_key) == disabled_alert then
checks_ok = true -- Present among the disabled alerts, can remove it
-- Don't break, finish the loop to prepare `new_disabled_alerts`
else
new_disabled_alerts[#new_disabled_alerts + 1] = disabled_alert
end
end
if checks_ok then
-- If here, all checks are valid and the control_group can be edited
_persist(control_group_id, cur_details["name"], cur_details["members"], new_disabled_alerts)
-- Control_Group edited successfully
ret = true
end
end
_unlock()
end
return ret
end
-- ##############################################
function control_groups.delete_control_group(control_group_id)
local ret = false
local locked = _lock()
if locked then
-- Make sure the control_group exists
local cur_details = control_groups.get_control_group(control_group_id)
if cur_details then
-- Remove the key with all the control_group details (e.g., with members)
ntop.delCache(_get_control_group_details_key(control_group_id))
-- Remove the control_group_id from the set of all currently existing control_group ids
ntop.delMembersCache(_get_control_group_ids_key(), string.format("%d", control_group_id))
-- Tell the core to reload control groups
ntop.reloadControlGroups()
ret = true
end
_unlock()
end
return ret
end
-- ##############################################
-- @brief Returns all the defined control_groups. Control_Groups are returned in a lua table with control_group ids as keys
function control_groups.get_all_control_groups()
local cur_control_group_ids = _get_assigned_control_group_ids()
local res = {}
for _, control_group_id in pairs(cur_control_group_ids) do
local control_group_details = control_groups.get_control_group(control_group_id)
if control_group_details then res[#res + 1] = control_group_details end
end
return res
end
-- ##############################################
-- @brief Returns the number of currently defined control_group ids
function control_groups.get_num_control_groups()
local cur_control_group_ids = _get_assigned_control_group_ids()
return #cur_control_group_ids
end
-- ##############################################
function control_groups.get_control_group(control_group_id, recipient_details)
local recipient_details = recipient_details or true
local control_group_details
local control_group_details_key = _get_control_group_details_key(control_group_id)
-- Attempt at retrieving the control_group details key and at decoding it from JSON
if control_group_details_key then
local control_group_details_str = ntop.getCache(control_group_details_key)
control_group_details = json.decode(control_group_details_str)
if control_group_details then
-- Add the integer control_group id
control_group_details["control_group_id"] = tonumber(control_group_id)
end
end
-- Upon success, control_group details are returned, otherwise nil
return control_group_details
end
-- ##############################################
-- @brief Delete all control_groups
function control_groups.cleanup()
-- Delete control_group details
local cur_control_group_ids = _get_assigned_control_group_ids()
for _, control_group_id in pairs(cur_control_group_ids) do
control_groups.delete_control_group(control_group_id)
end
local locked = _lock()
if locked then
-- Delete control_group ids
ntop.delCache(_get_control_group_ids_key())
_unlock()
end
end
-- ##############################################
-- @brief Returns a boolean indicating whether the member is a valid control_group member
function control_groups.is_valid_member(member)
return isIPv4Network(member)
end
-- ##############################################
-- @brief Returns a boolean indicating whether the array of members passed contains all valid members
function control_groups.are_valid_members(members)
for _, member in pairs(members) do
if not control_groups.is_valid_member(member) then
return false
end
end
return true
end
-- ##############################################
function control_groups.get_control_group_by_name(name)
local cur_control_group_ids = _get_assigned_control_group_ids()
for _, control_group_id in pairs(cur_control_group_ids) do
local control_group_details = control_groups.get_control_group(control_group_id)
if control_group_details and control_group_details["name"] and control_group_details["name"] == name then
return control_group_details
end
end
return nil
end
-- ##############################################
return control_groups

View file

@ -50,20 +50,20 @@ end
-- #######################
-- Extracts the information serialized into status_info from the flow
-- Extracts the information serialized into alert_info from the flow
-- user scripts
function flow2statusinfo(flow)
local status_info = flow["status_info"]
function flow2alertinfo(flow)
local alert_info = flow["alert_info"]
if(status_info and (string.sub(status_info, 1, 1) == "{")) then
local res = json.decode(status_info)
if(alert_info and (string.sub(alert_info, 1, 1) == "{")) then
local res = json.decode(alert_info)
if(res ~= nil) then
return(res)
end
end
return(status_info)
return(alert_info)
end
-- #######################
@ -94,8 +94,8 @@ function getFlowsFilter()
local icmp_type = _GET["icmp_type"]
local icmp_code = _GET["icmp_cod"]
local dscp_filter = _GET["dscp"]
local flow_status = _GET["flow_status"]
local flow_status_severity = _GET["flow_status_severity"]
local alert_type = _GET["alert_type"]
local alert_type_severity = _GET["alert_type_severity"]
local deviceIP = _GET["deviceIP"]
local inIfIdx = _GET["inIfIdx"]
local outIfIdx = _GET["outIfIdx"]
@ -196,21 +196,21 @@ function getFlowsFilter()
end
end
if not isEmptyString(flow_status) then
if flow_status == "normal" then
if not isEmptyString(alert_type) then
if alert_type == "normal" then
pageinfo["alertedFlows"] = false
pageinfo["filteredFlows"] = false
elseif flow_status == "alerted" then
elseif alert_type == "alerted" then
pageinfo["alertedFlows"] = true
elseif flow_status == "filtered" then
elseif alert_type == "filtered" then
pageinfo["filteredFlows"] = true
else
pageinfo["statusFilter"] = tonumber(flow_status)
pageinfo["statusFilter"] = tonumber(alert_type)
end
end
if not isEmptyString(flow_status_severity) then
local s = alert_consts.severity_groups[flow_status_severity]
if not isEmptyString(alert_type_severity) then
local s = alert_consts.severity_groups[alert_type_severity]
if s then
pageinfo["statusSeverityFilter"] = s.severity_group_id
@ -1614,14 +1614,14 @@ function printActiveFlowsDropdown(base_url, page_params, ifstats, flowstats, is_
-- Status selector
-- table.clone needed to modify some parameters while keeping the original unchanged
local flow_status_params = table.clone(page_params)
flow_status_params["flow_status"] = nil
local alert_type_params = table.clone(page_params)
alert_type_params["alert_type"] = nil
print[[, '\
<div class="btn-group">\
<button class="btn btn-link dropdown-toggle" data-toggle="dropdown">]] print(i18n("status")) print(getParamFilter(page_params, "flow_status")) print[[<span class="caret"></span></button>\
<button class="btn btn-link dropdown-toggle" data-toggle="dropdown">]] print(i18n("status")) print(getParamFilter(page_params, "alert_type")) print[[<span class="caret"></span></button>\
<ul class="dropdown-menu scrollable-dropdown" role="menu">\
<li><a class="dropdown-item" href="]] print(getPageUrl(base_url, flow_status_params)) print[[">]] print(i18n("flows_page.all_flows")) print[[</a></li>\]]
<li><a class="dropdown-item" href="]] print(getPageUrl(base_url, alert_type_params)) print[[">]] print(i18n("flows_page.all_flows")) print[[</a></li>\]]
local entries = {
{"normal", i18n("flows_page.normal")},
@ -1634,7 +1634,7 @@ function printActiveFlowsDropdown(base_url, page_params, ifstats, flowstats, is_
-- Add labels to allow alphabetic sort
for status_key, status in pairs(status_stats) do
if status.count > 0 then
status.label = alert_consts.statusTypeLabel(status_key, true --[[ no html --]])
status.label = alert_consts.alertTypeLabel(status_key, true --[[ no html --]])
end
end
@ -1653,7 +1653,7 @@ function printActiveFlowsDropdown(base_url, page_params, ifstats, flowstats, is_
entries[#entries + 1] = {"filtered", i18n("flows_page.blocked")}
end
printDropdownEntries(entries, base_url, flow_status_params, "flow_status", page_params.flow_status)
printDropdownEntries(entries, base_url, alert_type_params, "alert_type", page_params.alert_type)
print[[\
</ul>\
@ -1661,14 +1661,14 @@ function printActiveFlowsDropdown(base_url, page_params, ifstats, flowstats, is_
']]
-- Flow Status Severity
local flow_status_severity_params = table.clone(page_params)
flow_status_severity_params["flow_status_severity"] = nil
local alert_type_severity_params = table.clone(page_params)
alert_type_severity_params["alert_type_severity"] = nil
print[[, '\
<div class="btn-group">\
<button class="btn btn-link dropdown-toggle" data-toggle="dropdown">]] print(i18n("flows_page.flow_status_severity")) print(getParamFilter(page_params, "flow_status_severity")) print[[<span class="caret"></span></button>\
<button class="btn btn-link dropdown-toggle" data-toggle="dropdown">]] print(i18n("flows_page.alert_type_severity")) print(getParamFilter(page_params, "alert_type_severity")) print[[<span class="caret"></span></button>\
<ul class="dropdown-menu scrollable-dropdown" role="menu">\
<li><a class="dropdown-item" href="]] print(getPageUrl(base_url, flow_status_severity_params)) print[[">]] print(i18n("flows_page.all_flows")) print[[</a></li>]]
<li><a class="dropdown-item" href="]] print(getPageUrl(base_url, alert_type_severity_params)) print[[">]] print(i18n("flows_page.all_flows")) print[[</a></li>]]
local entries
@ -1682,7 +1682,7 @@ function printActiveFlowsDropdown(base_url, page_params, ifstats, flowstats, is_
end
end
printDropdownEntries(entries, base_url, flow_status_severity_params, "flow_status_severity", page_params.flow_status_severity)
printDropdownEntries(entries, base_url, alert_type_severity_params, "alert_type_severity", page_params.alert_type_severity)
print[[\
</ul>\
@ -1935,20 +1935,20 @@ function getFlowsTableTitle()
local active_msg = ""
local status_type
if _GET["flow_status"] then
local flow_status_id = tonumber(_GET["flow_status"])
if _GET["alert_type"] then
local alert_type_id = tonumber(_GET["alert_type"])
if(flow_status_id ~= nil) then
status_type = alert_consts.statusTypeLabel(tonumber(_GET["flow_status"]), true)
if(alert_type_id ~= nil) then
status_type = alert_consts.alertTypeLabel(tonumber(_GET["alert_type"]), true)
else
status_type = firstToUpper(_GET["flow_status"])
status_type = firstToUpper(_GET["alert_type"])
end
end
if _GET["flow_status_severity"] then
local flow_status_severity = _GET["flow_status_severity"]
if _GET["alert_type_severity"] then
local alert_type_severity = _GET["alert_type_severity"]
local s = alert_consts.severity_groups[flow_status_severity]
local s = alert_consts.severity_groups[alert_type_severity]
active_msg = active_msg .. " ".. i18n(s.i18n_title)
end

View file

@ -301,12 +301,14 @@ function format_utils.formatConnectionIssues(info)
what[#what + 1] = i18n("alerts_dashboard.x_lost", {lost = format_utils.formatValue(lost)})
end
if info.cli2srv_pkts > 0 then
what[#what + 1] = i18n("alerts_dashboard.out_of_x_total_packets", {tot = format_utils.formatValue(info.cli2srv_pkts)})
end
if retx + ooo + lost > 0 then
if info.cli2srv_pkts > 0 then
what[#what + 1] = i18n("alerts_dashboard.out_of_x_total_packets", {tot = format_utils.formatValue(info.cli2srv_pkts)})
end
if #what > 0 then
res = res.." "..string.format("[%s: %s]", i18n("client_to_server"), table.concat(what, ", "))
if #what > 0 then
res = res.." "..string.format("[%s: %s]", i18n("client_to_server"), table.concat(what, ", "))
end
end
end
@ -326,12 +328,15 @@ function format_utils.formatConnectionIssues(info)
if lost > 0 then
what[#what + 1] = i18n("alerts_dashboard.x_lost", {lost = format_utils.formatValue(lost)})
end
if info.srv2cli_pkts > 0 then
what[#what + 1] = i18n("alerts_dashboard.out_of_x_total_packets", {tot = format_utils.formatValue(info.srv2cli_pkts)})
end
if #what > 0 then
res = res.." "..string.format("[%s: %s]", i18n("server_to_client"), table.concat(what, ", "))
if retx + ooo + lost > 0 then
if info.srv2cli_pkts > 0 then
what[#what + 1] = i18n("alerts_dashboard.out_of_x_total_packets", {tot = format_utils.formatValue(info.srv2cli_pkts)})
end
if #what > 0 then
res = res.." "..string.format("[%s: %s]", i18n("server_to_client"), table.concat(what, ", "))
end
end
end

View file

@ -430,7 +430,7 @@ local function validateBroadcastUnicast(mode)
return validateChoice(modes, mode)
end
local function validateFlowStatusNumber(status)
local function validateAlertTypeNumber(status)
if not validateNumber(status) then
return false
end
@ -439,17 +439,17 @@ local function validateFlowStatusNumber(status)
return((num >= 0) and (num < 2^8))
end
local function validateFlowStatus(mode)
local function validateAlertType(mode)
local modes = {"normal", "alerted", "filtered"}
if validateFlowStatusNumber(mode) then
if validateAlertTypeNumber(mode) then
return true
end
return validateChoice(modes, mode)
end
local function validateFlowStatusSeverity(mode)
local function validateAlertTypeSeverity(mode)
local modes = {"notice_or_lower", "warning", "error_or_higher"}
return validateChoice(modes, mode)
@ -1525,6 +1525,8 @@ local known_parameters = {
["script_type"] = validateSingleWord,
["script_subdir"] = validateSingleWord,
["script_key"] = validateSingleWord,
["alert_key"] = validateNumber,
["alert_addr"] = validateIpAddress,
["search_script"] = validateSingleWord,
["field_alias"] = validateListOfTypeInline(validateFieldAlias),
["dscp_class"] = validateSingleWord,
@ -1837,9 +1839,9 @@ local known_parameters = {
["delete_user"] = validateSingleWord,
["drop_flow_policy"] = validateBool, -- true if target flow should be dropped
["traffic_type"] = validateBroadcastUnicast, -- flows_stats.lua
["flow_status"] = validateFlowStatus, -- flows_stats.lua
["flow_status_severity"] = validateFlowStatusSeverity, -- flows_stats.lua
["flow_status_num"] = validateFlowStatusNumber, -- charts
["alert_type"] = validateAlertType, -- flows_stats.lua
["alert_type_severity"] = validateAlertTypeSeverity, -- flows_stats.lua
["alert_type_num"] = validateAlertTypeNumber, -- charts
["tcp_flow_state"] = validateTCPFlowState, -- flows_stats.lua
["traffic_profile"] = http_lint.validateTrafficProfile, -- flows_stats.lua
["include_unlimited"] = validateBool, -- pool_details_ndpi.lua

View file

@ -2802,33 +2802,28 @@ end
-- ###############################################
function formatElephantFlowStatus(flowstatus_info, local2remote)
function formatElephantAlertType(flowalert_info)
local threshold = ""
local res = ""
if not flowstatus_info then
if not flowalert_info then
return i18n("flow_details.elephant_flow")
end
if local2remote then
res = i18n("flow_details.elephant_flow_l2r")
local l2r_bytes = bytesToSize(flowalert_info["l2r_bytes"])
if flowstatus_info["elephant.l2r_threshold"] then
threshold = flowstatus_info["elephant.l2r_threshold"]
end
else
res = i18n("flow_details.elephant_flow_r2l")
if flowstatus_info["elephant.r2l_threshold"] then
threshold = flowstatus_info["elephant.r2l_threshold"]
end
if flowalert_info["l2r_bytes"] > flowalert_info["l2r_threshold"] then
l2r_bytes = l2r_bytes .." > "..bytesToSize(flowalert_info["l2r_threshold"])
end
local r2l_bytes = bytesToSize(flowalert_info["r2l_bytes"])
if flowalert_info["r2l_bytes"] > flowalert_info["r2l_threshold"] then
r2l_bytes = r2l_bytes .. " > "..bytesToSize(flowalert_info["r2l_threshold"])
end
res = i18n("flow_details.elephant_flow")
res = string.format("%s<sup><i class='fas fa-info-circle' aria-hidden='true' title='"..i18n("flow_details.elephant_flow_descr").."'></i></sup>", res)
if threshold ~= "" then
res = string.format("%s [%s]", res, i18n("flow_details.elephant_exceeded", {vol = bytesToSize(threshold)}))
end
res = string.format("%s %s", res, i18n("flow_details.elephant_exceeded", {l2r = l2r_bytes, r2l = r2l_bytes}))
return res
end

View file

@ -8,6 +8,8 @@ package.path = dirs.installdir .. "/scripts/lua/modules/pools/?.lua;" .. package
local json = require "dkjson"
local alert_severities = require "alert_severities"
local alert_consts = require "alert_consts"
local alert_severities = require "alert_severities"
local user_scripts = require "user_scripts"
local endpoints = require("endpoints")
-- ##############################################
@ -26,12 +28,30 @@ local default_builtin_minimum_severity = alert_severities.info.severity_id -- mi
-- ##############################################
local function _bitmap_from_user_script_categories(user_script_categories)
local bitmap = 0
for _, category_id in ipairs(user_script_categories) do
bitmap = bitmap | (1 << category_id)
end
return bitmap
end
-- ##############################################
-- @brief Performs Initialization operations performed during startup
function recipients.initialize()
-- Initialize builtin recipients, that is, recipients always existing an not editable from the UI
-- For each builtin configuration type, a configuration and a recipient is created
local all_categories = {}
for _, category in pairs(user_scripts.script_categories) do
all_categories[#all_categories + 1] = category.id
end
for endpoint_key, endpoint in pairs(endpoints.get_types()) do
if endpoint.builtin then
-- Add the configuration
local res = endpoints.add_config(
endpoint_key --[[ the type of the endpoint--]],
@ -42,10 +62,11 @@ function recipients.initialize()
-- Endpoint successfully created (or existing)
if res and res.endpoint_id then
-- And the recipient
local recipient_res = recipients.add_recipient(
res.endpoint_id --[[ the id of the endpoint --]],
"builtin_recipient_"..endpoint_key --[[ the name of the endpoint recipient --]],
nil, -- User script categories
all_categories,
default_builtin_minimum_severity,
false, -- Do Not add it to every pool automatically
{} --[[ no recipient params --]]
@ -57,8 +78,16 @@ function recipients.initialize()
-- Register all existing recipients in C to make sure ntopng can start with all the
-- existing recipients properly loaded and ready for notification enqueues/dequeues
for _, recipient in pairs(recipients.get_all_recipients()) do
ntop.recipient_register(recipient.recipient_id)
ntop.recipient_register(recipient.recipient_id, recipient.minimum_severity, _bitmap_from_user_script_categories(recipient.user_script_categories))
end
-- Now specify which recipients are "flow" recipients and tell this information to C++
local pools_alert_utils = require "pools_alert_utils"
local flow_pools = require "flow_pools"
local all_flow_recipients = pools_alert_utils.get_entity_recipients_by_pool_id(alert_consts.alert_entities.flow.entity_id, flow_pools.DEFAULT_POOL_ID)
flow_pools:create():set_flow_recipients(all_flow_recipients)
end
-- ##############################################
@ -243,6 +272,8 @@ function recipients.add_recipient(endpoint_id, endpoint_recipient_name, user_scr
if locked then
local ec = endpoints.get_endpoint_config(endpoint_id)
if ec["status"] == "OK" and endpoint_recipient_name then
-- Is the endpoint already existing?
local same_recipient = recipients.get_recipient_by_name(endpoint_recipient_name)
@ -264,7 +295,7 @@ function recipients.add_recipient(endpoint_id, endpoint_recipient_name, user_scr
_set_endpoint_recipient_params(endpoint_id, recipient_id, endpoint_recipient_name, user_script_categories, minimum_severity, safe_params)
-- Finally, register the recipient in C so we can start enqueuing/dequeuing notifications
ntop.recipient_register(recipient_id)
ntop.recipient_register(recipient_id, minimum_severity, _bitmap_from_user_script_categories(user_script_categories))
-- Set a flag to indicate that a recipient has been created
if not ec.endpoint_conf.builtin and isEmptyString(ntop.getPref(recipients.FIRST_RECIPIENT_CREATED_CACHE_KEY)) then
@ -331,7 +362,7 @@ function recipients.edit_recipient(recipient_id, endpoint_recipient_name, user_s
-- Finally, register the recipient in C to make sure also the C knows about this edit
-- and periodic scripts can be reloaded
ntop.recipient_register(tonumber(rc["endpoint_id"]))
ntop.recipient_register(tonumber(rc["endpoint_id"]), minimum_severity, _bitmap_from_user_script_categories(user_script_categories))
res = {status = "OK"}
end
@ -472,7 +503,6 @@ end
-- ##############################################
function recipients.get_recipient(recipient_id, include_stats)
local user_scripts = require "user_scripts"
local recipient_details
local recipient_details_key = _get_recipient_details_key(recipient_id)
@ -608,7 +638,7 @@ function recipients.dispatch_notification(notification, current_script)
local is_high_priority = is_notification_high_priority(notification)
for _, recipient_id in pairs(recipients) do
ntop.recipient_enqueue(recipient_id, is_high_priority, json_notification, notification.alert_severity)
ntop.recipient_enqueue(recipient_id, is_high_priority, json_notification, notification.alert_severity, current_script and current_script.category and current_script.category.id)
end
end
else

View file

@ -254,8 +254,14 @@ local function load_definitions(defs_dir, runtime_path)
return(false)
end
-- tprint({"copying", fname, defs_dir, runtime_path})
file_utils.copy_file(fname, defs_dir, runtime_path)
local ntopng_alert_definition = os_utils.fixPath(dirs.installdir .. "/scripts/lua/modules/alert_definitions/"..fname)
if ntop.exists(ntopng_alert_definition) then
-- Prevent plugin alert definitions from overwriting alert definitions under modules
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Cannot copy plugin alert definition from %s (alert already defined in %s)", full_path, ntopng_alert_definition))
else
-- tprint({"copying", fname, defs_dir, runtime_path})
file_utils.copy_file(fname, defs_dir, runtime_path)
end
end
end
@ -654,6 +660,10 @@ function plugins_utils.loadPlugins(community_plugins_only)
-- Reload the periodic scripts to load the new plugins
ntop.reloadPeriodicScripts()
-- Reload alerts configuration
local alerts_config = require "alerts_config"
alerts_config.initDefaultConfig()
-- Reload user scripts with their configurations
local user_scripts = require "user_scripts"
user_scripts.initDefaultConfig()

View file

@ -42,6 +42,28 @@ function flow_pools:get_all_members() return {} end
-- ##############################################
--@brief Tells the C++ core about the flow recipients
function flow_pools:set_flow_recipients(recipients)
-- Create a bitmap of all recipients responsible for flows (pool_id in this case is ignored)
local recipients_bitmap = 0
for _, recipient_id in ipairs(recipients) do
recipients_bitmap = recipients_bitmap | (1 << recipient_id)
end
-- Tell the C++ that flow recipients have changed
ntop.recipient_set_flow_recipients(recipients_bitmap)
end
-- ##############################################
--@brief Method called after a successful execution of method persist
function flow_pools:_post_persist(pool_id, name, members, recipients)
self:set_flow_recipients(recipients)
end
-- ##############################################
function flow_pools:default_only()
-- This is a dummy, default-only pool
return true

View file

@ -239,6 +239,12 @@ function pools:_unlock() ntop.delCache(self:_get_pool_lock_key()) end
-- ##############################################
--@brief Method called after a successful execution of method persist
function pools:_post_persist(pool_id, name, members, recipients)
end
-- ##############################################
-- @brief Persist pool details to disk. Possibly assign a pool id
-- @param pool_id The pool_id of the pool which needs to be persisted. If nil, a new pool id is assigned
function pools:_persist(pool_id, name, members, recipients)
@ -259,6 +265,8 @@ function pools:_persist(pool_id, name, members, recipients)
ntop.setCache(pool_details_key, json.encode(pool_details))
self:_post_persist(pool_id, name, members, recipients)
ntop.reloadPeriodicScripts()
-- Return the assigned pool_id

View file

@ -119,7 +119,7 @@ function pools_alert_utils.get_entity_recipients_by_pool_id(entity_id, pool_id,
end
if recipient_ok then
if recipient["recipient_minimum_severity"] ~= nil and
if alert_severity and recipient["recipient_minimum_severity"] ~= nil and
alert_severity < recipient["recipient_minimum_severity"] then
-- If the current alert severity is less than the minimum requested severity
-- exclude the recipient

View file

@ -1,87 +0,0 @@
--
-- (C) 2020 - ntop.org
--
-- ##############################################
local flow_keys = {
ntopng = {
status_normal = 0,
status_blacklisted = 1,
status_blacklisted_country = 2,
status_blocked = 3,
status_data_exfiltration = 4,
status_device_protocol_not_allowed = 5,
status_dns_data_exfiltration = 6,
status_dns_invalid_query = 7,
status_elephant_local_to_remote = 8,
status_elephant_remote_to_local = 9,
status_external_alert = 10,
status_longlived = 11,
status_low_goodput = 12,
status_malicious_signature = 13,
status_not_purged = 14,
status_potentially_dangerous = 15,
status_remote_to_remote = 16,
status_suspicious_tcp_probing = 17,
status_suspicious_tcp_syn_probing = 18,
status_tcp_connection_issues = 19,
status_tcp_connection_refused = 20,
status_tcp_severe_connection_issues = 21,
status_tls_certificate_expired = 22,
status_tls_certificate_mismatch = 23,
status_tls_old_protocol_version = 24,
status_tls_unsafe_ciphers = 25,
status_udp_unidirectional = 26,
status_web_mining_detected = 27,
status_tls_certificate_selfsigned = 28,
status_suspicious_file_transfer = 29,
status_known_proto_on_non_std_port = 30,
status_flow_risk = 31,
status_unexpected_dhcp_server = 32,
status_unexpected_dns_server = 33,
status_unexpected_smtp_server = 34,
status_unexpected_ntp_server = 35,
status_zero_tcp_window = 36,
status_iec_invalid_transition = 37,
status_remote_to_local_insecure_proto = 38,
status_ndpi_url_possible_xss = 39,
status_ndpi_url_possible_sql_injection = 40,
status_ndpi_url_possible_rce_injection = 41,
status_ndpi_http_suspicious_user_agent = 42,
status_ndpi_http_numeric_ip_host = 43,
status_ndpi_http_suspicious_url = 44,
status_ndpi_http_suspicious_header = 45,
status_ndpi_tls_not_carrying_https = 46,
status_ndpi_suspicious_dga_domain = 47,
status_ndpi_malformed_packet = 48,
status_ndpi_ssh_obsolete = 49,
status_ndpi_smb_insecure_version = 50,
status_ndpi_tls_suspicious_esni_usage = 51,
status_ndpi_unsafe_protocol = 52,
status_ndpi_dns_suspicious_traffic = 53,
status_ndpi_tls_missing_sni = 54,
-- Add here additional flow statuses when writing ntopng plugins.
-- User plugins should use statuses under key user.
-- WARNING: no not overlap with user; MAXIMUM status is 58 unless
-- class Bitmap in Flow has been extended to accomodate more than
-- 64 bits
},
user = {
status_user_01 = 59,
status_user_02 = 60,
status_user_03 = 61,
status_user_04 = 62,
status_user_05 = 63, -- Seems this is not seen by Lua, use until 62
-- WARNING: do not add any extra status greater than 63
-- unless class Bitmap inside Flow has been extended to
-- accomodate more than 64 bits.
},
}
-- ##############################################
return flow_keys
-- ##############################################

View file

@ -61,7 +61,7 @@ local REQUEST_PERIODIC_USER_SCRIPTS_RUN_KEY = "ntopng.cache.ifid_%i.user_scripts
local NON_TRAFFIC_ELEMENT_CONF_KEY = "all"
local NON_TRAFFIC_ELEMENT_ENTITY = "no_entity"
local ALL_HOOKS_CONFIG_KEY = "all"
local CONFIGSET_KEY = "ntopng.prefs.user_scripts.configset_v3"
local CONFIGSET_KEY = "ntopng.prefs.user_scripts.configset_v3" -- Keep in sync with ntop_defines.h FLOW_CALLBACKS_CONFIG
user_scripts.DEFAULT_CONFIGSET_ID = 0
-- NOTE: the subdir id must be unique
@ -184,51 +184,26 @@ local available_subdirs = {
-- User script execution filters (field names are those that arrive from the C Flow.cpp)
filter = {
-- Default fields populated automatically when creating filters
default_fields = {"srv_addr", "srv_port", "l7_proto", "proto" },
default_fields = { "srv_addr", },
-- All possible filter fields
available_fields = {
cli_addr = {
lint = http_lint.validateNetwork,
match = function(context, val)
local client_ip = flow.getClientIp()
-- Attempt exact match
if client_ip == val then return true end
-- Attempt IPv4 network match
local network, netmask = ipv4_utils.cidr_2_addr(val)
if network and netmask then return ipv4_utils.includes(network, netmask, client_ip) end
-- No match
return false
-- NO match, match is done in C++
end,
sqlite = function(val)
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
return string.format("cli_addr = '%s'", val)
return string.format("cli_addr = '%s'", val)
end,
find = function(alert, alert_json, filter, val)
return (alert[filter] and (alert[filter] == val))
end,
},
cli_port = {
lint = http_lint.validatePort,
match = function(context, val) return flow.getClientPort() == tonumber(val) end,
sqlite = function(val)
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
return string.format("cli_port = %u", val)
end,
find = function(alert, alert_json, filter, val)
return (alert[filter] and (tonumber(alert[filter]) == tonumber(val)))
end,
},
srv_addr = {
lint = http_lint.validateNetwork,
match = function(context, val)
local server_ip = flow.getServerIp()
-- Attempt exact match
if server_ip == val then return true end
-- Attempt IPv4 network match
local network, netmask = ipv4_utils.cidr_2_addr(val)
if network and netmask then return ipv4_utils.includes(network, netmask, server_ip) end
-- No match
return false
-- NO match, match is done in C++
end,
sqlite = function(val)
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
@ -238,124 +213,6 @@ local available_subdirs = {
return (alert[filter] and (alert[filter] == val))
end,
},
srv_port = {
lint = http_lint.validatePort,
match = function(context, val) return flow.getServerPort() == tonumber(val) end,
sqlite = function(val)
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
return string.format("srv_port = %u", val)
end,
find = function(alert, alert_json, filter, val)
return (alert[filter] and (tonumber(alert[filter]) == tonumber(val)))
end,
},
l7_proto = {
lint = http_lint.validateProtocolIdOrName,
match = function(context, val)
-- If val is the application name, then it is converted to application id
if not tonumber(val) then val = interface.getnDPIProtoId(val) end
-- For integers represented as strings
val = tonumber(val)
-- Check for equality on either the master or application ids
return flow.getnDPIMasterProtoId() == val or flow.getnDPIAppProtoId() == val
end,
sqlite = function(val)
-- If val is the application name, then it is converted to application id
if not tonumber(val) then val = interface.getnDPIProtoId(val) end
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
-- Match both on the master and app proto
return string.format("(l7_proto = %u OR l7_master_proto = %u)", val, val)
end,
find = function(alert, alert_json, filter, val)
-- Converting value into it's id if value is under string format
local value = tonumber(val)
if not value then value = interface.getnDPIProtoId(val) end
return (alert[filter] and (tonumber(alert[filter]) == value))
end,
},
proto = {
lint = http_lint.validateProtocolIdOrName,
match = function(context, val)
-- If val is the protocol name, then it is converted to L4 protocol id
if not tonumber(val) then val = l4_proto_to_id(val) end
-- Check for equality on either the master or application protocol
return flow.getProtocol() == tonumber(val)
end,
sqlite = function(val)
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
return string.format("proto = %u", val)
end,
find = function(alert, alert_json, filter, val)
-- Converting value into it's id if value is under string format
local value = tonumber(val)
if not value then value = l4_proto_to_id(val) end
return (alert[filter] and (tonumber(alert[filter]) == value))
end,
},
flow_risk_bitmap = {
lint = http_lint.validateNumber,
match = function(context, val)
-- Convert the string-bitmap to a number
val = tonumber(val)
-- Check if there's at least one risk in common between val
-- and the actual flow bitmap of risks
return (val & flow.getRiskBitmap()) ~= 0
end,
sqlite = function(val)
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
return string.format("flow_risk_bitmap = %u", val)
end,
find = function(alert, alert_json, filter, val)
return (alert[filter] and (tonumber(alert[filter]) == tonumber(val)))
end,
},
info = {
lint = http_lint.validateSingleWord,
match = function(context, val)
-- Search for substring val inside the flow info field
return not not flow.getFlowInfoField():find(val)
end,
sqlite = function(val)
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
-- As the info is stored inside the JSON alert, it is necessary to
-- use sqlite json_extract to access it
return string.format("json_extract(alert_json, '$.info') like '%%%s%%'", val)
end,
find = function(alert, alert_json, filter, val)
-- Search for substring val inside the flow info field
if alert_json and val then
return (alert_json[filter] and alert_json[filter]:find(val))
end
return false
end,
},
l7_cat = {
lint = http_lint.validateCategory,
match = function(context, val)
-- If val is the application name, then it is converted to application id
if not tonumber(val) then val = interface.getnDPICategoryId(val) end
-- For integers represented as strings
val = tonumber(val)
-- Check for equality on either the master or application ids
return flow.getnDPICategoryId() == val
end,
sqlite = function(val)
-- If val is the application name, then it is converted to application id
if not tonumber(val) then val = interface.getnDPICategoryId(val) end
-- Keep in sync with SQLite database schema declared in AlertsManager.cpp
-- Match both on the master and app proto
return string.format("l7_cat = %u", val)
end,
find = function(alert, alert_json, filter, val)
-- If val is the application name, then it is converted to application id
local value = tonumber(val)
if not value then value = interface.getnDPICategoryId(val) end
return (alert[filter] and (tonumber(alert[filter]) == value))
end,
},
},
},
-- No pools for flows
@ -789,7 +646,7 @@ local function init_user_script(user_script, mod_fname, full_path, plugin, scrip
end
-- Expand hooks
if(user_script.hooks["all"] ~= nil) then
if(user_script.hooks and user_script.hooks["all"] ~= nil) then
local callback = user_script.hooks["all"]
user_script.hooks["all"] = nil
@ -834,7 +691,7 @@ local function loadAndCheckScript(mod_fname, full_path, plugin, script_type, sub
return(nil)
end
if(table.empty(user_script.hooks)) then
if(subdir ~= "flow" and table.empty(user_script.hooks)) then
traceError(TRACE_WARNING, TRACE_CONSOLE, string.format("No 'hooks' defined in user script '%s', skipping", mod_fname))
return(nil)
end
@ -951,7 +808,7 @@ function user_scripts.load(ifid, script_type, subdir, options)
-- Checks passed, now load the script information
-- Populate hooks fast lookup table
for hook, hook_fn in pairs(user_script.hooks) do
for hook, hook_fn in pairs(user_script.hooks or {}) do
-- load previously computed benchmarks (if any)
-- benchmarks are loaded even if their computation is disabled with a do_benchmark ~= true
if(rv.hooks[hook] == nil) then
@ -1125,6 +982,9 @@ local function saveConfigset(configset)
-- Reload the periodic scripts as the configuration has changed
ntop.reloadPeriodicScripts()
-- Reload flow callbacks executed in C++
ntop.reloadFlowCallbacks()
return true
end
@ -1137,10 +997,6 @@ local cached_config_set = nil
function user_scripts.getConfigset()
if not cached_config_set then
cached_config_set = json.decode(ntop.getCache(CONFIGSET_KEY))
if not cached_config_set then
traceError(TRACE_ERROR, TRACE_CONSOLE, string.format("Unable to load a valid configset"))
end
end
return cached_config_set
@ -1441,23 +1297,16 @@ end
-- @brief Initializes a default configuration for user scripts
-- @param overwrite If true, a possibly existing configuration is overwritten with default values
function user_scripts.initDefaultConfig(overwrite)
if not overwrite and json.decode(ntop.getCache(CONFIGSET_KEY)) then
-- Nothing to do, already initialized
return
end
function user_scripts.initDefaultConfig()
local ifid = getSystemInterfaceId()
-- Default per user-script configuration
local default_conf = {}
-- Default per user-script filters
local default_filters = {}
if default_conf then
-- Drop possible nested values due to a previous bug
default_conf.config = nil
end
-- Current (possibly not-existing, not yet created configset)
local configset = user_scripts.getConfigset() or {}
-- Default per user-script configuration
local default_conf = configset.config or {}
-- Default per user-script filters
local default_filters = configset.filters or {}
for type_id, script_type in pairs(user_scripts.script_types) do
for _, subdir in pairs(script_type.subdirs) do
local scripts = user_scripts.load(ifid, script_type, subdir, {return_all = true})
@ -1485,25 +1334,31 @@ function user_scripts.initDefaultConfig(overwrite)
if usermod.filter and usermod.filter.default_filters then
default_filters[subdir] = default_filters[subdir] or {}
default_filters[subdir][key] = usermod.filter.default_filters
if not default_filters[subdir][key] then
-- Do not override filter of an existing configuration
default_filters[subdir][key] = usermod.filter.default_filters
end
end
end
end
end
-- This is the new configset with all defaults
local configset = {
config = default_conf,
filters = default_filters,
}
saveConfigset(configset)
saveConfigset(configset)
end
-- ##############################################
function user_scripts.resetConfigset()
cached_config_set = nil
user_scripts.initDefaultConfig(true --[[ Overwrite a possibly existing configuration --]])
ntop.delCache(CONFIGSET_KEY)
user_scripts.initDefaultConfig()
return(true)
end
@ -1567,7 +1422,7 @@ function user_scripts.getScriptConfig(configset, script, subdir)
local script_type = user_scripts.getScriptType(subdir)
local hooks = ternary(script_type.has_per_hook_config, script.hooks, {[ALL_HOOKS_CONFIG_KEY]=1})
for hook in pairs(script.hooks) do
for hook in pairs(script.hooks or {}) do
rv[hook] = default_config
end
@ -1659,18 +1514,9 @@ function user_scripts.getFilterPreset(alert, alert_info)
return ''
end
local script_key = alert_generation["script_key"]
local subdir = alert_generation["subdir"]
local filter_string = ''
local script_type = user_scripts.getScriptType(subdir)
local script = user_scripts.loadModule(interface.getId(), script_type, subdir, script_key)
local filter_to_use = {}
local subdir_id = getSubdirId(subdir)
if not script then
return ''
end
if subdir_id == -1 then
return ''
end
@ -1679,11 +1525,9 @@ function user_scripts.getFilterPreset(alert, alert_info)
return ''
end
-- Checking if the script has default filter fields or not
-- if not, getting the default for the subdir
if script["filter"] and script["filter"]["default_fields"] then
filter_to_use = script["filter"]["default_fields"]
elseif available_subdirs[subdir_id]["filter"]["default_fields"] then
local filter_to_use = {}
if available_subdirs[subdir_id]["filter"]["default_fields"] then
filter_to_use = available_subdirs[subdir_id]["filter"]["default_fields"]
end