4. 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 can contain many user scripts. Differences between a plugin and a user script are described in Plugins vs User Scripts.

4.1. Hooks

How does ntopng know when to call a certain user script? By means of hooks. Hooks are pre-defined events (for flows) of intervals of time (for any other network element such as an host, or a network) which can be associated to functions to be called. Such functions are also referred to as callbacks. So for example if a user script needs to be called every minute, it will implement a function assigned to hook min. Similarly, if a user script needs to be called every time a flow goes idle, it will implement a function assigned to hook flowEnd.

Hooks and user scripts are described in detail for flows and other network elements in the reminder of this section.

4.2. Structure

Here is the skeleton for a generic user script:

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 script table which exposes the following attributes:

  • hooks (mandatory): a map hook_name -> callback which defines on which events the callback should be called. The scripts must register to at least one hook. The list of available hooks depends on the script type. Flow User Scripts hooks are different from Other User Scripts hooks.
  • gui (optional): See Web UI for additional details
  • local_only (optional, hosts only): if true, the script will not be executed on remote hosts
  • packet_interface_only (optional): only execute the script on packet interfaces
  • l4_proto (optional, flows only): only execute the script for flows matching the L4 proto
  • l7_proto (optional, flows only): only execute the script for flows matching the L7 proto see 2nd column in lua_utils.lua::l4_keys for supported protocols.
  • nedge_only (optional): if true, the script will only be executed in nEdge
  • nedge_exclude (optional): if true, the script will not be 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)
  • default_enabled (optional): if false, the script will be disabled by default

Note

all is a special hook name which will cause the
associated callback to be called for all the events.

Futhermore, a script may define the following extra callbacks, which are only called once per script:

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

4.3. Hook Callbacks

An hook callback function takes the following form:

function my_callback(params)
  -- ...
end

The information contained into the params object depends on the script type:

  • granularity (traffic element only): the current granularity
  • alert_entity (traffic element only): the traffic element entity type
  • entity_info (traffic element only): contains entity specific data (e.g. on hosts, it is the output of Host:lua())

It is the ntopng engine which takes care of calling the hook callback with table params opportunely populated.

4.4. Flow User Scripts

Flow user scripts are executed on each network flow. The user can inspect the flow protocol, peers involved in the communication, and other specific information.

A user script can hook to the following functions:

  • protocolDetected: called after the Layer-7 application protocol has been detected
  • statusChanged: called when the internal status of the flow has changed since the previous invocation. The flow status can be used to detect anomalous behaviours.
  • periodicUpdate: called every few minutes on long-lived flows
  • flowEnd: called when the flow is considered finished

See the Flow API for a documentation of the available functions which can be called inside a flow user script.

4.5. Other User Scripts

ntopng supports users scripts on the following traffic elements:

  • interface: a network interface of ntopng
  • network: a local network of ntopng
  • host: a local/remote host of ntopng
  • system: the system on top of which is running ntopng
  • SNMP interfaces: interfaces of monitored SNMP devices

4.5.1. Hooks

Traffic element scripts are called periodically. The corresponding available hooks are:

  • min: called every minute
  • 5mins: called every 5 minutes
  • hour: called every hour
  • day: called every day (at midnight)

4.6. 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).

4.6.1. 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.

4.6.2. 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.

4.6.3. 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

4.7. Triggering Alerts

An user script can trigger an alert when some anomalous behaviour 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

Alerts 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.

4.7.1. 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.