User Scripts

User scripts are the core of plugins. They actually allow certain actions to be performed periodically, or when a certain event occurs. The logic of a plugin is contained in its users scripts. A plugin contains zero to many user scripts.

Structure

The structure of a user script is the following:

local user_scripts = require("user_scripts")

-- #################################################################

local script = {
  hooks = {},

  -- other script attributes ...
}

-- #################################################################

function script.setup()
  -- return false to disable the script
  return true
end

-- #################################################################

return(script)

Every user script must return a Lua table with the following keys:

  • hooks: a Lua table with hook names as key and callbacks as values. User Script Hooks are events or points in time. ntopng uses hooks to know when to call a user script. A user script defining a hook will get the hook callaback called by ntopng. User scripts must register to at least one hook. See User Script Hooks.
  • gui: a Lua table specifying user script name, description and configuration. Data is used by ntopng to show the user script configurable from the User Scripts GUI.
  • local_only (optional, hosts only): if true, the user script is only executed for local hosts.
  • packet_interface_only (optional): only execute the script on packet interfaces, excluding ZMQ interfaces.
  • l4_proto (optional, flows only): only execute the script for flows matching the L4 protocol.
  • l7_proto (optional, flows only): only execute the script for flows matching the L7 application protocol.
  • nedge_only (optional): if true, the script is only executed in nEdge.
  • nedge_exclude (optional): if true, the script is not executed in nEdge.
  • default_value (optional): the default value for the script configuration, in the form <script_key>;<operator>;<value> (e.g. syn_flood_victim;gt;50). See User Scripts GUI.
  • default_enabled (optional): if false, the script is disabled by default.

Furthermore, a script may define the following extra functions, which are only called once per script:

  • setup(): called once per user script. If it returns false then the script is considered disabled and its hooks are not be called.
  • teardown(): called after the script operation is complete (e.g. after all the hosts have been iterated and hooks called).

Flow User Scripts

Flow user scripts are executed on each network flow. The user script have access to flow information such as L4 and L7 protocols, peers involved in the communication, and other things. This information can be retrieved via the Flow User Scripts API.

Refer to Flow User Script Hooks for available hooks.

Setting Flow Statuses

Flow statuses are set with

flow.setStatus(flow_status_type, flow_score, cli_score, srv_score)

See flow.lua for the source code. Parameters are:

  • flow_status_type: flow status as described in Flow Status Definitions.
  • flow_score: A score to be assigned to the current flow
  • cli_score: A score to be added to the score of the flow client
  • srv_score: A score to be added to the score to the flow server

Setting a flow status will cause ntopng to show it across the interface.

Triggering Flow Alerts

A status can also determine the triggering of an alert. Triggering an alert is done calling

flow.triggerStatus(flow_status_type, status_info, flow_score, cli_score, srv_score, custom_severity)

See flow.lua for the source code. Parameters are those described in Setting Flow Statuses plus a custom_severity.

Other User Scripts

ntopng supports users scripts for the following traffic elements:

Refer to Other User Script Hooks for available hooks.

Syslog User Scripts

Syslog scripts are used to handle syslog events and ingest data, including flows and alerts, from external sources (e.g. alerts from Intrusion Detection Systems).

Scripts Location

Syslog scripts are located under /usr/share/ntopng/scripts/callbacks/syslog and should use the source name (e.g. application name) with the .lua extension as file name. In fact messages demultiplexing is implemented by using the source name for matching the script name. For example, log messages coming from suricata will be delivered to the /usr/share/ntopng/scripts/callbacks/syslog/suricata.lua script.

Script API

A syslog module shoule implement the below functions:

  • setup (optional) which is called once to initialize the module.
  • teardown (optional) which is called once to terminate the module.
  • hooks.handleEvent which is called for each log message matching the module.

Script Example

Here is a sample script suricata.lua processing log messages from Suricata, exported to syslog in Eve JSON format.

local dirs = ntop.getDirs()
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
require "lua_utils"
local json = require ("dkjson")

local syslog_module = {
   hooks = {},
}

-- The function below is called once to initialize the script
function syslog_module.setup()
   return true
end

-- The function below is called for each log message received from Suricata
function syslog_module.hooks.handleEvent(message)
   local alert = json.decode(message)
   tprint(alert)
end

-- The function below is called once to terminate the script
function syslog_module.teardown()
   return true
end

return syslog_module

Triggering Alerts

An user script can trigger an alert when some anomalous behavior is detected. Users can use the already provided hook callbacks:

  • alerts_api.threshold_check_function: can check thresholds and trigger threshold cross alerts
  • alerts_api.anomaly_check_function: checks anomaly status, set by the C core

or build their own alert custom logic. In the latter case, the hook callback should call the following functions:

  • alerts_api.trigger(entity_info, type_info) whenever the entity state is alerted
  • alerts_api.release(entity_info, type_info) whenever the entity state is not alerted

Alert state is kept internally so multiple trigger/releases of the same alert have no effect. The type_info is specific of the alert_type and should be built using one of the “type_info building functions” available into alerts_api.lua, for example alerts_api.thresholdCrossType.

Built-in Alerts

Alert types are defined into alert_consts.alert_types inside scripts/lua/modules/alert_consts.lua. Additional alert types can be created as explained in Alert Definitions.