返回

解决Linux nf_conntrack: helper分配错误 (安全指南)

Linux

Linux 下 "nf_conntrack: default automatic helper assignment..." 问题的解决方法

直接说事,最近碰到个系统提示:nf_conntrack: default automatic helper assignment has been turned off for security reasons and CT-based firewall rule not found. Use the iptables CT target to attach helpers instead. 内核版本是 5.4.23,nftables 版本是 0.9.3。 这啥意思?怎么整?别急,下面咱们来捋一捋。

一、问题原因:内核安全策略变更

这个提示的出现,其实是 Linux 内核为了安全起见,关掉了 conntrack 模块的自动 helper 分配功能。

早些时候,内核会根据你的流量类型,自动给它匹配一个 “helper” 模块。这些 helper 模块是干啥的呢? 像 FTP、SIP 这类协议,一个连接可能会开多个端口,单靠端口过滤不行,就需要 helper 模块来识别、关联这些连接,方便管理。

但是,自动分配 helper 有安全风险。 攻击者可能利用某些 helper 的漏洞,搞事情。 所以,新的内核版本默认就把这个自动功能关掉了。 你得手动指定用哪个 helper。

二、解决方法:告别 “自动挡”,拥抱 “手动挡”

解决这个问题,核心思路就是手动指定需要的 conntrack helper。 下面介绍几个可行的方案。

2.1 方案一: 使用 nftables 的 CT target

nftables 提供了 ct helper 语句,可以直接在规则里绑定 helper。 这是官方推荐的搞法。

  1. 创建 helper 定义

    首先,你要定义一个 helper 对象。 这个对象要指明它处理哪个协议,监听哪个端口。

    nft add helper filter ftp-helper inet { type ftp dport 21 }
    

    解释一下:

    • add helper: 添加 helper 对象的命令。
    • filter: 自定义的名字,你可以改成你喜欢的。
    • ftp-helper: 这个 helper 的名字,也随意。
    • inet: 指定协议族, inet 表示 IPv4。如果是IPv6, 使用 inet6。
    • type ftp: 指明这个 helper 处理的是 ftp 协议。
    • dport 21: 指定监听端口,这里是 FTP 的默认端口。
  2. 在规则中使用 helper

    定义好 helper 之后,在 input 链(或者你处理入站流量的其他链)里,用 ct helper 语句,把它跟具体的流量绑定起来。

    nft add rule filter input tcp dport 21 ct helper set "ftp-helper"
    

    这条规则的意思:对于 TCP 目标端口是 21 的流量,使用刚才定义的名为 "ftp-helper" 的 helper。

    完整nftables配置示例:

    table ip filter {
        helper ftp-helper {
                type ftp dport 21
        }
        chain input {
                type filter hook input priority filter; policy accept;
                ct state established,related accept
                iif "lo" accept
                tcp dport 21 ct helper set "ftp-helper" #添加的helper规则
        }
    
        chain forward {
                type filter hook forward priority filter; policy accept;
        }
    
        chain output {
                type filter hook output priority filter; policy accept;
        }
    }
    

    然后用nft -f <文件名>.nft使配置生效

进阶技巧:

如果你要处理多个端口的同一个协议,可以在 dport 后面用大括号 {} 括起来,用逗号分隔。 比如:

nft add helper filter h323-helper inet { type h323 dport { 1719, 1720 } }
nft add rule filter input tcp dport { 1719, 1720 } ct helper set "h323-helper"

2.2 方案二: 使用 raw 表

如果方案一不奏效(某些情况下可能会这样),可以尝试使用 raw 表。 raw 表在 netfilter 框架里处理数据包非常靠前,甚至在 conntrack 之前。 可以在这里就设置好 helper。

  1. 添加 raw 表规则

    nft add table raw
    nft add chain raw prerouting { type filter hook prerouting priority -300 \; }
    nft add rule raw prerouting tcp dport 21 ct helper set ftp
    
    • 第一行:建立名为raw的表。
    • 第二行: 建立名为prerouting的链, 类型为filter, hook到prerouting, 优先级为-300.
    • 第三行:为 raw 表 prerouting 链添加一条规则: 对于 TCP 目标端口为 21 的数据包,设置 conntrack helper 为 ftp
    • 注意:这里的helper 名字直接写ftp,而不是方案一种定义过的helper名字。
  2. 清空并重新加载规则 (根据情况)

nft flush ruleset
nft -f /path/to/your/nftables.conf # 如果你把配置写到了文件里

因为raw表处理非常靠前, 可能需要在修改后清空所有nftable的配置, 并重新载入.
(根据实际测试判断需不需要进行该步)

注意: 使用 raw 表直接写 ftp 这种,比方案一少了一层 “抽象”。 如果你有自定义需求,比如用非标准端口跑 FTP,方案一更灵活。

2.3方案三 启用自动辅助分配(不建议)

如果你确定自己知道风险,而且必须使用自动 helper 分配(比如某些旧的应用依赖这个),可以临时把它打开。
但是非常不建议,安全性有一定降低

  1. 修改内核参数

    sysctl -w net.netfilter.nf_conntrack_helper=1
    

    这行命令将 net.netfilter.nf_conntrack_helper 设置为 1,就开启了自动分配。

  2. 持久化设置(可选)

    直接用 sysctl 修改是临时的,重启后会失效。 要永久生效,可以把这行加到 /etc/sysctl.conf 文件里:

    net.netfilter.nf_conntrack_helper = 1
    

    然后执行:

    sysctl -p
    

再次强调,方案三仅仅是应急手段,不建议长期使用。 尽量用方案一或者方案二,安全第一。

三、安全建议

  • 最小化原则: 只启用你真正需要的 helper。 没用的 helper 关掉,减少潜在风险。

  • 定期检查: 定期看看系统日志,有没有跟 conntrack 相关的异常。

  • 保持更新: 内核、nftables,能更新就更新,新版本通常会修复已知的安全问题。

  • 端口管理 尽量使用标准端口,减少出现奇怪问题的几率.

    如果对Linux 防火墙感兴趣,可以看看这几个:

  • nftables 官方文档: https://wiki.nftables.org/

  • netfilter 官方网站: https://www.netfilter.org/

搞定! 以后再碰到 nf_conntrack 报错,就不会懵了。