数据包 ------ 可以通过 ``suricata.packet`` 库将数据包暴露给 Lua 脚本。例如:: local packet = require("suricata.packet") 初始化 ~~~~~~~~~~~~~~ ``get`` ^^^^^^^ 初始化数据包以便在脚本中使用。该数据包是引擎当前正在处理的数据包。 :: p = packet.get() 时间 ~~~~ ``timestamp`` ^^^^^^^^^^^^^ 获取数据包时间戳,返回两个数字:自 1970-01-01 00:00:00 UTC 以来的秒数和微秒数。 :: p = packet.get() local sec, usec = p:timestamp() ``timestring_legacy`` ^^^^^^^^^^^^^^^^^^^^^ 获取数据包时间戳,格式为:`11/24/2009-18:57:25.179869`。这是 `fast.log`、`http.log` 和其他传统输出使用的格式。 :: p = packet.get() print p:timestring_legacy() ``timestring_iso8601`` ^^^^^^^^^^^^^^^^^^^^^^ 获取数据包时间戳,格式为:`2015-10-06T15:16:43.137833+0000`。这是 `eve` 使用的格式。 :: p = packet.get() print p:timestring_iso8601() 端口和地址 ~~~~~~~~~~~~~~~~~~~ ``tuple`` ^^^^^^^^^ 使用 `tuple` 方法可以获取 IP 版本(4 或 6)、源 IP 和目标 IP(作为字符串)、IP 协议(整数)以及端口(整数)。 协议值来自 IP 头,详见 https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml :: p = packet.get() ipver, srcip, dstip, proto, sp, dp = p:tuple() 如果协议是 ICMPv4 或 ICMPv6,即当 `proto == 1` 或 `proto == 58` 时,最后两个结果是 `icmp 类型` 和 `icmp 代码`。 :: p = packet.get() ipver, srcip, dstip, proto, itype, icode = p:tuple() if ipver == 6 and proto == 1 then -- 奇怪,IPv6 上的 ICMPv4 return 1 end ``sp`` ^^^^^^ 获取数据包的 TCP、UDP 或 SCTP 源端口(整数)。对于其他协议返回 `nil`。 :: p = packet.get() source_port = p:sp() if source_port == 31337 then return 1 end ``dp`` ^^^^^^ 获取数据包的 TCP、UDP 或 SCTP 目标端口(整数)。对于其他协议返回 `nil`。 :: p = packet.get() dest_port = p:dp() -- 不是 443 端口 if dest_port ~= 443 then return 1 end 数据 ~~~~ ``payload`` ^^^^^^^^^^^ 数据包的有效载荷。 :: payload = p:payload() ``packet`` ^^^^^^^^^^ 完整的数据包,包括 TCP、以太网、VLAN 等协议的头部。 :: raw_packet = p:packet() 杂项 ~~~~ ``pcap_cnt`` ^^^^^^^^^^^^ 从 pcap 文件读取时的数据包编号。 :: p = packet.get() print p:pcap_cnt() 示例 ~~~~~~~ 一个 `match` 函数示例,该函数接收一个数据包,逐行检查有效载荷,查找 HTTP 请求行。 如果找到,则记录一条 notice 日志,包含数据包详细信息。 :: local logger = require("suricata.log") function match (args) p = packet.get() payload = p:payload() ts = p:timestring() for line in payload:gmatch("([^\r\n]*)[\r\n]+") do if line == "GET /index.html HTTP/1.0" then ipver, srcip, dstip, proto, sp, dp = p:tuple() logger.notice(string.format("%s %s->%s %d->%d (pcap_cnt:%d) match! %s", ts, srcip, dstip, sp, dp, p:pcap_cnt(), line)); return 1 end end return 0 end