This documentation is no longer maintained and exists for historical purposes. The current documentation is located at http://suricata.readthedocs.io/.
Lua Output¶
Note: this page new Lua scripting available for outputs. It will be available in 2.1.
Script structure¶
A script defines 4 functions: init, setup, log, deinit
- init -- registers where the script hooks into the output engine
- setup -- does per output thread setup
- log -- logging function
- deinit -- clean up function
Example:
function init (args) local needs = {} needs["protocol"] = "http" return needs end function setup (args) filename = SCLogPath() .. "/" .. name file = assert(io.open(filename, "a")) SCLogInfo("HTTP Log Filename " .. filename) http = 0 end function log(args) http_uri = HttpGetRequestUriRaw() if http_uri == nil then http_uri = "<unknown>" end http_uri = string.gsub(http_uri, "%c", ".") http_host = HttpGetRequestHost() if http_host == nil then http_host = "<hostname unknown>" end http_host = string.gsub(http_host, "%c", ".") http_ua = HttpGetRequestHeader("User-Agent") if http_ua == nil then http_ua = "<useragent unknown>" end http_ua = string.gsub(http_ua, "%g", ".") ts = SCPacketTimeString() ipver, srcip, dstip, proto, sp, dp = SCFlowTuple() file:write (ts .. " " .. http_host .. " [**] " .. http_uri .. " [**] " .. http_ua .. " [**] " .. srcip .. ":" .. sp .. " -> " .. dstip .. ":" .. dp .. "\n") file:flush() http = http + 1 end function deinit (args) SCLogInfo ("HTTP transactions logged: " .. http); file:close(file) end
YAML¶
To enable the lua output, add the 'lua' output and add one or more scripts like so:
outputs: - lua: enabled: yes scripts-dir: /etc/suricata/lua-output/ scripts: - tcp-data.lua - flow.lua
The scripts-dir option is optional. It makes Suricata load the scripts from this directory. Otherwise scripts will be loaded from the current workdir.
packet¶
Initialize with:
function init (args) local needs = {} needs["type"] = "packet" return needs end
SCPacketTimeString¶
Add SCPacketTimeString to get the packets time string in the format: 11/24/2009-18:57:25.179869
function log(args) ts = SCPacketTimeString()
SCPacketTuple¶
ipver, srcip, dstip, proto, sp, dp = SCPacketTuple()
SCPacketPayload¶
p = SCPacketPayload()
flow¶
function init (args) local needs = {} needs["type"] = "flow" return needs end
SCFlowTimeString¶
startts = SCFlowTimeString()
SCFlowTuple¶
ipver, srcip, dstip, proto, sp, dp = SCFlowTuple()
SCFlowAppLayerProto¶
Get alproto as string from the flow. If alproto is not (yet) known, it returns "unknown".
Example:
function log(args) alproto = SCFlowAppLayerProto() if alproto ~= nil then print (alproto) end end
SCFlowStats¶
Gets the packet and byte counts per flow.
tscnt, tsbytes, tccnt, tcbytes = SCFlowStats()
http¶
Init with:
function init (args) local needs = {} needs["protocol"] = "http" return needs end
HttpGetRequestBody and HttpGetResponseBody.¶
Make normalized body data available to the script through HttpGetRequestBody and HttpGetResponseBody.
There no guarantees that all of the body will be availble.
Example:
function log(args) a, o, e = HttpGetResponseBody(); --print("offset " .. o .. " end " .. e) for n, v in ipairs(a) do print(v) end end
HttpGetRequestHost¶
Get the host from libhtp's tx->request_hostname, which can either be the host portion of the url or the host portion of the Host header.
Example:
http_host = HttpGetRequestHost() if http_host == nil then http_host = "<hostname unknown>" end
HttpGetRequestHeader¶
http_ua = HttpGetRequestHeader("User-Agent") if http_ua == nil then http_ua = "<useragent unknown>" end
HttpGetResponseHeader¶
server = HttpGetResponseHeader("Server"); print ("Server: " .. server);
HttpGetRequestLine¶
rl = HttpGetRequestLine(); print ("Request Line: " .. rl);
HttpGetResponseLine¶
rsl = HttpGetResponseLine(); print ("Response Line: " .. rsl);
HttpGetRawRequestHeaders¶
rh = HttpGetRawRequestHeaders(); print ("Raw Request Headers: " .. rh);
HttpGetRawResponseHeaders¶
rh = HttpGetRawResponseHeaders(); print ("Raw Response Headers: " .. rh);
HttpGetRequestUriRaw¶
http_uri = HttpGetRequestUriRaw() if http_uri == nil then http_uri = "<unknown>" end
HttpGetRequestUriNormalized¶
http_uri = HttpGetRequestUriNormalized() if http_uri == nil then http_uri = "<unknown>" end
HttpGetRequestHeaders¶
a = HttpGetRequestHeaders(); for n, v in pairs(a) do print(n,v) end
HttpGetResponseHeaders¶
a = HttpGetResponseHeaders(); for n, v in pairs(a) do print(n,v) end
DNS¶
DnsGetQueries¶
dns_query = DnsGetQueries(); if dns_query ~= nil then for n, t in pairs(dns_query) do rrname = t["rrname"] rrtype = t["type"] print ("QUERY: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " .. "TODO" .. " [**] " .. srcip .. ":" .. sp .. " -> " .. dstip .. ":" .. dp) end end
returns a table of tables
DnsGetAnswers¶
dns_answers = DnsGetAnswers(); if dns_answers ~= nil then for n, t in pairs(dns_answers) do rrname = t["rrname"] rrtype = t["type"] ttl = t["ttl"] print ("ANSWER: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " .. ttl .. " [**] " .. srcip .. ":" .. sp .. " -> " .. dstip .. ":" .. dp) end end
returns a table of tables
DnsGetAuthorities¶
dns_auth = DnsGetAuthorities(); if dns_auth ~= nil then for n, t in pairs(dns_auth) do rrname = t["rrname"] rrtype = t["type"] ttl = t["ttl"] print ("AUTHORITY: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " .. ttl .. " [**] " .. srcip .. ":" .. sp .. " -> " .. dstip .. ":" .. dp) end end
returns a table of tables
DnsGetRcode¶
rcode = DnsGetRcode(); if rcode == nil then return 0 end print (rcode)
returns a lua string with the error message, or nil
DnsGetRecursionDesired¶
if DnsGetRecursionDesired() == true then print ("RECURSION DESIRED") end
returns a bool
TLS¶
Initialize with:
function init (args) local needs = {} needs["tls"] = tostring(true) return needs end
TlsGetCertInfo¶
Make certificate information available to the script through TlsGetCertInfo.
Example:
function log (args) version, subject, issuer, fingerprint = TlsGetCertInfo() if version == nil then return 0 end end
SSH¶
Initialize with:
function init (args) local needs = {} needs["protocol"] = "ssh" return needs end
SshGetServerProtoVersion¶
Get SSH protocol version used by the server through SshGetServerProtoVersion.
Example:
function log (args) version = SshGetServerProtoVersion() if version == nil then return 0 end end
SshGetServerSoftwareVersion¶
Get SSH software used by the server through SshGetServerSoftwareVersion.
Example:
function log (args) software = SshGetServerSoftwareVersion() if software == nil then return 0 end end
SshGetClientProtoVersion¶
Get SSH protocol version used by the client through SshGetClientProtoVersion.
Example:
function log (args) version = SshGetClientProtoVersion() if version == nil then return 0 end end
SshGetClientSoftwareVersion¶
Get SSH software used by the client through SshGetClientSoftwareVersion.
Example:
function log (args) software = SshGetClientSoftwareVersion() if software == nil then return 0 end end
Files¶
To use the file logging API, the script's init() function needs to look like:
function init (args) local needs = {} needs['type'] = 'file' return needs end
SCFileInfo¶
fileid, txid, name, size, magic, md5 = SCFileInfo()
returns fileid (number), txid (number), name (string), size (number), magic (string), md5 in hex (string)
SCFileState¶
state, stored = SCFileState()
returns state (string), stored (bool)
Alerts¶
Alerts are a subset of the 'packet' logger:
function init (args) local needs = {} needs["type"] = "packet" needs["filter"] = "alerts" return needs end
SCRuleIds¶
sid, rev, gid = SCRuleIds()
SCRuleMsg¶
msg = SCRuleMsg()
SCRuleClass¶
class, prio = SCRuleClass()
Streaming Data¶
Streaming data can currently log out reassembled TCP data and normalized HTTP data. The script will be invoked for each consecutive data chunk.
In case of TCP reassembled data, all possible overlaps are removed according to the host OS settings.
function init (args) local needs = {} needs["type"] = "streaming" needs["filter"] = "tcp" return needs end
In case of HTTP body data, the bodies are unzipped and dechunked if applicable.
function init (args) local needs = {} needs["type"] = "streaming" needs["protocol"] = "http" return needs end
SCStreamingBuffer¶
function log(args) data = SCStreamingBuffer() hex_dump(data) end
Misc¶
SCThreadInfo¶
tid, tname, tgroup = SCThreadInfo()
It gives: tid (integer), tname (string), tgroup (string)
SCLogError, SCLogWarning, SCLogNotice, SCLogInfo, SCLogDebug¶
Print a message. It will go into the outputs defined in the yaml. Whether it will be printed depends on the log level.
Example:
SCLogError("some error message")
SCLogPath¶
Expose the log path.
name = "fast_lua.log" function setup (args) filename = SCLogPath() .. "/" .. name file = assert(io.open(filename, "a")) end
locked