Processing Connections in Lua

In this section:

General Information.

Requirements for the Script of Connection Processing.

Examples.

Tables in Use.

Available Auxiliary Modules.

General Information

Dr.Web Firewall for Linux supports interaction via program interpreter in Lua (version 5.3.4 is used and is supplied together with Dr.Web for UNIX Mail Servers). Scripts written in Lua can be used by the component for preliminary connection scanning before it is send to SpIDer Gate for analysis.

Connections will be analyzed with the Lua script, if the path to this script is specified in the Dr.Web Firewall for Linux settings (in the InterceptHook parameter). Otherwise, connection processing is performed by using the default settings and processing rules specified in the component settings (the RuleSet* parameters).

For more examples of Lua scripts for connection processing, follow the link:
https://github.com/DoctorWebLtd/drweb-lua-examples/tree/master/firewall.

Requirements for the Script of Connection Processing

The script must contain a global function, which is the entry point in the connection scanning module (Dr.Web Firewall for Linux calls this function for processing a newly received connection). The function should match the following call conventions:

function nameintercept_hook;

the only argument—the Lua context table (provides the access to information from function on the processed connection, see description of the table below);

the only return value—one of the string values from the table below:

Value

Verdict description

pass

Skip the connection without checking it by SpIDer Gate

check

Check the connection with the help of SpIDer Gate

reject

Discard the connection (the client who initiated the connection will receive the TCP package with an RST flag)

drop

Disconnect (the client that initiated the connection will receive no acknowledgement)

Examples
 

1.The script always returns the pass verdict (skip) for all the connections lest the connections be checked by Dr.Web Firewall for Linux:

-- Function of connection scanning written by the user
function intercept_hook(ctx)
  return "pass" -- do not scan the connection
end

2.With the help of the script given below Dr.Web Firewall for Linux checks all the connections being established with the following exceptions:

outgoing local connections from applications running with user rights from the drweb group;

connections initiated from privileged ports (regardless of the connection owner and its direction);

connections originating from IP addresses of the local network:

function intercept_hook(ctx)
  -- Do not scan connections, initiated from the local
  -- host (divert == "output") by application under the name of
  -- "drweb" (group == "[drweb]")
  if ctx.divert == "output" and ctx.group == "drweb" then
    return "pass"
  end

  -- Do not scan connections, initiated from
  -- privileged ports (range is from 0 to 1024)
  if ctx.src.port >= 0 and ctx.src.port <= 1024 then
    return "pass"
  end

  -- Do not scan connections from local network IP addresses
  -- (IP address range 127.0.0.1/8)
  if ctx.src.ip.belongs("127.0.0.0/8") then
    return "pass"
  end

  -- Connection is scanned by default
  return "check"
end

Tables Used in Scripts

1. InterceptContext Table

The table is used to transfer data on the processed connection to the intercept_hook function. On the basis of this data one of the following action can be performed to the connection:

skip without checking;

disrupt the connection;

send the connection to SpIDer Gate for checking.

Dr.Web Firewall for Linux fills the table with data. Some data in the table is already available by the time the intercept_hook functions is executed, other data (so called “lazy” data) will be calculated directly upon request of the corresponding field of the table.

Field

Description

Data type

src

Address and port of the client that initiated the connection

Example:

if ctx.src.port >= 0 and ctx.src.port <= 1024 then
  return "pass"
end

TcpEndpoint table

dst

Address and port of the server, the connection to which was initiated by the client

Example:

if ctx.dst.ip.belongs("10.20.30.41/8") then
  return "reject"
end

TcpEndpoint table

divert

The type of intercepted connection:

"output"—outgoing connection;

"input"—incoming connection;

"forward"—transit connection.

Example:

if ctx.divert == "forward" then
  return "check"
end

String

iface_in

The name of the interface from which the connection was initiated.

If the name of the interface was not identified, it has the nil value.

String

iface_out

The name of the interface to which the packets were sent after the connection had been initiated.

If the name of the interface was not identified, it has the nil value.

String

uid

The ID of the user who initiated the outgoing connection.

If the connection type (divert) is not "output", or UID cannot be identified, it has nil value.

Number

gid

The ID of the group on behalf of which the outgoing connection was initiated.

If the connection type (divert) is not "output", or GID cannot be identified, it has the nil value.

Number

user

The name of the user who initiated the outgoing connection.

If the connection type (divert) is not "output", or UID cannot be identified, it has the nil value.

String

group

The name of the group on behalf of which the outgoing connection was initiated.

If the connection type (divert) is not "output", or UID cannot be identified, it has the nil value.

String

pid

The ID of the process which initiated the outgoing connection.

If the connection type (divert) is not "output", or PID cannot be identified, it has the nil value.

Number

exe_path

Executable path to the application file which initiated the outgoing connection.

If the connection type (divert) is not "output", or executable path cannot be identified, it has the nil value.

String

Overridden metamethods: None

2. TcpEndpoint Table

The table describes the address of connection point (client or server).

Field

Description

Data type

ip

IP address

The IpAddress table

port

Port number

Number

Overridden metamethods:

__tostring—a function that converts TcpEndpoint to a string, for example: "127.0.0.1:443" (IPv4) or "[::1]:80" (IPv6);

__concat—a function that concatenates TcpEndpoint to a string

Available Auxiliary Modules

For interconnection with Dr.Web for UNIX Mail Servers in program space in Lua the following specific modules can be imported.

Name of the module

Function

The module that provides functions to record messages from the Lua program to the log of the Dr.Web for UNIX Mail Servers component which has launched the Lua program and the means of asynchronous execution of Lua procedures

The module that provides tools to request data from external sources by calling the Dr.Web LookupD module

Contents of the drweb Module

1.Functions

The module provides a set of functions.

Saving messages from the Lua program in the Dr.Web for UNIX Mail Servers component log:

log(<level>, <message>) writes the <message> string to the Dr.Web for UNIX Mail Servers log on the <level> level (the required level is defined using the “debug”, “info”, “notice”, “warning”, and “error”);

debug(<message>) writes the <message> string to the Dr.Web for UNIX Mail Servers log at the DEBUG level;

info(<message>) writes the <message> string to the Dr.Web for UNIX Mail Servers log at the INFO level;

notice(<message>) writes the <message> string to the Dr.Web for UNIX Mail Servers log at the NOTICE level;

warning(<message>) writes the <message> string to the Dr.Web for UNIX Mail Servers log at the WARNING level;

error(<message>) writes the <message> string to the Dr.Web for UNIX Mail Servers log at the ERROR level.

Managing the synchronization of Lua procedures:

sleep(<sec.>) pauses the execution of a Lua procedure instance for a specified number of seconds.

async(<Lua function>[, <argument list>]) launches the specified function asynchronously and passes to it the specified argument list. The async function call completes immediately, and the return value (the table Future) allows you to obtain the result of the <Lua function>.

Adding IP addresses to the IpAddress table:

ip(<address>) indicates an IP address, sent as the <address> string in the form of an IpAddress table. Either IPv4 or IPv6 addresses can be used.

Uploading external data from a text file:

load_set(<file path>) generates a table with the true values from the contents of the specified text file; strings read from a file are used as keys. Empty strings as well as strings with blank spaces will be ignored;

load_array(<file path>) generates a string array from the contents of the specified text file. Empty strings and strings consisting of whitespace characters only, are ignored and are not included in the array.

2.Tables

The Future table describes the pending result of performing a function using the async function.

Field

Description

Data type

wait

A function that returns the result of the function started using the async.function If the function has not completed its execution yet, it waits for the completion and returns the result. If the function is completed before wait is called, the result is returned immediately. If the started function fails, the wait call generates the same error.

Function

Overridden metamethods: None

The IpAddress table describes an IP address.

Field

Description

Data type

belongs

Function checks an IP address stored in the IpAddress table for belonging to the specified subnets (IP address ranges).

Receives the only argument—a string that looks like: "<IP address>" or "<IP address>/<mask>", where <IP address>—a host address or a network address (for example, "127.0.0.1"), and <mask>—a subnetwork mask (can be specified as an IP address, for example, "255.0.0.0", or in the numerical form, for example, "8").

Returns a Boolean value:

true indicates that the address equals to at least one of the specified addresses or belongs at least one of the specified subnets (range of IP addresses);

false—otherwise.

Function

Overridden metamethods:

__tostring is a function that modifies IpAddress in a string, for example: "127.0.0.1" (IPv4) or "::1" (IPv6);

__concat is a function that performs joining IpAddress to a string;

__eq is a function that checks the equality of two IpAddress;

__band—function that allows to apply a mask, for example: dw.ip('192.168.1.2') & dw.ip('255.255.254.0')

3.Examples

Writing the messages generated by a procedure initiating asynchronously to the log:

local dw = require "drweb"

-- This function waits two seconds and returns a string,
-- received as an argument
function out_msg(message)
 dw.sleep(2)
 return message
end

-- "Main" function
function intercept(ctx)
 -- Output of a string at the NOTICE level to the Dr.Web for UNIX Mail Servers log
 dw.notice("Intercept function started.")

 -- An asynchronous start of two copies of the out_msg function
 local f1 = dw.async(out_msg, "Hello,")
 local f2 = dw.async(out_msg, " world!")

 -- Waiting for the completion of the copies of the function
 -- out_msg and output its results to log
 -- the Dr.Web for UNIX Mail Servers log at the DEBUG level
 dw.log("debug", f1.wait() .. f2.wait())
end

Creating a scheduled procedure:

local dw = require "drweb"

-- Save the table Future in the future global variable in order
-- to preven the removal by the garbage collector
future = dw.async(function()
   while true do
     -- Everyday, the following message is displayed in the log
     dw.sleep(60 * 60 * 24)
     dw.notice("A brand new day began")
   end
end)

Modifying an IP address represented as a string into an IpAddress table::

local dw = require "drweb"

local ipv4 = dw.ip("127.0.0.1")
local ipv6 = dw.ip("::1")
local mapped = dw.ip("::ffff:127.0.0.1")

 

Contents of the drweb.lookup Module

1.Functions

The module provides the following functions:

lookup(<request>, <parameters>) requests data from an external storage available via the Dr.Web LookupD module. The <request> argument must correspond to a section in the Dr.Web LookupD settings (the string <type>@<tag>). The <parameters> argument is optional. It describes substitutions that will be used to generate a request. The following automatically permitted markers can be used:

$u, $U is automatically replaced with user, the user name sent by the client component;

$d, $D is automatically replaced with domain, the domain sent by the client component.

These arguments are set as a table. Keys and values of this table must be strings. The function returns an array of strings that are results of the request;

check(<checked string>, <request>, <parameters>) returns true if <checked string> is found in the external repository, available via the Dr.Web LookupD module. The arguments <request> and <parameters> are equivalent to the arguments of the lookup function (see above). The <checked string> argument is supposed to be a string or a table with the __tostring metamethod (i.e. that can be formatted into a string).

2.Examples

Writing to the log list of users retrieved from the LookupD.LDAP.users data source:

local dw = require "drweb"
local dwl = require "drweb.lookup"

-- "Main" function
function intercept(ctx)
 -- Writing the string at the NOTICE level to the Dr.Web for UNIX Mail Servers log
 dw.notice("Intercept function started.")

 -- Writing the request results to the Dr.Web for UNIX Mail Servers log
 -- to the 'ldap@users' data source
 for _, s in ipairs(dwl.lookup("ldap@users", {user="username"})) do
   dw.notice("Result for request to 'ldap@users': " .. s)
 end

end