在 Linux 上配置 Suricata IPS/内联模式

在 Linux 上配置 Suricata IPS/内联模式

使用 Netfilter 配置 IPS

本指南介绍如何使用 iptables,让 Suricata 以第三层内联模式运行。

首先编译启用 NFQ 支持的 Suricata;步骤见原文链接的 Ubuntu 安装指南。关于 NFQ 与 iptables 的更多信息,参阅 Suricata 的 NFQ 文档。

运行以下命令,检查当前构建是否启用了 NFQ:

suricata --build-info

确认输出中列出了 NFQ。 使用 NFQ 模式运行时,需要传入 -q 选项,指定 Suricata 使用的队列编号。

sudo suricata -c /etc/suricata/suricata.yaml -q 0

iptables 配置

首先确定要将哪些流量发送给 Suricata。可分为两种情况:

  1. 经过这台计算机的流量。

  2. 由这台计算机产生的流量。

原文示意图 原文示意图

如果 Suricata 运行在网关上,用于保护网关后面的计算机,属于第一种转发场景。 如果 Suricata 用于保护其所在计算机,则属于第二种主机场景,参见图 2。

这两种用法也可以组合。

在网关场景下,向 Suricata 发送流量最简单的规则是:

sudo iptables -I FORWARD -j NFQUEUE

这会把所有转发流量送到 Suricata。 主机场景下,最简单的两条 iptables 规则是:

sudo iptables -I INPUT -j NFQUEUE
sudo iptables -I OUTPUT -j NFQUEUE

可以指定队列编号;若不指定,默认为 0。 例如,只检查 TCP 流量,或端口 80 的传入流量、目标端口为 80 的流量,可以这样设置:

sudo iptables -I INPUT -p tcp  -j NFQUEUE
sudo iptables -I OUTPUT -p tcp -j NFQUEUE

本例只检查 TCP 流量。

sudo iptables -I INPUT -p tcp --sport 80  -j NFQUEUE
sudo iptables -I OUTPUT -p tcp --dport 80 -j NFQUEUE

这个示例检查所有发往端口 80 的出站连接的数据包。

原文示意图 原文示意图

确认 Suricata 正在运行,再执行以下命令,检查 iptables 规则是否设置正确:

sudo iptables -vnL

从示例中可以看到是否有数据包被记录。

原文示意图 上述 iptables 用法针对 IPv4。处理 IPv6 时,将前述命令中的 iptables 替换为 ip6tables。也可以让 Suricata 同时检查两类流量。

还可以让 iptables 处理多个网络与网卡,例如:

原文示意图
sudo iptables -I FORWARD -i eth0 -o eth1 -j NFQUEUE
sudo iptables -I FORWARD -i eth1 -o eth0 -j NFQUEUE

-i(输入)和 -o(输出)可以与前面介绍的所有选项组合。

如果此时停止 Suricata,网络流量将无法通过。原文要求先删除 iptables 规则,以恢复网络访问。

清除所有 iptables 规则的命令如下:

sudo iptables -F

nftables 配置

nftables 配置很直接,也允许混合使用防火墙规则与 IPS。思路是为 IPS 创建独立链,在防火墙规则之后执行。如果主表名为 filter,可这样创建:

nft> add chain filter IPS { type filter hook forward priority 10;}

将全部转发数据包送到 Suricata:

nft> add rule filter IPS queue

如果只处理 eth0 与 eth1 之间交换的数据包:

nft> add rule filter IPS iif eth0 oif eth1 queue
nft> add rule filter IPS iif eth1 oif eth0 queue

NFQUEUE 高级选项

NFQUEUE 机制支持一些实用选项。这里展示 nftables 配置;iptables 也支持这些功能。

队列机制的完整语法如下:

nft add rule filter IPS queue num 3-5 options fanout,bypass

这条规则把匹配的数据包送到编号 3 至 5 的三个负载均衡队列。要使 Suricata 接收这些队列中的数据包,需在命令行指定多个队列:

suricata -q 3 -q 4 -q 5

可用选项为 fanout 与 bypass: – fanout:与负载均衡一起使用时,以 CPU ID 而不是连接哈希作为索引,将数据包映射到队列。每个 CPU 对应一个队列,有助于提升性能;必须指定多于一个队列。 – bypass:默认情况下,如果没有用户态程序监听 Netfilter 队列,所有准备入队的数据包都会被丢弃。启用此选项后,若没有程序监听,该队列规则会像 ACCEPT 一样处理,数据包继续进入下一张表。

bypass 可以避免 Suricata 未运行时链路中断,但此时也不会提供阻断功能。 ## 在第二层配置 IPS ### AF_PACKET IPS 模式

AF_PACKET 捕获方式支持 IPS/Tap 模式。只需让接口处于启用状态,Suricata 就会负责把数据包从一个接口复制到另一个接口,不需要配置 iptables 或 nftables。

这种模式需要专用的两块网络接口,通过 AF_PACKET 接口定义中的配置变量设置。 下面的配置使 Suricata 在 eth0 与 eth1 之间充当 IPS:

af-packet:
  - interface: eth0
    threads: 1
    defrag: no
    cluster-type: cluster_flow
    cluster-id: 98
    copy-mode: ips
    copy-iface: eth1
    buffer-size: 64535
  - interface: eth1
    threads: 1
    cluster-id: 97
    defrag: no
    cluster-type: cluster_flow
    copy-mode: ips
    copy-iface: eth0
    buffer-size: 64535

这是使用两个接口的基本 AF_PACKET 配置。由于以下 copy-* 设置,eth0 收到的全部数据包会复制到 eth1:

copy-mode: ips
copy-iface: eth1

eth1 上的设置与之对称:

copy-mode: ips
copy-iface: eth0

设置这种模式时,需要注意: – 两个接口的 MTU 必须相同。接口之间直接复制数据包,超过 MTU 的数据包会被内核丢弃。

  • 两个接口的 cluster-id 必须不同,以避免冲突。

  • 任何产生大于物理层数据报的网卡卸载功能,例如 GRO、LRO、TSO,都会导致丢包,因为发送路径无法处理这些数据包。

  • 将 stream.inline 设为 auto 或 yes,使 Suricata 切换到阻断模式。 copy-mode 可取以下值:

  • ips:遵循 drop 关键字,丢弃匹配的数据包。

  • tap:不丢包,Suricata 作为网桥。 要把捕获方式扩展到多个线程,需格外注意。不能使用会生成过大帧的 defrag,因此内核负载均衡可能不正确:仅带 IP 信息的分片不含端口信息,可能无法与同一流中包含完整信息的数据包进入同一个线程。 一种解决办法是使用 eBPF 负载均衡,按 IP 对分配流量而不进行分片重组。多线程及 eBPF 负载均衡的 AF_PACKET IPS 配置如下:

af-packet:
  - interface: eth0
    threads: 16
    defrag: no
    cluster-type: cluster_ebpf
    ebpf-lb-file: /usr/libexec/suricata/ebpf/lb.bpf
    cluster-id: 98
    copy-mode: ips
    copy-iface: eth1
    buffer-size: 64535
  - interface: eth1
    threads: 16
    cluster-id: 97
    defrag: no
    cluster-type: cluster_ebpf
    ebpf-lb-file: /usr/libexec/suricata/ebpf/lb.bpf
    copy-mode: ips
    copy-iface: eth0
    buffer-size: 64535

磁盘上可能不存在 /usr/libexec/suricata/ebpf/lb.bpf。更多信息参阅 Suricata 的 eBPF 与 XDP 文档。 ### DPDK IPS 模式

DPDK 捕获模块的配置方式与 AF_PACKET IPS 类似。在开始 IPS/内联配置前,建议阅读 DPDK 手册页,了解基本设置。 DPDK IPS 同样使用两个接口。第一块接口 0000:3b:00.1 收到的数据包由第二块接口 0000:3b:00.0 发出,反方向亦然。这种模式不会修改数据包。 下面的片段配置两块网卡之间的 Suricata DPDK IPS 模式:

dpdk:
  eal-params:
    proc-type: primary

  interfaces:
  - interface: 0000:3 b:00.1
    threads: 4
    promisc: true
    multicast: true
    checksum-checks: true
    checksum-checks-offload: true
    mempool-size: 262143
    mempool-cache-size: 511
    rx-descriptors: 4096
    tx-descriptors: 4096
    copy-mode: ips
    copy-iface: 0000:3 b:00.0
    mtu: 3000

  - interface: 0000:3 b:00.0
    threads: 4
    promisc: true
    multicast: true
    checksum-checks: true
    checksum-checks-offload: true
    mempool-size: 262143
    mempool-cache-size: 511
    rx-descriptors: 4096
    tx-descriptors: 4096
    copy-mode: ips
    copy-iface: 0000:3 b:00.1
    mtu: 3000

上面的 DPDK 配置有几个注意点:

  • copy-mode:参阅 AF_PACKET IPS 模式小节。

  • copy-iface:参阅 AF_PACKET IPS 模式小节。

  • threads:所有接口条目都必须设置线程数;成对连接的接口必须设置相同的线程数。

  • mtu:配对接口的 MTU 必须相同。 DPDK 捕获模块还要求在配置文件中设置 CPU 亲和性。为获得最佳性能,每个 Suricata worker 应绑定到独立 CPU 核,不与其他 Suricata 线程(例如管理线程)共享。以下是可用于 DPDK IPS 的线程配置:

threading:
  set-cpu-affinity: yes
  cpu-affinity:
    management-cpu-set:
      cpu: [ 0 ]
    worker-cpu-set:
      cpu: [ 2,4,6,8,10,12,14,16 ]

Netmap IPS 模式

Netmap IPS 需要配置接口对:数据包从其中一个接口接收,经 Suricata 检查后从另一个接口发出。可使用原生模式或主机协议栈模式;接口名中含 ^ 时使用后者,例如 enp6s0f0^。主机协议栈模式不要求多块物理网卡。 #### Netmap 主机协议栈模式

Netmap 主机协议栈模式允许流经 Suricata 的数据包供主机上的其他应用使用,例如防火墙。它也允许通过同一块网卡接收和发送流量。 在这种模式下,Netmap 创建一对主机协议栈环形缓冲区,分别用于 RX 和 TX。入站数据包从网卡进入操作系统网络协议栈,再进入环形缓冲区;出站数据包则从环形缓冲区经过协议栈,最后到达网卡。 Suricata 从这些环形缓冲区接收数据包,并在 IPS 模式下将待发送的数据包放回缓冲区。Suricata 写入其中的数据包也可供其他主机应用使用。 在 netmap 配置节中指定配对接口。下面的配置使 Suricata 在 enp6s0f0 与 enp6s0f1 之间充当 IPS:

netmap:
  - interface: enp6s0f0
    threads: auto
    copy-mode: ips
    copy-iface: enp6s0f1

  - interface: enp6s0f1
    threads: auto
    copy-mode: ips
    copy-iface: enp6s0f0

可以指定 threads。默认的 auto 会为网卡支持的每个队列创建一个线程;也可明确限制,例如 threads: 1。

这是使用两个接口的基本 Netmap 配置。enp6s0f0 定义中的 copy-* 变量使 Suricata 在配对接口之间复制数据包:

copy-mode: ips
copy-iface: enp6s0f1

enp6s0f1 上的配置与之对称:

copy-mode: ips
copy-iface: enp6s0f0

也可以使用 Netmap 主机协议栈模式,这种模式不需要第二块网卡。

下面是使用单一物理接口的主机协议栈模式示例;原文描述将接口写为 enp6s0f01:

- interface: enp60s0f0
  copy-mode: ips
  copy-iface: enp6s0f0^

enp6s0f0^ 上的配置与之对称:

- interface: enp60s0f0^
  copy-mode: ips
  copy-iface: enp6s0f0

当运行模式为 workers 时,Suricata 使用零拷贝模式。

设置这种模式时,需要注意:

  • GRO、LRO、TSO 等产生大于物理层数据报的网卡卸载功能会导致丢包,因为发送路径无法处理。
  • 将 stream.inline 设为 auto 或 yes,使 Suricata 切换到阻断模式;默认值为 auto。

copy-mode 可取以下值:

  • ips:遵循 drop 关键字并丢弃匹配的数据包。

  • tap:不丢包,Suricata 作为网桥。

来源与许可

Suricata 8.0.7 官方文档,Open Information Security Foundation 与文档贡献者。文档采用 CC BY-NC 4.0,保留非商业性使用条件。中文翻译与静态排版转换于 2026-10-03 完成;保留原始命令和配置,未执行。原文部分接口名有空格或拼写不一致,已单独记录于校核说明,未擅自改写配置。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容