nftables学习笔记

nftables 是 Linux 内核中的新一代数据包过滤框架,旨在替代传统的 iptables。它提供了更简洁的语法、更好的性能和更多的功能。

基础概念

主要组件

  • 表 (Tables):规则的容器,类似于数据库中的表

  • 链 (Chains):规则的集合,类似于iptables中的链

  • 规则 (Rules):具体的过滤条件

  • 集合 (Sets):命名的元素集合,用于高效匹配

与 iptables 对比

  • 统一的配置语法

  • 更好的性能

  • 支持匿名集合和映射

  • 更简洁的规则管理

安装与基本配置

安装 nftables

Ubuntu/Debian:

sudo apt update
sudo apt install nftables

CentOS/RHEL:

sudo yum install nftables
# 或对于较新版本
sudo dnf install nftables

启动服务

# 启动服务
sudo systemctl start nftables

# 设置开机自启
sudo systemctl enable nftables

# 检查状态
sudo systemctl status nftables

基本语法结构

基本命令格式

nft [选项] 命令 [对象] 规则

常用选项

  • add – 添加规则

  • delete – 删除规则

  • list – 列出规则

  • flush – 清空规则

常用规则实例

1. 基本防火墙配置

创建简单的防火墙表

# 创建表
sudo nft add table inet filter

# 创建输入链
sudo nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }

# 创建输出链
sudo nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }

# 创建转发链
sudo nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }

保存配置

# 保存当前规则
sudo nft list ruleset > /etc/nftables.conf

# 使配置永久生效(系统启动时加载)
echo 'include "/etc/nftables.conf"' > /etc/sysconfig/nftables.conf

2. 常用防火墙规则

允许本地回环

sudo nft add rule inet filter input iifname "lo" accept
sudo nft add rule inet filter output oifname "lo" accept

允许已建立的连接

sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter output ct state established,related accept

允许 SSH 连接

sudo nft add rule inet filter input tcp dport 22 accept

允许 HTTP 和 HTTPS

sudo nft add rule inet filter input tcp dport {80, 443} accept

允许 DNS 查询

sudo nft add rule inet filter input udp dport 53 accept
sudo nft add rule inet filter output udp dport 53 accept

3. 网络地址转换 (NAT)

创建 NAT 表

# 创建 nat 表
sudo nft add table ip nat

# 创建 prerouting 链
sudo nft add chain ip nat prerouting { type nat hook prerouting priority -100 \; }

# 创建 postrouting 链
sudo nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }

SNAT 示例(源地址转换)

# 将内部网络 192.168.1.0/24 的流量转换为公网 IP
sudo nft add rule ip nat postrouting ip saddr 192.168.1.0/24 oifname "eth0" masquerade

DNAT 示例(目的地址转换)

# 将公网 IP 的 80 端口转发到内部服务器
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 80 dnat to 192.168.1.100:80

4. 流量限制

限制 SSH 连接频率

# 创建限制集合
sudo nft add set inet filter ssh_limits { type ipv4_addr \; flags timeout \; }

# 限制 SSH 连接:每分钟最多 3 次新连接
sudo nft add rule inet filter input tcp dport 22 ip saddr @ssh_limits drop
sudo nft add rule inet filter input tcp dport 22 limit rate 3/minute add @ssh_limits { ip saddr }

限制 ICMP 请求

sudo nft add rule inet filter input proto icmp icmp type echo-request limit rate 1/second accept
sudo nft add rule inet filter input proto icmp icmp type echo-request drop

表、链和规则集管理

表管理

列出所有表

sudo nft list tables

查看特定表

sudo nft list table inet filter

删除表

sudo nft delete table inet filter

链管理

创建自定义链

# 创建自定义链用于日志记录
sudo nft add chain inet filter logchain

# 向自定义链添加规则
sudo nft add rule inet filter logchain log prefix "Dropped: " level info
sudo nft add rule inet filter logchain drop

跳转到自定义链

# 将特定流量跳转到日志链
sudo nft add rule inet filter input tcp dport 23 jump logchain

规则管理

列出所有规则

sudo nft list ruleset

添加带注释的规则

sudo nft add rule inet filter input tcp dport 22 accept comment "Allow SSH"

删除规则

# 首先找到规则的句柄
sudo nft --handle list chain inet filter input

# 然后使用句柄删除规则
sudo nft delete rule inet filter input handle 3

高级功能

使用集合

定义命名集合

# 创建 IP 地址集合
sudo nft add set inet filter allowed_ips { type ipv4_addr \; }

# 向集合添加元素
sudo nft add element inet filter allowed_ips { 192.168.1.100, 192.168.1.200 }

# 使用集合进行匹配
sudo nft add rule inet filter input ip saddr @allowed_ips accept

使用匿名集合

# 直接在规则中使用匿名集合
sudo nft add rule inet filter input tcp dport {22, 80, 443} accept

使用映射

创建端口映射

# 创建端口转发映射
sudo nft add map inet filter port_forward { type inet_service : ipv4_addr . inet_service \; }

# 添加映射条目
sudo nft add element inet filter port_forward { 8080 : 192.168.1.100 . 80 }

# 使用映射进行 DNAT
sudo nft add rule ip nat prerouting tcp dport map @port_forward dnat to ip daddr . tcp dport

日志记录

基本日志记录

# 记录被拒绝的数据包
sudo nft add rule inet filter input tcp dport 23 log prefix "Telnet attempt: " drop

带限制的日志记录

# 限制日志记录频率
sudo nft add rule inet filter input tcp dport 23 log prefix "Telnet: " limit rate 3/minute drop

实用脚本示例

完整的家庭防火墙配置

#!/bin/bash

# 清空现有规则
sudo nft flush ruleset

# 创建表
sudo nft add table inet firewall

# 创建链
sudo nft add chain inet firewall input { type filter hook input priority 0 \; policy drop \; }
sudo nft add chain inet firewall forward { type filter hook forward priority 0 \; policy drop \; }
sudo nft add chain inet firewall output { type filter hook output priority 0 \; policy accept \; }

# 允许本地回环
sudo nft add rule inet firewall input iif "lo" accept
sudo nft add rule inet firewall output oif "lo" accept

# 允许已建立和相关的连接
sudo nft add rule inet firewall input ct state established,related accept

# 允许 ICMP (ping)
sudo nft add rule inet firewall input ip protocol icmp icmp type echo-request limit rate 1/second accept
sudo nft add rule inet firewall input ip protocol icmp icmp type echo-request drop

# 允许 SSH (限制连接频率)
sudo nft add set inet firewall ssh_limit { type ipv4_addr \; flags timeout \; }
sudo nft add rule inet firewall input tcp dport 22 ip saddr @ssh_limit drop
sudo nft add rule inet firewall input tcp dport 22 limit rate 3/minute add @ssh_limit { ip saddr } accept

# 允许 HTTP 和 HTTPS
sudo nft add rule inet firewall input tcp dport {80, 443} accept

# 允许 DNS
sudo nft add rule inet firewall input udp dport 53 accept

# 记录并拒绝其他所有输入流量
sudo nft add rule inet firewall input log prefix "Dropped input: " limit rate 3/minute drop

# 保存配置
sudo nft list ruleset > /etc/nftables.conf

echo "Firewall configuration completed and saved."

Web 服务器防火墙配置

#!/bin/bash

# 清空规则
sudo nft flush ruleset

# 创建表
sudo nft add table inet web_firewall

# 创建链
sudo nft add chain inet web_firewall input { type filter hook input priority 0 \; policy drop \; }
sudo nft add chain inet web_firewall output { type filter hook output priority 0 \; policy accept \; }

# 基本规则
sudo nft add rule inet web_firewall input iif "lo" accept
sudo nft add rule inet web_firewall input ct state established,related accept

# Web 服务端口
sudo nft add rule inet web_firewall input tcp dport {80, 443} accept

# SSH 访问(限制来源 IP)
sudo nft add set inet web_firewall allowed_ssh_ips { type ipv4_addr \; }
sudo nft add element inet web_firewall allowed_ssh_ips { 192.168.1.0/24, 203.0.113.50 }
sudo nft add rule inet web_firewall input tcp dport 22 ip saddr @allowed_ssh_ips accept

# 监控端口
sudo nft add rule inet web_firewall input tcp dport 9090 accept

# 保存配置
sudo nft list ruleset > /etc/nftables.conf

echo "Web server firewall configuration completed."

调试和故障排除

查看规则统计信息

sudo nft list ruleset -a

监控实时流量

# 查看数据包计数
sudo nft list ruleset | grep -E "(counter|packets)"

# 重置计数器
sudo nft reset counters

测试规则

# 临时添加规则进行测试
sudo nft add rule inet filter input tcp dport 8080 accept

# 测试后删除
sudo nft delete rule inet filter input handle [handle-number]

总结

nftables 提供了强大而灵活的数据包过滤功能,具有以下优势:

  1. 统一语法:替代 iptables、ip6tables、arptables 和 ebtables

  2. 更好性能:使用更高效的数据结构

  3. 动态更新:支持原子规则更新

  4. 丰富功能:支持集合、映射等高级功能

通过本教程的实例,您可以开始使用 nftables 构建适合自己需求的防火墙配置。建议在生产环境部署前充分测试所有规则。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部
×
问题求助