nftables(nft)详解
nft(即 nftables)是 Linux 内核中负责数据包过滤和网络地址转换(NAT)的新一代框架。它在 2014 年并入内核,旨在彻底取代老旧的 iptables、ip6tables、arptables 等工具。
既然你现在的服务器 ruleset 为空,理解它的结构能让你更优雅地掌控网络安全。
1. 核心架构:为什么比 iptables 好?
在 iptables 中,规则是内置在预定义链(如 INPUT, FORWARD)里的;而在 nftables 中,没有预定义的表和链,所有的东西都需要你手动创建。这种“按需定制”大大减少了不必要的内核开销。
-
表 (Tables):容器,包含链。可以指定地址族(如
ip,ip6,inet)。 -
链 (Chains):规则的容器。你需要指定它挂载到哪个内核钩子(如
input,output)。 -
规则 (Rules):具体的指令。
2. 基础操作:从零开始构建
由于你现在的 ruleset 是空的,你可以按照以下逻辑构建一个基础防火墙。
A. 创建表 (Table)
使用 inet 地址族可以同时管理 IPv4 和 IPv6,非常省事。
Bash
nft add table inet my_filter
B. 创建链 (Chain)
我们要创建一个处理入站流量的链。
-
type filter:说明这是过滤用的。 -
hook input:挂载到入站钩子。 -
policy accept:默认策略是允许(初学者建议先选 accept,等规则写稳了再改 drop,防止把自己锁外面)。
Bash
nft add chain inet my_filter my_input_chain { type filter hook input priority 0 \; policy accept \; }
C. 添加规则 (Rule)
规则是按顺序匹配的。
-
允许已建立的连接(确保你的 SSH 不会掉线):
Bash
nft add rule inet my_filter my_input_chain ct state established,related accept -
允许本地回环 (lo):
Bash
nft add rule inet my_filter my_input_chain iif lo accept -
放行特定端口(例如 Go 程序常用的 8080):
Bash
nft add rule inet my_filter my_input_chain tcp dport 8080 accept -
丢弃(Drop)来自特定 IP 的所有包:
Bash
nft add rule inet my_filter my_input_chain ip saddr 123.123.123.123 drop
3. 查看与管理
- 列出所有规则(带 handle 编号,删除时必用):
Bash
nft -a list ruleset
```
* **删除特定规则**:
假设你想删除 handle 为 5 的规则:
```bash
nft delete rule inet my_filter my_input_chain handle 5
```
* **清空整个 ruleset**(相当于防火墙全开):
```bash
nft flush ruleset
```
---
## 4. 进阶用法:一次性加载配置
`nftables` 支持非常人性化的语法,你可以把规则写在一个文本文件里(如 `firewall.nft`):
```nft
table inet my_filter {
chain my_input {
type filter hook input priority 0; policy drop;
# 允许已建立的连接
ct state established,related accept
# 允许回环
iif "lo" accept
# 允许 SSH
tcp dport 22 accept
# 允许 Go 程序的 HTTP 服务
tcp dport 8080 accept
}
}
然后执行 nft -f firewall.nft 即可原子性地更新所有规则。如果文件里有语法错误,旧规则会继续生效,不会导致网络中断。
5. 总结
| 特性 | iptables | nftables (nft) |
|---|---|---|
| 语法 | 晦涩、参数多 | 类似类 C 语言,更易读 |
| 性能 | 规则多时性能线性下降 | 使用高效的数据结构(如集合),性能极佳 |
| 协议支持 | IPv4/IPv6 需分开管理 | 一个 inet 族通吃 |
| 灵活性 | 预置链,改动受限 | 完全自定义,按需创建 |
既然你现在是 root 权限且没有防火墙干扰,建议你先尝试创建一个 inet 表并放行你的 Go 程序端口。
你打算把你的 Go 服务跑在哪个端口?我们可以针对性地写一条最安全的 nft 规则。