在Ubuntu系统中实现状态防火墙并统计流量,nftables是当前最推荐的工具。它取代了传统的iptables,提供了更简洁的语法、更高的性能以及统一的管理框架。本文将详细讲解如何在Ubuntu 20.04 LTS及更新版本上,使用nftables配置一个具备连接状态跟踪、数据包计数和基础防护功能的防火墙。

理解nftables的核心概念:表、链与规则

nftables的配置围绕三个核心层级展开。表(Table)是最高层级,用于隔离不同的协议族,例如ip(IPv4)、ip6(IPv6)、inet(同时处理IPv4和IPv6)以及arp、bridge等。链(Chain)存在于表中,是规则的容器,分为基础链和常规链。基础链是网络数据包的入口点,需要绑定钩子(hook)和优先级。规则(Rule)则包含具体的匹配表达式和判决动作。理解这个结构是进行有效配置的前提。

安装与基本配置初始化

Ubuntu通常预装了nftables。如果没有,可以使用sudo apt update && sudo apt install nftables进行安装。首先,建议清除所有现有规则并加载一个干净的配置。备份现有规则后,使用sudo nft flush ruleset清空。然后,创建一个初始配置文件,例如/etc/nftables.conf。我们将主要使用inet协议族来同时管理IPv4和IPv6流量,这能简化双栈网络的配置。

构建一个具备状态跟踪的基础防火墙

状态防火墙的核心是能够识别数据包属于一个新连接、已建立的连接还是相关的连接(如ICMP错误或FTP数据通道)。nftables内置了连接跟踪系统(conntrack)。以下是一个基础防火墙配置框架,定义了输入(input)、转发(forward)和输出(output)策略,并默认丢弃所有流量。

#!/usr/sbin/nft -f

flush ruleset

table inet firewall {
    chain input {
        type filter hook input priority filter; policy drop;

        # 允许本地回环接口流量
        iif "lo" accept
        ct state established,related accept

        # 允许ICMP(ping)
        ip protocol icmp icmp type { echo-request, echo-reply, destination-unreachable, time-exceeded } accept
        ip6 nexthdr icmpv6 icmpv6 type { echo-request, echo-reply, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } accept

        # 允许SSH(端口22)和HTTP/HTTPS(端口80,443)的入站新连接
        tcp dport { 22, 80, 443 } ct state new accept

        # 记录并丢弃所有其他入站流量
        log prefix "[nftables] Denied INPUT: " group 0
        counter drop
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        log prefix "[nftables] Denied FORWARD: " group 0
        counter drop
    }

    chain output {
        type filter hook output priority filter; policy accept;
        ct state established,related accept
    }
}

这个配置中,input链默认丢弃,但允许回环、已建立/相关的连接、必要的ICMP协议以及访问22、80、443端口的新TCP连接。forward链在作为网关时有用,此处也设为默认丢弃。output链默认允许,确保系统发出的流量不受阻。

实现精确的流量计数与监控

nftables的计数器(counter)功能强大且易于使用。你可以将计数器附加到任何规则上,也可以创建独立的计数器对象供多条规则引用。这对于分析流量模式、排查问题至关重要。以下是如何在规则中内联使用计数器,并创建命名计数器。

table inet firewall {
    # 创建一个名为"web_traffic"的命名计数器
    counter web_traffic {
        packets 0 bytes 0
    }

    chain input {
        type filter hook input priority filter; policy drop;

        # 内联计数器:统计所有SSH连接尝试
        tcp dport 22 ct state new counter accept

        # 使用命名计数器:统计HTTP/HTTPS流量
        tcp dport { 80, 443 } ct state new counter name "web_traffic" accept

        # 计数器记录被拒绝的SYN包
        tcp flags syn ct state new counter log prefix "[nftables] Rejected SYN: " drop
    }
}

要查看计数器结果,使用命令sudo nft list counters。你可以看到每个计数器的数据包数量和字节总数,这为流量审计提供了量化依据。

高级状态管理与安全加固技巧

除了基本的established和related状态,nftables的连接跟踪还支持更精细的管理。例如,可以限制新建连接的速率以防止洪水攻击,或为特定连接设置更长的超时时间。以下规则展示了如何限制每分钟来自同一IP的新SSH连接不超过3次,并调整HTTP连接的跟踪超时。

table inet firewall {
    set ssh_ratelimit {
        type ipv4_addr
        flags dynamic, timeout
        timeout 1m
    }

    chain input {
        type filter hook input priority filter; policy drop;

        # SSH连接速率限制
        tcp dport 22 ct state new add @ssh_ratelimit { ip saddr } limit rate 3/minute accept

        # 调整HTTP连接在跟踪表中的超时为5分钟(默认可能更短)
        tcp dport 80 ct state new ct helper set "http" ct timeout set 5m accept
    }
}

此外,建议显式地丢弃无效状态的数据包以提升安全:ct state invalid drop。对于面向公网的服务器,考虑使用ip daddr != { 私有网段 }等条件来限制管理端口的源IP范围。

规则的持久化与运维管理

测试规则无误后,必须将其持久化,否则重启后会丢失。在Ubuntu中,nftables服务会从/etc/nftables.conf读取配置。将最终配置写入该文件,然后执行sudo systemctl enable --now nftables启用服务。日常运维中,常用命令包括:sudo nft list ruleset(查看所有规则)、sudo nft flush chain inet firewall input(清空特定链)、sudo nft monitor trace(实时跟踪规则匹配,用于深度调试)。

与iptables的对比及迁移建议

虽然iptables在旧系统中仍可使用,但nftables在架构上优势明显。其语法更统一(IPv4/IPv6合一),规则集可像编程一样使用变量和集合,执行效率也因更少的内核模块依赖而更高。对于新部署的Ubuntu系统,应直接采用nftables。对于已有iptables规则的系统,可以使用iptables-translateip6tables-translate工具进行辅助迁移,但复杂规则仍需手动调整和测试。

总结来说,在Ubuntu上使用nftables构建状态防火墙是一个高效且面向未来的选择。通过定义清晰的表结构、利用连接跟踪状态、灵活运用计数器进行监控,并实施速率限制等高级策略,你可以构建一个既安全又可观测的防火墙系统。关键在于理解数据包流经钩子的路径,并在此基础上编写精确的匹配规则。