Linux iptables 防火墙管理实战:规则配置、NAT 转发与故障排查
从 Netfilter 数据包路径、五表五链、iptables 常用参数和 conntrack,到安全开放端口、DNAT/SNAT、双网卡路由、IPv6、Docker/Kubernetes、规则持久化与生产排障。
一台 Linux 服务器的服务端口已经监听,为什么外部仍然连接超时?端口转发明明配置了 DNAT,为什么后端收到了请求却无法正常应答?Docker 映射端口后,为什么主机的 INPUT 规则似乎没有生效?
这些问题的关键在于:iptables 不是一张简单的“允许/拒绝列表”,而是 Linux Netfilter 数据包处理路径上的规则配置接口。了解数据包走过什么 Hook、使用哪张表、匹配哪条链,以及什么时候做 NAT,才能有效排查。
如果你先想分清 iptables-nft、iptables-legacy、nftables、firewalld、UFW 的关系,可以先查看第 1.1 节的分层架构图及第 1.2~1.5 节的说明;关于 DNAT/SNAT 是否需要成对配置,见第 6.5~6.6 节。
本文以 Linux 常见的 iptables 1.8.x 命令接口为例,覆盖单机防火墙、双网卡网关、数据库白名单、容器网络与故障排查。每组示例都会解释命令用途、关键参数、是否修改规则以及验证步骤,避免只堆叠命令。
操作前须知:本文的修改命令只适合测试环境或有控制台、维护窗口和自动回滚机制的生产环境。
- 示例网段使用内网
192.168.10.0/24、文档专用公网地址198.51.100.10/203.0.113.50,网卡enp1s0(WAN)与enp2s0(LAN)。这些只是示例,必须替换为实际网络信息。- 操作 iptables 通常需要 root 权限;执行
DROP、REJECT、-F、-P、iptables-restore可能直接导致 SSH 断线、业务不可用或容器网络中断。- 不要在未知 Docker、Kubernetes、firewalld、UFW 或 nftables 的管理关系前覆盖规则;不同管理器的规则不一定出现在同一视图。
- 本文依据官方手册整理,未在你的生产环境执行过以下规则变更。
- SSH 安全顺序:先保存现有规则 → 准备独立控制台与自动回滚 → 放行管理来源与已建立连接 → 再收紧默认策略 → 从第二个连接验证 → 最后持久化。
1. iptables、Netfilter 与现代 Linux 防火墙
1.1 一张图看懂管理工具、规则语法与内核
先区分五个层次:
- 管理工具:
firewalld、UFW负责把“开放哪些端口、限制哪些来源”等高级策略转成实际规则,它们不是两套独立的内核防火墙。 - 规则语法/体系:
iptables是传统规则语法及命令接口;nftables是更现代的规则体系,同时包括相应内核接口。两者都围绕 Linux 的数据包过滤、NAT 等能力展开。 - 命令实现:
iptables-legacy与iptables-nft是iptables语法的两种实现;nft是nftables的原生命令行工具。 - 内核规则后端:
iptables-legacy使用传统 xtables 规则接口;iptables-nft和nft都能操作现代nf_tables规则接口。它们不是三套独立的 Linux 内核。 - 底层执行:最终仍然由 Linux 内核的 Netfilter 框架参与包过滤、NAT、连接跟踪与相应 Hook 处理。
最容易理解的对应关系是:firewalld / UFW(管理)→ iptables / nftables(规则方式)→ iptables-legacy、iptables-nft / nft(具体命令实现)→ Linux Netfilter(内核执行)。中间的箭头表示抽象层级,不代表所有管理工具都必须逐层调用某一个特定程序。
这是一张概念关系图,不是软件包依赖树:firewalld / UFW 实际通过哪种后端落实规则,取决于其版本和配置;nft 是 nftables 的管理命令,而 nftables 还包含内核 nf_tables 规则体系。
**一句话总结:**不要把 firewalld/UFW(管理工具)、iptables/nftables(规则接口或体系)、iptables-legacy/iptables-nft/nft(命令实现)混为一谈。它们最终都基于 Netfilter 处理数据包,但内核规则后端、工具语法及管理责任并不完全相同。
1.2 iptables、iptables-nft、iptables-legacy、nftables 和 nft 分别是什么?
| 名称 | 它究竟是什么? | 实际规则接口 / 需要注意 |
|---|---|---|
| Netfilter | Linux 内核网络包处理框架 | 提供 Hook、连接跟踪、NAT、过滤等基础能力 |
iptables / ip6tables | 用户态命令名称及兼容的规则语法 | 当前具体实现可能是 iptables-nft 或 iptables-legacy;前者/后者分别对应 nft / legacy |
iptables-legacy | 保留旧 iptables 语法的传统实现 | 操作旧式 xtables 规则接口,不通过 nf_tables 接口写规则 |
iptables-nft | 保留旧 iptables 语法的兼容实现 | 把 iptables 命令转换为对 nf_tables 的操作;不是 nft 命令的别名 |
| nftables | 现代 Linux 包过滤规则体系(含内核 nf_tables API) | 支持原生表、链、集合、映射、IPv4/IPv6 等 |
nft | nftables 的原生命令行工具 | 通过 nftables 语法直接管理 nf_tables 规则 |
| firewalld | 防火墙管理服务 | 通过 zone、service、policy 管理规则;现代默认后端为 nftables |
| UFW | 简化防火墙管理工具 | Ubuntu 常见实现依赖 iptables/ip6tables 系列命令,可能经 iptables-nft 进入 nf_tables |
例如,以下两行表达了相似的规则意图,但语法不一样:
# iptables 语法:filter/INPUT 链中允许目标 TCP 443(会实际修改规则)
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# nftables 原生语法:要求系统已创建 inet filter 表及 input 基础链(同样会修改规则)
sudo nft add rule inet filter input tcp dport 443 accept
命令解释与前提:-A INPUT 在 iptables 的 INPUT 链尾部追加规则;-p tcp --dport 443 只匹配目的 TCP 443;-j ACCEPT 表示接受匹配的包。nft add rule 是 nftables 原生“向指定表/链添加规则”的语法。两条都是会立即改变防火墙的演示命令,不能在生产服务器一起执行;第二条在 inet filter input 不存在时会报错,不会自动为你创建表和链。即使添加了 ACCEPT,也不代表其他 Hook、firewalld、云安全组不可能拒绝连接。
1.3 firewalld:更高层的策略管理工具
firewalld 负责管理 zone、service、policy 等高层防火墙策略,最终由其选定的内核规则后端落实。 关键不是它是否调用了 iptables 这个程序,而是它作为管理器负责维护规则。
firewall-cmd是 firewalld 的客户端命令,firewalld 守护服务负责把 zone、service、policy 等配置落到选定的后端。- 在 firewalld 官方文档中,
FirewallBackend=nftables是默认值;主要规则可以直接进入 nftables 后端,因此无需把iptables-legacy当成先决条件。 - 历史上也存在
FirewallBackend=iptables选项,但该后端已被 firewalld 标为弃用;旧式direct/passthrough功能可能仍使用 iptables/ip6tables/ebtables 路径,必须具体检查。 - 不能用“firewalld 使用 nftables”推出“主机上不需要安装任何 iptables 相关工具”:发行版依赖包和兼容功能可能另有要求;核心区别是firewalld 默认防火墙规则不依赖传统 iptables-legacy 后端。
示例:用 firewalld 开放 HTTPS:
# 只读确认 firewalld 是否运行及当前默认 zone
sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
# 演示:开放当前默认 zone 的 HTTPS(会修改防火墙)
# sudo firewall-cmd --add-service=https
命令解释:--state 查询 firewalld 服务是否运行;--get-default-zone 查询没有其他明确分配时的默认区域。--add-service=https(保持为注释演示)只修改 firewalld 运行时配置,针对的 zone 由实际参数与系统上下文决定;需持久化则应按 firewalld 规则管理流程审查 --permanent、--reload 的影响。firewall-cmd 是高层命令,不要求你亲自编写 iptables 的 -A INPUT 语法。
官方:firewalld.conf 的 FirewallBackend 说明。
1.4 UFW:更简单的策略管理入口
UFW 负责将简洁的 allow、deny 等策略转换成 Linux 防火墙规则,最终同样依托 Netfilter。 在 Ubuntu 常见实现中,它通常通过 iptables/ip6tables 用户态工具完成这个过程,但这只是具体实现路径,不是判断 UFW 与 Netfilter 层级关系的关键。
典型链路是:
ufw allow 443/tcp
↓
UFW 解析策略
↓
iptables / ip6tables 系列命令(如 restore)
↓
由系统选择 iptables-nft 或 iptables-legacy
↓
nf_tables 或传统 xtables 内核规则
因此必须区分两个问题:
- UFW 需不需要
iptables命令/软件包? 在常见 Ubuntu UFW 0.36.x 配置中,通常需要相应命令工具。 - UFW 需不需要旧的
iptables-legacy内核规则接口? 不需要必然如此。如果系统把iptables指向iptables-nft,UFW 的规则可以通过兼容工具落在nf_tables后端。
Ubuntu 官方文档既将 UFW 归类为方便使用的防火墙前端,也提醒在经典实现中它调用 iptables 工具;其他发行版或未来的 UFW 实现可能不同,应以实际版本、安装包依赖与已选后端为准。
# 查询 UFW 状态(未安装时可能返回 command not found)
sudo ufw status verbose
# 查询 Ubuntu 当前 iptables 命令指向的实现
iptables --version
update-alternatives --display iptables
命令解释:ufw status verbose 查看 UFW 状态、默认策略和部分规则,不会更改规则;iptables --version 中的 (nf_tables) 或 (legacy) 表示当前 iptables 工具的后端;update-alternatives --display iptables 在 Debian/Ubuntu 上只查询当前命令选择和候选实现,其他发行版未必提供这套 alternatives 机制。
参考:Ubuntu 安全文档:Firewall · Ubuntu 安全文档:nftables 与 UFW 的使用边界。
1.5 如何辨认服务器实际使用哪套规则?
# 1. 观察当前 iptables 命令后端
iptables --version
# 2. 查询 nft 与 legacy(如果系统提供对应的可执行文件)
command -v iptables-nft
command -v iptables-legacy
sudo iptables-nft -S
sudo iptables-legacy -S
# 3. 查询 nftables 全部规则,以及 IPv6 的对应规则
sudo nft list ruleset
sudo ip6tables -S
# 4. 查询上层管理服务(未安装时相应命令可能不存在)
systemctl is-active firewalld
sudo firewall-cmd --state
sudo ufw status verbose
# 5. Debian / Ubuntu:检查当前 iptables 命令的程序选择
update-alternatives --display iptables
命令解释与查看范围:
| 命令 | 能确认什么 | 不能代表什么 |
|---|---|---|
iptables --version | 当前 iptables 是 (nf_tables) 还是 (legacy) | 不能证明另一种后端完全没有规则 |
iptables-nft -S | nft 兼容接口所管理的 iptables 风格规则 | 不是全部原生 nft 规则的完整视图 |
iptables-legacy -S | 传统 xtables 规则 | 不包含 nf_tables 中的原生规则 |
nft list ruleset | nftables 原生规则与多数兼容层创建的规则 | 不显示旧式 xtables 规则 |
ip6tables -S | 当前 IPv6 iptables 规则视图 | 不等于覆盖所有原生 nft IPv6 规则 |
systemctl is-active firewalld / ufw status verbose | 是否运行、上层管理器显示的规则 | 不等于所有组件都只受它管理 |
以上都是查询操作。如果 iptables-nft / iptables-legacy / firewall-cmd / ufw 不存在,应跳过对应命令,不要为了“检查”而安装、启动或切换防火墙管理器。
最常见的误判:iptables-legacy -S 中没有规则,不代表 nft/firewalld/UFW 没有过滤流量;反过来也一样。更关键的是:同一数据包可以经过多个过滤 Hook 或规则链,一处 ACCEPT 不保证全局放行,而另一个位置的 DROP 仍可能阻断。
2. Netfilter 数据包处理机制:Hook、Table、Chain 与 Rule
先纠正一个常见说法:所谓 iptables「五表五链」并不是五张表对应五条链,也不是数据包依次通过五张表。
对于传统 IPv4/IPv6 的 iptables,可以概括为:五张常见规则表、五个经典 IP Hook,以及分布在各张表中的多条规则链。理解完整数据路径,应该从内核的 Hook 开始,而不是从某张表开始。
本章最重要的一句话:数据包到达 Netfilter Hook → 按优先级执行注册在该 Hook 上的相应处理逻辑和规则链 → 在规则链里逐条匹配 Rule。Table 负责给 Chain 分类,并不是单独的“流量关卡”。
2.1 四个核心概念:Hook、Table、Chain、Rule
| 概念 | 解决什么问题 | 例子 |
|---|---|---|
| Hook(钩子/处理位置) | 数据包在什么时机被交给 Netfilter 处理? | PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING |
| Table(表) | 规则按功能放在哪一类? | raw、mangle、nat、filter、security |
| Chain(规则链) | 哪些规则按怎样的顺序逐条匹配? | filter 表的 INPUT 链、mangle 表的 INPUT 链 |
| Rule(规则) | 匹配什么条件、命中后执行什么动作? | 匹配 TCP 22,然后 ACCEPT |
在 iptables 语法里,用户通常通过“表名 + 链名 + 匹配条件 + 动作”配置防火墙。
例如,下列演示命令会立即更改防火墙,不要直接在生产服务器执行:
# 演示规则结构,不是完整安全策略
sudo iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT
命令解释:-t filter 指定表;-A INPUT 向 filter 表的 INPUT 链末尾追加规则;-p tcp --dport 22 限制匹配 TCP 目标端口 22;-j ACCEPT 表示接受当前匹配的数据包。这条链挂在内核的 INPUT Hook 对应处理位置,但是 INPUT Hook 和“filter/INPUT 这条链”不是一个概念。
特别注意:
- 一个 Hook 上可以运行多个表中的规则链,例如 INPUT 位置同时可能处理
mangle/INPUT、filter/INPUT、security/INPUT。 - 一张表可以含有多条内置链,例如
filter表含INPUT、FORWARD、OUTPUT。 - 同名链不代表同一条链:
filter/INPUT和mangle/INPUT是两条不同的链。 - 在原生 nftables 中,基础链还可以叫
ssh_guard等自定义名称,再通过hook input声明挂载的 Hook;因此尤其不能把 Hook 与 Chain 画成完全相同的对象。 RETURN可以让数据包从自定义链返回调用位置;ACCEPT、DROP、REJECT等动作也必须结合 Hook 和后续处理链理解,不能认为任意一个 ACCEPT 可以覆盖整条网络路径中的其他 DROP。
2.2 五个经典 IP Hook:先决定流量经过哪里
| Hook | 数据包何时到达? | 常见用途 |
|---|---|---|
| PREROUTING | 外部数据包进入主机,路由判断之前 | 早期处理、DNAT |
| INPUT | 路由判断确认包要交给本机进程 | 主机入站过滤 |
| FORWARD | 路由判断确认包要由本机转发给其他主机 | 网关转发过滤 |
| OUTPUT | 本机进程生成数据包时 | 本地发包过滤、本机 DNAT |
| POSTROUTING | 路由确认后,包离开主机之前 | SNAT、MASQUERADE |
先看这张数据包流转主图。它借鉴常见的 Linux 网络路径图,将五个经典 Hook、路由判断以及每个 Hook 中具有代表性的 iptables 表/链直接放到同一张图里,便于追踪流量实际经过的位置。
如何读这张图:请求从外部进入,先经过 PREROUTING,然后路由决定是走 INPUT(交给本机)还是 FORWARD(转发其他主机);本机主动发出的包走 OUTPUT,转发与本机出站的包通常都经过 POSTROUTING。图中 nat/PREROUTING、filter/INPUT 等是该 Hook 下的典型规则链示例,不代表此 Hook 只存在或只执行这一张表。
特别注意:本机 SSH 服务发出的响应属于另外一个反向数据包,不代表同一个入站报文在 INPUT 之后继续执行 OUTPUT。同时,从网关转发到后端的包走 FORWARD,通常不走网关的 INPUT。
范围:以上是常见 IP 数据路径的简化图,略去了路由的某些细节,以及网桥、隧道、容器网络、eBPF 等特殊处理。Netfilter 并非总共只有这五种 Hook;例如原生 nftables 的 netdev ingress/egress 就是另一个层面的处理位置,此处先聚焦经典 IP Hook。
2.3 五张表到底放在哪些 Hook 上?
五张常见的传统 iptables 表有不同职责:
| 表 | 主要负责什么? | 典型动作或用途 |
|---|---|---|
raw | 连接跟踪之前的早期处理 | 某些流量的 NOTRACK 配置等 |
mangle | 修改包字段、打标记等 | MARK、TTL/DSCP 等 |
nat | 网络地址、端口转换 | DNAT、SNAT、MASQUERADE |
filter | 常规包过滤(默认表) | ACCEPT、DROP、REJECT |
security | 额外的安全访问控制 | SELinux 等安全标记相关规则 |
表与 Hook 的关系是多对多,并不是一一对应。 传统 iptables 的常见内置链分布如下:
| 表 / Hook | PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING |
|---|---|---|---|---|---|
raw | ✓ | — | — | ✓ | — |
mangle | ✓ | ✓ | ✓ | ✓ | ✓ |
nat | ✓ | ✓* | — | ✓ | ✓ |
filter | — | ✓ | ✓ | ✓ | — |
security | — | ✓ | ✓ | ✓ | — |
矩阵说明:✓ 表示该表在对应 Hook 位置有典型内置链;✓* 表示 nat/INPUT 取决于内核与具体实现。这个矩阵描述的是传统 IP iptables 的表/链结构,并不意味着原生 nftables 只能创建这些链。
从这张矩阵可以立即得到几个结论:
- PREROUTING Hook 可能执行
raw/PREROUTING、mangle/PREROUTING、nat/PREROUTING,但没有传统filter/PREROUTING内置链。 - INPUT Hook 可以执行多张表下的 INPUT 链;
filter/INPUT只是其中一条,而不是 Hook 的全部。 - POSTROUTING Hook 通常涉及
mangle/POSTROUTING和nat/POSTROUTING;因此 SNAT 常放在nat/POSTROUTING。 - 连接跟踪 conntrack 不是第六张表,也不是 iptables 中某个叫 conntrack 的默认链;它是 Netfilter 的独立处理机制。
在理解了 Hook 路径与表/链矩阵后,可以再看下面的综合关系图:上半部分回顾三条路径,中间放大 PREROUTING 的处理优先级,底部再次核对五张表与五个 Hook 的对应位置。
2.4 同一个 Hook 内,规则链按什么顺序执行?
Hook 决定执行位置,注册优先级决定各个处理逻辑和规则链的先后顺序,Chain 内部再按规则顺序匹配。
以 PREROUTING 为例,典型 IPv4 包会经历如下几个重要阶段:
| 优先级 | 阶段 | 实际含义 |
|---|---|---|
| -300 | raw/PREROUTING | 早期规则,可配置部分流量不参与跟踪 |
| -200 | conntrack | 内核的连接跟踪处理,不是 table/chain |
| -150 | mangle/PREROUTING | 修改标记/某些包字段 |
| -100 | nat/PREROUTING | 典型 DNAT 处理位置 |
数字越小通常越早执行。上表省略了可能存在的分片重组、SELinux 内核 Hook 与其他额外注册逻辑,因此它不是内核执行步骤的穷举。
其他经典 Hook 的典型顺序(仅列出传统 iptables 相关阶段):
| Hook | 主要处理顺序 |
|---|---|
| INPUT | mangle → filter → security → nat/INPUT(支持时) |
| FORWARD | mangle → filter → security |
| OUTPUT | raw → conntrack → mangle → nat → filter → security |
| POSTROUTING | mangle → nat |
为什么并不是“所有数据包先经过 raw、再经过 mangle、最后经过 filter”? 因为不同 Hook 下对应的表/链不同。例如 PREROUTING 没有传统 filter 内置链;POSTROUTING 的典型 NAT 是 SNAT;INPUT 的访问控制一般放在 filter,而不在 PREROUTING 使用一个不存在的 filter/PREROUTING。
还需注意:
- NAT 规则通常用于建立连接的 NAT 映射,后续同一连接及反方向的包由 conntrack 延续已有映射。不能用 nat 表的规则命中数代表所有业务包数量。
- 一条链中 ACCEPT 并不等于整个数据路径无条件放行。同一包仍可能遇到其他 Hook、其他 nftables 基础链及上游的云安全组过滤。
- 在原生 nftables 中,Hook 和 Chain 的关系更加明确:基础链通过
type ... hook ... priority ...绑定;链名可以自行定义,相同 Hook 可以注册多个不同优先级的基础链。
参考:Netfilter 官方 Wiki:Netfilter hooks 与优先级 · nftables 官方手册。
2.5 三个常见场景:从 Hook 到具体规则链
场景 A:外部客户端连接本机 SSH
假设 Linux 自己监听 TCP 22:
- 请求从网络接口进入,先到 PREROUTING Hook:可能执行 raw、连接跟踪、mangle、nat 等相关阶段。
- 路由判断发现目标地址属于本机,于是进入 INPUT Hook。
- 在 INPUT 的相应处理阶段,进入 filter 表的 INPUT 链,检查匹配 TCP 22 的放行/拒绝规则。
- 规则允许后,报文才能继续交给
sshd;如果主机另有安全链、上游策略,也可能进一步限制。 sshd发出响应时,该响应是本机新产生的反向数据包,通过 OUTPUT、POSTROUTING 等处理路径发送。
结论:管理本机 SSH,重点检查 filter/INPUT;并不是所有流量都必须经过 FORWARD。
场景 B:网关将公网 8080 DNAT 到内网 80
- 请求从外网接口进入 PREROUTING Hook。
nat/PREROUTING的 DNAT 规则可能把目的地址从网关公网198.51.100.10:8080改成192.168.10.20:80。- 路由判断发现目的地址在另一台内网主机,请求进入 FORWARD Hook;通常在
filter/FORWARD决定是否允许转发。 - 从 POSTROUTING Hook 发往内网服务器;此时不意味着一定要 SNAT。
- 后端服务器的回复应沿原 NAT 网关返回,conntrack 才能自动执行相应反向 NAT,详见第 6.5~6.6 节。
结论:DNAT 转发重点看 nat/PREROUTING、filter/FORWARD、回程路由,而不是网关的 filter/INPUT。
场景 C:内网客户端经 Linux 网关共享上网
- 内网客户端的包进入网关 PREROUTING Hook。
- 路由判断目标在公网,进入 FORWARD Hook,检查是否允许 LAN → WAN 转发。
- 在 POSTROUTING Hook 的
nat/POSTROUTING中匹配SNAT或MASQUERADE,改写请求的源地址。 - 外部服务器把响应发回网关,conntrack 还原内网地址后,网关按路由把响应转发给原客户端。
结论:nat/POSTROUTING 负责常见出站源地址转换;filter/FORWARD 负责控制是否允许通过网关,两个职责不能混淆。
2.6 用命令验证:Hook、Table、Chain 实际是什么关系?
先检查当前实际后端和各张表中的内置链:
# 当前 iptables 使用 nft 兼容实现还是传统实现
iptables --version
# 分别查询 filter 和 mangle 表的 INPUT 链
sudo iptables -t filter -L INPUT -n -v
sudo iptables -t mangle -L INPUT -n -v
# 查看 PREROUTING 中常见的三张表
sudo iptables -t raw -L PREROUTING -n -v
sudo iptables -t mangle -L PREROUTING -n -v
sudo iptables -t nat -L PREROUTING -n -v
# 查看 POSTROUTING 的两张表
sudo iptables -t mangle -L POSTROUTING -n -v
sudo iptables -t nat -L POSTROUTING -n -v
# 如果系统采用 nftables,也单独查看真实的 nftables 规则集
sudo nft list ruleset
命令解释:iptables --version 用于区分 (nf_tables) 和 (legacy) 后端;-t 选择表,-L 选择查看哪条链(如 -t filter -L INPUT 表示 filter 表的 INPUT 链);-n 使用数字地址与端口,-v 显示规则计数、接口等详情;nft list ruleset 查看 nftables 中的基础链、规则及 Hook/priority 信息。这些均为只读命令,部分工具未安装时会提示找不到命令。
例如同时运行:
sudo iptables -t filter -S INPUT
sudo iptables -t mangle -S INPUT
命令解释:-S 以规则语法形式输出链的规则与策略,不修改内核规则。它们都选择了名为 INPUT 的链,但分别属于 filter 表和 mangle 表,恰好验证了“同名链不等于同一条链”。
如果在原生 nftables 中看到如下结构:
table inet example {
chain ssh_guard {
type filter hook input priority 0; policy accept;
tcp dport 22 accept
}
}
**代码解释:**这仅是 nftables 语法示意,不是要求写入系统的命令。表名是 example;链名为自定义的 ssh_guard;hook input 明确绑定 INPUT Hook,priority 0 决定该基础链的注册优先级;tcp dport 22 accept 是匹配规则。policy accept 允许未被拒绝的包通过此链,绝不意味着已经实现严格的 SSH 白名单。
这一章最终记住四点:① 数据包先经过 Netfilter Hook,而非“先到某张表”;② 同一 Hook 可以处理不同表中的多条链;③ 每条 Chain 存放顺序匹配的 Rule;④ 执行顺序取决于 Hook 与优先级,而不是“五张表全局串行”。
3. 安装、查看与修改规则
3.1 安装工具前确认发行版
cat /etc/os-release
uname -r
# Debian / Ubuntu:仅在确实需要 iptables 命令时
sudo apt update
sudo apt install -y iptables
# RHEL/Rocky:先看系统当前防火墙管理策略
rpm -q iptables-nft firewalld nftables
命令解释:/etc/os-release 标识发行版;uname -r 查询内核版本。apt update 更新软件包索引,apt install -y 安装 iptables 工具(会修改系统包)。rpm -q 只查询 RPM 包是否安装。两类发行版命令不是一组需要连续执行的脚本;RHEL 9 不建议仅为实现防火墙而弃用现有的 firewalld/nftables 管理方式。
3.2 最常用的只读查询
sudo iptables -L -n -v --line-numbers
sudo iptables -S
sudo iptables -t nat -L -n -v
sudo iptables-save
# IPv6 与 nftables 规则另行查询
sudo ip6tables -S
sudo nft list ruleset
命令解释:
| 命令/参数 | 说明 |
|---|---|
-L | 以人类可读的表格列出某张表的规则;省略 -t 时默认 filter |
-n | 不将 IP/端口反向解析为域名/服务名,输出更快,也减少误读 |
-v | 显示匹配包数、字节数、接口等详细信息 |
--line-numbers | 给链中规则显示临时行号,方便定位;插入/删除后行号可能改变 |
-S | 使用更接近可重建的命令格式打印规则与默认策略 |
-t nat | 将操作对象指定为 NAT 表,而不是默认 filter |
iptables-save | 将当前 IPv4 iptables 规则以可供 restore 使用的格式输出到标准输出;不自动持久化 |
ip6tables -S | 查看 IPv6 侧规则,不等同于 IPv4 规则 |
nft list ruleset | 查看 nftables 规则集;需要区分 iptables-nft 转换的规则与原生 nft 规则 |
这些是只读操作。同一条规则的计数器不增长,可能意味着报文没到达、走了其他 Hook/规则、原有 conntrack/NAT 映射已决定结果,或根本由其他防火墙层拦截。
3.3 增加、插入、检查、删除一条规则
下面用仅允许指定来源访问测试端口 2222演示语法。会修改当前运行时防火墙规则,只在已做好回滚的独立实验环境执行:
# 检查规则是否已存在(返回码 0 表示找到)
sudo iptables -C INPUT -p tcp -s 203.0.113.50/32 --dport 2222 -j ACCEPT
# 如果确认不存在且该策略合理,在 INPUT 链尾部追加
sudo iptables -A INPUT -p tcp -s 203.0.113.50/32 --dport 2222 -j ACCEPT
# 查看行号与匹配计数
sudo iptables -L INPUT -n -v --line-numbers
# 删除刚才那条完全匹配的规则(不依赖易变行号)
sudo iptables -D INPUT -p tcp -s 203.0.113.50/32 --dport 2222 -j ACCEPT
命令解释:-C 检查规则而不添加;-A 追加到链尾,若前方已经有 DROP 则可能永远匹配不到;-I INPUT 1 是插入链首(比末尾优先);-D 删除指定的完整规则或按当前行号删除。-p tcp 匹配 TCP,-s 限制源 IP,--dport 匹配目标端口,-j ACCEPT 指定匹配后的处理动作。
风险:增加/删除会即时生效,且 203.0.113.50 是文档保留地址,不是你现在的管理 IP;直接复制不会让真实来源连通。
3.4 修改默认策略、清空与替换规则
# 只读:先查看当前各内置链默认策略
sudo iptables -S INPUT
sudo iptables -S OUTPUT
sudo iptables -S FORWARD
# 以下命令非常危险,仅展示语义,不建议直接执行:
# sudo iptables -P INPUT DROP
# sudo iptables -F INPUT
# sudo iptables -X APP-INPUT
命令解释:-P INPUT DROP 把 filter 表 INPUT 内置链的默认策略设为丢弃,立即可能阻断所有未匹配放行规则的入站连接;-F INPUT 删除该链全部规则;-X APP-INPUT 删除一个已空且未被引用的自定义链,满足限制时才成功。它们不是安全重置流程,尤其不能在远程服务器先设 DROP 后慢慢放行 SSH。
4. 规则匹配与 conntrack 连接状态
4.1 常用匹配条件
| 参数 | 意义 | 示例 |
|---|---|---|
-s / --source | 来源 IPv4 地址/网段 | 192.168.10.0/24 |
-d / --destination | 目标地址 | 192.168.10.20 |
-i | 入接口 | enp1s0 |
-o | 出接口 | enp2s0 |
-p | 协议 | tcp、udp、icmp |
--sport / --dport | 源端口/目标端口 | --dport 443 |
-m | 启用匹配扩展 | conntrack、multiport、limit |
-j | 命中后动作/跳转目标 | ACCEPT、DROP、LOG、自定义链 |
--dport 一般需要匹配相应 TCP/UDP 协议,并由对应协议模块处理。-i 适用于入方向的 Hook,-o 用于出方向 Hook;接口名必须来自 ip -br link 的实际结果。
4.2 conntrack 的 NEW、ESTABLISHED、RELATED、INVALID
| 状态 | 含义与典型用途 |
|---|---|
NEW | 连接跟踪认为是新流,常用于允许新建连接的白名单 |
ESTABLISHED | 属于已经看到双向通信的已建立流 |
RELATED | 与已有流相关联的其他连接或错误报文 |
INVALID | 无法正常归类;需要结合抓包排查,而不是盲目丢弃所有场景 |
# 只读查看连接跟踪状态
sudo conntrack -L
# 仅输出已建立的 TCP 连接(主机应已安装 conntrack 工具)
sudo conntrack -L -p tcp --state ESTABLISHED
# 查看内核 conntrack 当前/最大容量
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
命令解释:conntrack -L 列出内核追踪的连接记录,不修改配置;-p tcp 限制协议,--state 筛选连接跟踪状态;sysctl 在这里不使用 -w,因此只查询参数。若工具未安装,可按发行版安装 conntrack 软件包。连接表耗尽可能使新流量受影响,应结合日志和内存容量判断,不要直接无限调高最大值。
4.3 使用连接状态匹配的规则示例
# 演示语法:允许已建立或相关连接的入站数据包
sudo iptables -I INPUT 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 示例:在确认整套规则和应用需求后,处理特定无效连接
# sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
命令解释:-m conntrack 启用连接跟踪匹配模块;--ctstate ESTABLISHED,RELATED 匹配指定状态;-I INPUT 1 插入第一条,避免先被更早的拒绝规则挡住。修改会立即影响流量,对 SSH/代理等长期连接要结合完整规则链和后端实现校验。INVALID 可能包含网络异常造成的意外数据包,是否丢弃需看业务实际需要。
5. INPUT / OUTPUT:控制主机端口和访问源
5.1 只允许一个管理地址访问 SSH
# 查询 SSH 实际监听端口及监听地址
sudo ss -lntp | grep sshd
ip -br addr
sudo iptables -S INPUT
# 下面是假设 SSH 在 22、管理客户端源地址已核实的示例
sudo iptables -I INPUT 1 -p tcp -s 203.0.113.50/32 --dport 22 \
-m conntrack --ctstate NEW -j ACCEPT
命令解释:ss -lntp 列出监听 TCP socket(-l 监听、-n 数字、-t TCP、-p 进程);ip -br addr 简洁查看本机接口 IP。iptables 命令表示只给指定来源的新 SSH TCP 连接放行,不自动关闭其他来源:要实现“只有这一台能连”,必须把更宽泛的允许规则和最终拒绝策略一并纳入安全设计。
必须注意:203.0.113.50 需替换为服务器实际观测到的客户端源地址。如果通过 VPN、跳板机、负载均衡或 NAT 登录,直接复制笔记本局域网 IP 可能错误;先从 ss 或管理日志确认来源,并保留控制台与自动回滚通道。
5.2 开放 HTTP/HTTPS、数据库白名单
# 仅示例:在已有安全回滚条件下新增这些放行规则
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 \
-m conntrack --ctstate NEW -j ACCEPT
# PostgreSQL 仅允许内网应用服务器 192.168.10.20 访问 TCP 5432
sudo iptables -A INPUT -p tcp -s 192.168.10.20/32 --dport 5432 \
-m conntrack --ctstate NEW -j ACCEPT
sudo iptables -L INPUT -n -v --line-numbers
命令解释:-m multiport --dports 80,443 匹配多个目标端口;数据库规则中的 -s 把来源限制为单台主机,而不是 0.0.0.0/0;-A INPUT 追加到链末尾,前方若存在宽泛的 ACCEPT/DROP,新的规则可能不具备预期限制作用。最后一条只读查看顺序和命中数。
数据库安全还依赖 PostgreSQL 的 listen_addresses、pg_hba.conf、TLS、账号权限与云平台安全组;iptables 只是其中一层,不能代替数据库认证。
5.3 保护 Loopback、理解 OUTPUT
# 示意:只在确实需要、且有回滚的测试规则集中配置
sudo iptables -I INPUT 1 -i lo -j ACCEPT
sudo iptables -I OUTPUT 1 -o lo -j ACCEPT
# 查询已有 OUTPUT 规则和内核路由
sudo iptables -L OUTPUT -n -v
ip route
命令解释:-i lo、-o lo 只匹配本机回环接口,避免本机服务互访受阻;OUTPUT 控制本机进程主动发出的数据包;ip route 只查询路由表。若 OUTPUT 默认策略为 DROP,DNS/NTP/HTTPS/镜像下载和数据库连接可能都需要单独考虑新建出站连接与返回流量。
5.4 DROP、REJECT、日志和 ICMP
# 示例:有控制台和回滚时,对测试来源地址记录有限速日志
sudo iptables -A INPUT -s 198.51.100.50/32 -m limit \
--limit 5/min --limit-burst 10 -j LOG --log-prefix "IPT-LAB: "
# 紧跟明确处理规则,否则 LOG 并不会自己丢弃数据包
sudo iptables -A INPUT -s 198.51.100.50/32 -j DROP
# 查询最近内核日志
sudo journalctl -k --no-pager -n 60
命令解释:-m limit 开启速率匹配;--limit 5/min 为持续令牌补充速率;--limit-burst 10 允许短时间的初始突发;-j LOG 写入内核日志,--log-prefix 帮助定位;-j DROP 才执行实际丢弃;journalctl -k 只读查询内核日志。
对 ICMP 不宜简单“一律禁用”:诊断、PMTU 发现等网络功能依赖某些 ICMP 报文,IPv6 对 ICMPv6 的依赖更明显。更合理的方案是按消息类型、来源和速率设计规则。
6. NAT:DNAT、SNAT、MASQUERADE 与端口转发
6.1 三种常用转换
- DNAT(Destination NAT):修改目标 IP/端口,例如公网
:8080转发到内网192.168.10.20:80;常见于nat/PREROUTING。 - SNAT(Source NAT):把出站源地址改为指定地址,适合固定公网出口。
- MASQUERADE:与 SNAT 类似,但会针对出接口的地址工作,常用于动态公网 IP;通常比固定地址 SNAT 有额外处理开销。
conntrack 会保存转换关系,使后续往返包按照一致的 NAT 映射处理,因此 nat 表的命中计数不应该简单当作每个业务包的总数。
6.2 DNAT:公网 8080 转到内网 80
网络假设:
公网客户端 203.0.113.50
│ TCP:8080
▼
Linux 网关 enp1s0 = 198.51.100.10
enp2s0 = 192.168.10.1
│
▼
后端 Web 192.168.10.20:80
默认网关需要能返回到 Linux 网关
前提:Linux 网关开启转发(下一章)、已有正确路由、后端监听 80、回程能走同一个网关、防火墙未被其他管理器覆盖。下面命令会立即修改防火墙和 NAT,仅供受控实验环境使用:
# 只匹配公网接口、指定公网地址和 8080 端口
sudo iptables -t nat -A PREROUTING -i enp1s0 -d 198.51.100.10 \
-p tcp --dport 8080 -j DNAT --to-destination 192.168.10.20:80
# DNAT 后目标已变成内网地址,需在 FORWARD 中允许新流量
sudo iptables -A FORWARD -i enp1s0 -o enp2s0 \
-p tcp -d 192.168.10.20 --dport 80 \
-m conntrack --ctstate NEW -j ACCEPT
# 放行符合方向的返回数据包,实际仍需评估已有规则与顺序
sudo iptables -A FORWARD -i enp2s0 -o enp1s0 \
-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
命令解释:
| 片段 | 作用 |
|---|---|
-t nat -A PREROUTING | 将 DNAT 规则追加到进入网关后的路由判断之前 |
-i enp1s0 -d 198.51.100.10 | 只匹配从 WAN 入口进入、原目的地址为该公网 IP 的包 |
--dport 8080 | 用户访问的原始服务端口 |
-j DNAT --to-destination 192.168.10.20:80 | 将目标改为内网 Web 主机 TCP 80 |
-A FORWARD ... --ctstate NEW -j ACCEPT | 允许经网关转发的新连接,匹配的是DNAT 后的目的地址和端口 |
--ctstate ESTABLISHED,RELATED | 允许有关联的返回流量 |
特别提醒:DNAT 不要求额外配置 SNAT。只要返回流量仍经过此网关,conntrack 会自动将回复的源地址/端口还原为客户端最初访问的公网地址/端口;详见第 6.5 节的逐包示例。
典型故障:如果后端 192.168.10.20 的返回流量不经过这台 Linux 网关,可能出现路由不对称,导致连接失败。不能只看 DNAT 命中数;必须检查后端默认网关/路由与实际抓包。公网入站转发与从网关本机访问公网 IP的情况不同,后者可能需要 nat/OUTPUT 专门处理,不能期望 PREROUTING 规则覆盖。
6.3 SNAT:指定固定源地址
# 在双网卡出口服务器上:将内网源地址转换为指定的公网接口地址
sudo iptables -t nat -A POSTROUTING -s 192.168.10.0/24 \
-o enp1s0 -j SNAT --to-source 198.51.100.10
# 查看当前 NAT 规则(只读)
sudo iptables -t nat -L POSTROUTING -n -v --line-numbers
命令解释:POSTROUTING 位于发出网卡之前;-s 匹配内网源地址段;-o 限定真正离开公网的接口;SNAT --to-source 指定新的源 IP。固定 SNAT 只适合服务器确实拥有/可使用这个出口地址的场景,否则返回流量无法正确到达。SNAT 与下一节 MASQUERADE 通常按场景二选一。 SNAT 也不要求配对写一条 DNAT:回复方向的目的地址会被 conntrack 自动恢复为原内网客户端地址,前提是返回流量经由同一网关,详见第 6.5 节。
6.4 MASQUERADE:动态出口的内网共享上网
# NAT:外出公网时采用当前 WAN 接口地址
sudo iptables -t nat -A POSTROUTING -s 192.168.10.0/24 \
-o enp1s0 -j MASQUERADE
# FILTER:内网主动访问外网的新连接
sudo iptables -A FORWARD -i enp2s0 -o enp1s0 \
-s 192.168.10.0/24 -m conntrack --ctstate NEW -j ACCEPT
# FILTER:允许外网返回的已建立/相关包
sudo iptables -A FORWARD -i enp1s0 -o enp2s0 \
-d 192.168.10.0/24 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
命令解释:MASQUERADE 对匹配流使用出口接口地址,适合拨号、动态 WAN 等环境;这不等于允许转发,FORWARD 规则还需要配合 net.ipv4.ip_forward、接口路由与内网客户端网关。若此前已添加同范围的 SNAT 规则,应先核对并消除冲突/重叠,不要机械地把 SNAT 与 MASQUERADE 都追加进去。
6.5 DNAT 与 SNAT 要同时配置吗?conntrack 的反向转换
答案:不需要成对配置。 常规 Linux 有状态 NAT 由 Netfilter 的 conntrack 记录连接的地址、端口及转换映射:一个连接的首包建立 NAT 映射,后续同一连接的包和反方向的响应会依据这份映射自动转换。所以:
- 只配置 DNAT:入站请求的目标改成内网服务器;只要响应流量返回同一网关,conntrack 就会自动把响应的源地址/端口还原为客户端最初访问的公网地址/端口;不需要再写一条手工 SNAT 来匹配返回包。
- 只配置 SNAT / MASQUERADE:内网客户端的请求源地址转换为网关地址;外部服务响应到网关后,conntrack 自动把响应的目标还原为内网客户端;不需要手工 DNAT 返回包。
- 同时配置两者:只有在业务明确需要改变请求的源和目标,或者必须强制返回流量绕过直连路径经原 NAT 网关时,才考虑双向组合(见下一节 Hairpin NAT)。
这里的“自动反向转换”不等于自动放行防火墙或自动配置路由:FORWARD 链、ip_forward、云安全组、回程路径、连接跟踪是否生效依然要分别检查。若流量没有回到原网关、属于另外一个独立连接,或被配置为不跟踪(NOTRACK),就不能假定会自动完成相同的转换。
情况 A:仅配置 DNAT 的公网端口转发
沿用第 6.2 节的公网客户端 203.0.113.50、网关 198.51.100.10:8080 和后端 192.168.10.20:80:
| 方向 / 阶段 | 源地址 | 目标地址 |
|---|---|---|
| 客户端请求原始包 | 203.0.113.50:53120 | 198.51.100.10:8080 |
| 网关 DNAT 后 | 203.0.113.50:53120 | 192.168.10.20:80 |
| 后端发出响应 | 192.168.10.20:80 | 203.0.113.50:53120 |
| 网关 conntrack 自动反向转换后 | 198.51.100.10:8080 | 203.0.113.50:53120 |
结论:不需要额外的 SNAT 规则;后端仍能看到真实的客户端源 IP 203.0.113.50。但是后端必须有通往客户端的返回路由,经由这台 NAT 网关:例如把它设为默认网关,或为客户端网络配置相应的路由。如果后端经另一台路由器直接响应,网关没有机会做反向 NAT,就会出现超时或连接异常。
情况 B:仅配置 SNAT 的内网共享上网
内网客户端 192.168.10.30:53120 通过网关 198.51.100.10 访问外部服务 203.0.113.80:443:
| 方向 / 阶段 | 源地址 | 目标地址 |
|---|---|---|
| 内网客户端请求原始包 | 192.168.10.30:53120 | 203.0.113.80:443 |
| 网关 SNAT 后 | 198.51.100.10:映射端口 | 203.0.113.80:443 |
| 外部服务发出响应 | 203.0.113.80:443 | 198.51.100.10:映射端口 |
| 网关 conntrack 自动反向转换后 | 203.0.113.80:443 | 192.168.10.30:53120 |
**结论:**不需要额外的 DNAT 规则;conntrack 根据已有连接记录还原响应目标。映射端口可能与原端口相同,也可能因端口冲突等原因被 NAT 改写,因此表格中特意不假定两者总相等。SNAT 只帮助内部主动发起的流量正常往返,不意味着外部新连接可以任意访问内网。
用什么命令确认地址转换与回程?
# 只读查看正在跟踪的 TCP 连接及地址映射
sudo conntrack -L -p tcp
# 只读查看 NAT、FORWARD 规则与计数
sudo iptables -t nat -L -n -v --line-numbers
sudo iptables -L FORWARD -n -v --line-numbers
# 只读查看目标主机路由选择(目标示例为客户端地址)
ip route get 203.0.113.50
命令解释:conntrack -L -p tcp 会列出 TCP 连接跟踪信息,可对照原始与回复方向的源/目标地址和端口,注意输出量可能很大;-t nat -L -n -v 查询 NAT 规则的命中计数,NAT 规则通常在建立映射时参与查找,因此计数不能当作应用层每个数据包都再次命中;-L FORWARD 查看转发过滤规则;ip route get 查询当前执行命令的这台机器到指定目标的路由。真正要验证后端回程,必须登录后端主机执行相应的 ip route get,或者在网关、后端两个方向抓包验证。全部为查询操作。
场景速查
| 场景 | 需要 DNAT? | 需要 SNAT? | 关键前提 |
|---|---|---|---|
| 公网端口转发到内网服务 | 是 | 通常不需要 | 后端的响应必须通过原 NAT 网关 |
| 内网客户端经网关访问公网 | 不需要 | 通常需要,或 MASQUERADE | 网关具备有效的公网出口和回程路由 |
| DNAT 后后端绕过网关直接回包 | 已配置 | 可考虑,但不一定是最佳方案 | 优先纠正路由,必要时做范围受限的 SNAT |
| 同网段客户端通过公网 IP 访问同网段服务 | 通常需要 | 常需要 | 典型 Hairpin NAT,同网段直回问题 |
| 两侧是独立路由网络且无需地址转换 | 不需要 | 不需要 | 双向路由与过滤规则正确即可 |
选型原则:优先保证对称的返回路径,不要因为设置了 DNAT 就默认附加 SNAT。 不必要的 SNAT 会让后端只能看到网关地址,影响真实客户端 IP 日志、审计、限流及基于来源 IP 的访问控制。
6.6 Hairpin NAT:什么时候 DNAT 和 SNAT 要配合?
Hairpin NAT(NAT 回流)的典型场景:客户端和服务器位于同一个内网网段,但客户端通过网关的公网地址访问服务器。
同一 LAN:192.168.10.0/24
客户端 192.168.10.30
│ 请求 198.51.100.10:8080(网关公网地址)
▼
网关 LAN:192.168.10.1 / enp2s0
网关 WAN:198.51.100.10
│ DNAT → 目标 192.168.10.20:80
│ SNAT → 来源 192.168.10.1
▼
服务器 192.168.10.20:80
│ 响应发给 192.168.10.1,经过原网关反向转换
▼
客户端看到响应来自 198.51.100.10:8080
如果只有 DNAT:服务器收到的源 IP 是同网段的 192.168.10.30,可能直接通过交换网络把响应发给客户端,绕开网关;客户端原本连的是公网 198.51.100.10:8080,却收到来自 192.168.10.20:80 的响应,四元组不匹配,连接通常无法建立。
受控实验环境中可以将规则限定到这个单一客户端、单一发布端口、单一内网服务器(实际规则顺序、FORWARD 权限、IP 转发与网关地址均须先核实):
# 1. 只匹配 LAN 客户端访问网关公网 8080 的请求,执行 DNAT
sudo iptables -t nat -A PREROUTING -i enp2s0 \
-s 192.168.10.30/32 -d 198.51.100.10 \
-p tcp --dport 8080 \
-j DNAT --to-destination 192.168.10.20:80
# 2. 仅匹配上述连接的原始目标,将来源变成网关 LAN IP
sudo iptables -t nat -A POSTROUTING -o enp2s0 \
-s 192.168.10.30/32 -d 192.168.10.20/32 \
-p tcp --dport 80 \
-m conntrack --ctorigdst 198.51.100.10 --ctorigdstport 8080 \
-j SNAT --to-source 192.168.10.1
# 3. 只读检查 NAT 规则顺序,验证后应再抓包观察回程
sudo iptables -t nat -L -n -v --line-numbers
命令解释与风险:
- 第 1 条:
PREROUTING中-i enp2s0只选入站 LAN 流量;-s只匹配客户端192.168.10.30;-d ... --dport 8080只选对网关公网 Web 端口的请求;DNAT把目的改成内网192.168.10.20:80。 - 第 2 条:在
POSTROUTING中再以-o enp2s0和后端地址限制出 LAN 的流量;-m conntrack --ctorigdst/--ctorigdstport精确约束到最初访问的公网目的地址与端口,避免把普通内网直连 Web 也统统 SNAT;SNAT --to-source 192.168.10.1改变来源,使服务器必须把回复发回网关。 - 第 3 条:只读显示规则顺序与计数。前两条会立即改变现有连接的 NAT 行为;对新流是否生效还受更早规则、conntrack 已缓存映射和 FORWARD 过滤影响。
**注意:**这是示例网段和文档地址,不能直接在生产复制。网关必须开启 net.ipv4.ip_forward,相关 LAN→LAN 转发规则必须允许,客户端的路由要使访问网关公网地址的包到达网关;后端需正常监听 80 且能回复 192.168.10.1。同接口的 LAN→LAN 流量同样可能经过 FORWARD。
Hairpin SNAT 的代价是:服务器看到的是网关的 LAN IP,不再是客户端真实 IP。如果业务需要保留客户端真实地址,可以优先考虑分域 DNS(split-horizon DNS):内网客户端直接解析到 192.168.10.20,省去回流 NAT,或通过受信代理将真实来源信息在应用层传递;不要在不受信任的请求头中盲信 X-Forwarded-For。
参考:Netfilter 官方 Wiki:有状态 NAT 与连接跟踪 · nftables 官方手册:NAT、反向转换与 MASQUERADE。
7. FORWARD、双网卡路由和网段隔离
7.1 开启 IPv4 转发之前检查内核配置
# 只读查询内核是否允许 IPv4 转发
sysctl net.ipv4.ip_forward
# 检查网络接口、地址和路由
ip -br addr
ip route
ip route get 1.1.1.1
# 查询反向路径过滤配置
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.enp1s0.rp_filter
命令解释:sysctl net.ipv4.ip_forward 输出 0 表示关闭路由转发、1 表示允许(但不保证 FORWARD 规则放行)。ip -br addr 查看网卡与 IP;ip route get 只预测到某目标的路由,不会发送真实包;rp_filter 可能拒绝源地址与反向路由不一致的流量,对多出口/不对称路由环境尤其需要核查。
测试环境确认拓扑后才考虑修改:
# 会立即修改运行时内核参数
sudo sysctl -w net.ipv4.ip_forward=1
# 回读验证;持久化需要经过配置评审
sysctl net.ipv4.ip_forward
命令解释:-w 会写入当前 sysctl 参数,影响经过本机的所有 IPv4 转发流量;重启后是否继续生效取决于 /etc/sysctl.d/ 等持久化配置。此举不配置任何路由、NAT 或安全策略,在公网服务器上贸然开启不应被当作无害操作。
7.2 仅允许 A 网段访问 B 网段的指定服务
网络假设:两个网段路由已经通过 Linux,A 为 192.168.10.0/24,B 的服务器为 192.168.20.30,只允许 A 访问 B 的 TCP 443。
# 针对明确的 A→B 服务访问(仅在已备份、可回滚的环境)
sudo iptables -A FORWARD -s 192.168.10.0/24 \
-d 192.168.20.30/32 -p tcp --dport 443 \
-m conntrack --ctstate NEW -j ACCEPT
# 为 B→A 的已建立连接提供返回方向放行
sudo iptables -A FORWARD -s 192.168.20.30/32 \
-d 192.168.10.0/24 -m conntrack \
--ctstate ESTABLISHED,RELATED -j ACCEPT
命令解释:-s 匹配发包网段/主机,-d 匹配真正的目的主机,--dport 443 限制新流量可访问的服务;第二条只放行有连接跟踪状态的返回流量。这两条只是在现有规则中“添加允许”,如有宽泛的其他 ACCEPT,仍可能允许不该访问的端口;要隔离必须审核整个 FORWARD 规则顺序和默认策略。
7.3 为何会出现单向可达?
可能原因包括:
- A 主机没有正确指向 Linux 网关的路由,或者 B 主机回复经其他网关返回。
FORWARD只允许 A→B 的 NEW,没有放行正确的返回方向。rp_filter、云平台反欺骗策略或其他安全组拦截。conntrack状态异常/满表,或规则命中早于预期。- 路由策略与 SNAT/DNAT 造成源/目的地址在不同节点看到的值不同。
排查顺序:先用 ip route get 验证正反路由,再在两侧接口 tcpdump,对照 iptables -nvL FORWARD 的计数器。不要先随机添加一条全局 ACCEPT 掩盖原因。
8. 规则持久化、备份恢复与安全回滚
8.1 为什么 SSH 管理特别危险?
iptables 的规则变化通常即时生效,但未必重启后保留。一个错误的 INPUT DROP、OUTPUT DROP 或全局 iptables-restore,可能立即切断 SSH;如果没有带外控制台或自动回滚,远程管理员无法再次登录修正。
推荐流程:
- 查看现状和所属管理器,保留两条独立管理会话及云厂商/虚拟化的控制台。
- 保存当前 IPv4 和 IPv6 规则、记录 nftables 与 firewalld 状态。
- 在测试环境生成完整的新规则文件并进行语法测试。
- 使用具备超时回滚的
iptables-apply或等效机制确认远程连接。 - 在新的 SSH 会话和业务探针验证后,才持久化,最后复核 IPv6 和开机加载。
8.2 备份当前规则
# 仅获取规则并将文件写到受控备份位置
sudo sh -c 'umask 077; iptables-save > /root/iptables-before.v4'
sudo sh -c 'umask 077; ip6tables-save > /root/ip6tables-before.v6'
# 只读查看文件是否存在及权限
sudo ls -l /root/iptables-before.v4 /root/ip6tables-before.v6
命令解释:iptables-save、ip6tables-save 输出当前兼容后端的 IPv4、IPv6 规则;sh -c 确保文件重定向 > 也在 root 权限下执行;umask 077 限制备份文件默认权限,避免泄露源地址等安全策略。备份本身不会修改运行规则,但会写本地文件。
8.3 语法测试与超时回滚
假设已人工审核并准备好完整的规则文件 /root/iptables-candidate.v4,且本机安装了 iptables-apply:
# 只解析候选规则,不提交到内核
sudo iptables-restore --test < /root/iptables-candidate.v4
# 更安全的远程试运行:60 秒内未确认则恢复旧规则
sudo iptables-apply -t 60 /root/iptables-candidate.v4
命令解释:iptables-restore --test 解析规则但不提交;这不是全局逻辑正确性校验,只能过滤某些语法/构造问题。iptables-apply -t 60 会实际应用新规则并等待交互确认,超时或无法确认则尝试恢复旧规则;这比直接 restore 更安全,但仍要求具备控制台和测试网络,不能保证所有复杂 nftables/firewalld/容器规则都被恢复。
iptables-apply 可能未安装,且该工具只管理它所处理的规则族/后端;IPv6 需要独立设计。不可把不完整的候选 *filter 文件当作全机器所有链和容器规则的安全替代。
8.4 恢复、持久化与发行版差异
# 危险:仅在确认规则兼容、控制台可访问时执行恢复
# sudo iptables-restore < /root/iptables-before.v4
# Debian / Ubuntu 如采用 iptables-persistent 管理
# sudo apt install iptables-persistent
# sudo netfilter-persistent save
# 查看实际是否存在管理服务
systemctl status netfilter-persistent
命令解释:iptables-restore 会根据输入修改当前规则集,默认可能刷新输入涉及的表,不能在 Docker/Kubernetes 上盲目执行;Debian 系可安装 iptables-persistent 并由 netfilter-persistent 管理保存/加载,但必须先决定谁是规则的唯一管理者。旧 CentOS 7 的 iptables-services、RHEL 9 的 firewalld/nftables、Docker 的自动规则并不是相同管理方式,不能跨系统照抄服务名和配置文件。
官方:iptables-apply 安全回滚手册 · iptables-restore 手册。
9. IPv6 与 nftables 兼容迁移
9.1 IPv4 安全不代表 IPv6 安全
# 查询主机实际 IPv6 地址、路由及规则
ip -6 addr
ip -6 route
sudo ip6tables -S
sudo ip6tables -L INPUT -n -v --line-numbers
命令解释:ip -6 只列 IPv6 网络配置;ip6tables 对应 IPv6 规则;-S 查看配置语法,-L -n -v 查看命中计数。所有为查询操作。如果服务器有公网 IPv6 地址,仅设置 IPv4 INPUT 不足以限制 IPv6 入站。IPv6 需要合理允许 Neighbor Discovery、PMTU 等必需 ICMPv6 类型,不能粗暴地全部丢弃。
9.2 nftables 与 iptables-nft 混合时的注意事项
# 确认当前 iptables 接口后端
iptables --version
# 查看 nftables 中实际存在的规则表与链
sudo nft list ruleset
# 转换一条 iptables 规则为 nft 语法(仅输出结果,不执行)
iptables-translate -A INPUT -p tcp --dport 443 -j ACCEPT
命令解释:iptables-translate 是规则语法转换助手,不会将规则安装到内核;复杂 extension 或特定语义未必能直接迁移,需要逐条核对。nft list ruleset 为只读查询。即使 iptables-nft 显示 ACCEPT,其他 nftables 基础链仍可能 DROP,所以不能仅看 iptables 的输出判断全路径是否放行。
9.3 迁移原则
不要一边让 firewalld 管理 nftables,一边用 iptables-restore 无差别覆盖已存在的容器链。合理迁移要先确认唯一规则所有者、备份整套规则、建立等效路由与安全策略、验证 IPv4/IPv6、验证 Docker/K8s,再停掉旧规则管理器。不建议在本篇里把“卸载 firewalld”写成部署 iptables 的必要步骤。
10. Docker、Kubernetes 与 iptables
10.1 Docker 映射端口为什么可能绕过 INPUT?
Linux Docker 使用 iptables 防火墙后端时,bridge 网络的端口发布会创建 NAT/过滤规则,将宿主机端口映射到容器地址;从外部访问已发布的端口通常会发生 DNAT,然后进入 FORWARD 路径。因此宿主机 INPUT 的某条拒绝规则未必能控制已经 DNAT 的容器流量。
版本提示:现代 Docker Engine 也提供 nftables 后端,且相应行为可能变化;下面的 DOCKER-USER 示例仅适用于 Docker 的 iptables 后端,不适用于新 nftables 后端直接照搬。
10.2 查看 Docker 自动生成的规则
# 只读:列出容器与暴露端口
docker ps --format 'table {{.Names}}\t{{.Ports}}'
# 只读:查询 Docker 管理的规则
sudo iptables -t nat -S
sudo iptables -L DOCKER-USER -n -v --line-numbers
sudo iptables -L FORWARD -n -v --line-numbers
命令解释:docker ps --format 显示容器名称与端口映射;-t nat -S 查询 NAT 表规则;DOCKER-USER 是 Docker iptables 后端预留供管理员定义转发过滤的链,通常在 Docker 的转发放行规则之前检查;FORWARD 显示实际转发规则和计数。这些都是查询操作,如果 DOCKER-USER 链不存在,不应无依据地直接创建同名链模拟 Docker 内部架构。
10.3 在 DOCKER-USER 限制容器服务来源
假设宿主机对外发布 198.51.100.10:8080,只有 203.0.113.50 可以访问。下面规则需要 实际 Docker iptables 后端、链存在、外网接口正确、已有回滚、已有连接处理策略明确,才可以在受控测试环境尝试:
# 限制“原始目的地为宿主机公网 8080”的新连接来源
sudo iptables -I DOCKER-USER 1 -i enp1s0 -p tcp \
! -s 203.0.113.50/32 \
-m conntrack --ctstate NEW \
--ctorigdst 198.51.100.10 --ctorigdstport 8080 -j DROP
# 查询计数器
sudo iptables -L DOCKER-USER -n -v --line-numbers
命令解释:! -s 表示来源不是允许的客户端;-m conntrack --ctorigdst/--ctorigdstport 匹配 NAT 发生之前连接的原始目标 IP/端口,这是因为 DOCKER-USER 执行时目的地址已经可能被 DNAT 为容器 IP/端口;--ctstate NEW 将限制应用于新连接,避免直接切断所有存量连接;-j DROP 拒绝不在允许名单内的匹配流量。查询命中数要配合真实外部新连接测试。
边界与风险:查原始目的地通常增加连接跟踪处理成本;Docker 可能有多个网桥/映射规则,应核对具体出/入接口和容器模式。本示例只解释一个特定发布端口,不负责为全部容器建立完整隔离策略。DOCKER-USER 只属于 iptables 后端;如果 Docker 已切换 nftables backend,官方文档明确说明没有同名链,需要采用 nftables 的对应 Hook 与优先级策略。
官方:Docker Packet Filtering and Firewalls · Docker nftables 后端。
10.4 Kubernetes kube-proxy 与 CNI
# 在有 kubectl 和适当权限的管理节点查看 kube-proxy 配置
kubectl -n kube-system get configmap kube-proxy -o yaml
# 查看主机上的转发实现痕迹:不保证所有 CNI 都有相同链名
sudo iptables -t nat -S | grep KUBE-
sudo nft list ruleset
命令解释:kubectl ... get configmap 读取配置对象,但不是所有集群都以这个名字存储 kube-proxy 配置,托管环境或 eBPF dataplane 可能完全不同;grep KUBE- 仅过滤常见规则名,不等于没有这些链就“网络未配置”;nft list ruleset 只读查看其他后端。
kube-proxy 在 Linux 上可能采用 iptables、IPVS 或 nftables 模式;不同 Kubernetes 版本对模式的推荐和支持状态会变化,部署前必须查与实际集群版本一致的官方文档。CNI 的 NetworkPolicy 实现也可能通过 iptables、nftables 或 eBPF,不能用宿主机的一条 ACCEPT 当作替代 Kubernetes NetworkPolicy。
官方:Kubernetes Service 虚拟 IP 与代理模式。
11. 故障排查:从报错反推在哪一层丢包
推荐分层顺序:① 目标服务监听 → ② 云安全组/上游设备 → ③ 入口接口抓包 → ④ 路由/NAT/conntrack → ⑤ INPUT 或 FORWARD 规则顺序与计数 → ⑥ 后端接收 → ⑦ 回程路由。
11.1 服务监听了,但访问超时
sudo ss -lntp
ip -br addr
ip route
# 先读过滤规则与计数
sudo iptables -L INPUT -n -v --line-numbers
sudo iptables -L FORWARD -n -v --line-numbers
# 从网卡抓取特定端口的实际报文;替换接口/端口
sudo tcpdump -ni enp1s0 'tcp port 443' -c 20
命令解释:ss -lntp 看监听端口是否绑定正确的地址(127.0.0.1 监听通常不能直接从远端访问);iptables -L 看规则顺序和计数器;tcpdump -ni 不做反向 DNS 解析并指定接口,-c 20 抓取至多 20 包后退出,不改变过滤规则,但会读取网络流量,可能包含敏感数据,应控制访问权限与分享范围。
判断方式:如果网卡根本抓不到 SYN,先查上游网络/安全组/客户端;抓到 SYN,但服务器不响应,再分析 filter/NAT/路由/本地服务;有 SYN-ACK 却客户端仍超时,重点查回程。
11.2 SSH 被锁在外面
如仍有可用终端或带外控制台:
# 只读查看管理端口和当前规则
sudo ss -lntp
sudo iptables -S INPUT
sudo ip6tables -S INPUT
# 检查已经准备的规则备份
sudo ls -l /root/iptables-before.v4
**命令解释:**先确认 sshd 端口、客户端源 IP 以及 IPv4/IPv6 规则。不要直接在远程会话输入 iptables -F 试图“先全放开”,它可能受默认 DROP、其他表和管理器控制而无效,且可能暴露业务端口。若已完全失联,优先用云控制台或预先设置的自动回滚恢复已知良好配置。
11.3 NAT 转发的计数在增长,后端仍不可达
sudo iptables -t nat -L PREROUTING -n -v --line-numbers
sudo iptables -L FORWARD -n -v --line-numbers
sysctl net.ipv4.ip_forward
# 在 LAN 侧看是否真正发向后端
sudo tcpdump -ni enp2s0 'host 192.168.10.20 and tcp port 80' -c 20
# 查询 conntrack 记录(可能很大)
sudo conntrack -L -p tcp
**命令解释:**第一条看 PREROUTING DNAT 规则是否匹配新连接;第二条看 FORWARD 放行顺序;sysctl 只读查询是否开启转发;tcpdump 观察 DNAT 后的实际目的地址和返回方向;conntrack -L 查询连接跟踪映射。排查必须沿正向和返回方向同时进行,不能只用一个 NAT 计数器证明服务已经互通。
11.4 ACCEPT 已写,为什么依然被拒绝?
常见原因:
-A加在链末尾,前方已匹配 DROP/REJECT,根本走不到。- 目标经过 DNAT 后,数据包实际走
FORWARD而不是INPUT。 - 只写了 IPv4,客户端实际走 IPv6。
- firewalld/nftables 其他基础链、Docker/K8s 或云安全组还在过滤。
- 对
ESTABLISHED的假设与 conntrack 状态不一致,连接表满或连接跟踪被显式排除。 - 规则的接口或源 IP 与实际看到的 NAT/代理源地址不一致。
sudo iptables -S
sudo iptables -t nat -S
sudo ip6tables -S
sudo nft list ruleset
sudo iptables -L INPUT -n -v --line-numbers
sudo iptables -L FORWARD -n -v --line-numbers
命令解释:这组查询用于确认哪些规则实际存在、属于哪张表和规则顺序;全部为只读。对已存在的链,iptables -Z 可将计数器归零,但它本身也改变运行状态,生产排查优先对比两次读取结果,而不是为方便观察就清零所有计数器。
11.5 重启后规则消失
sudo iptables -S
sudo ip6tables -S
systemctl is-enabled netfilter-persistent
systemctl is-active firewalld
sudo nft list ruleset
**命令解释:**确认 IPv4、IPv6 的当前运行时规则,再查看持久化服务和其他管理器是否启用。is-enabled 仅查询服务是否配置开机启动,is-active 查询当前状态;规则未自动加载不代表重启前备份已丢失。应按发行版确定持久化归属,而不是顺手启动第二套防火墙管理器。
11.6 连接跟踪耗尽与不对称路由
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
sudo dmesg -T | grep -i 'conntrack' | tail -n 30
ip route
ip rule
ip route get 192.168.10.20
**命令解释:**前两条只读查询当前条目和上限;dmesg -T 查看 conntrack 满表或丢包相关内核日志;ip rule 查询策略路由;ip route get 模拟本机到目标的路由决策。容量问题要结合内存、连接峰值、超时和异常应用重试排查,不建议用盲目提高 nf_conntrack_max 代替根因分析。
12. 四个综合实战场景与运维速查
下面把前述知识整合成场景,并明确哪些属于演示计划,哪些能在已备份、带外控制台可用的实验机上操作。
12.1 场景 A:配置公网 Linux Web 服务器
目标:只允许来自可信管理来源的 SSH,公开 HTTP/HTTPS,保留必要的 Loopback 与已建立连接;其他 IPv4 入站流量采用显式收敛策略。
建议的审核顺序:
- 确认
sshd实际端口、管理来源经过 NAT 后的 IP,以及服务器是否有 IPv6。 - 备份运行时规则;准备控制台与超时回滚,记录 Docker/firewalld 等规则所有者。
- 审核候选规则,至少包含 Loopback、
ESTABLISHED,RELATED、指定来源 SSH、HTTP/HTTPS、必要 ICMP。 - 先添加允许规则,验证新 SSH 会话;最后由超时回滚工具试运行默认拒绝。
- 重新测试公网 HTTP/HTTPS、SSH 与 IPv6,再保存到正确的规则持久化管理器。
以下只是规则语义片段,不是完整可在生产直接替换的配置文件:
# 在受控环境中预期保留的几条入站放行语义
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -s 203.0.113.50/32 -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# 不直接给出在 SSH 会话中执行的“设置默认 DROP”命令
# 请将完整方案制作为受审候选规则文件并用 iptables-apply 回滚测试
**命令解释:**第一条允许回环;第二条避免阻断已经建立的连接;第三条只允许实际替换后的管理源 SSH;第四条公开常见 Web 端口;-A 是链尾追加,若链前方已有 DROP,以上命令不保证生效。这些规则本身也不会禁止其他来源 SSH,必须与完整策略一起审核。切勿原样复制文档保留地址上线。
12.2 场景 B:仅允许应用服务器访问 PostgreSQL
目标:内网应用 192.168.10.20 可连接本机 PostgreSQL TCP 5432,其他未授权源被拒绝,但不影响 SSH 管理或备份。
# 首先验证数据库监听和现有入站规则
sudo ss -lntp | grep 5432
sudo iptables -L INPUT -n -v --line-numbers
# 在有回滚的测试环境插入应用来源白名单
sudo iptables -I INPUT 1 -s 192.168.10.20/32 \
-p tcp --dport 5432 -m conntrack --ctstate NEW -j ACCEPT
命令解释:前两条只读检查本机服务与规则;后一条允许特定源 IP 建立数据库 TCP 连接,会即时改变内核规则,但并不自动阻止其他来源。如果已有全网允许 5432 的规则,必须审计并调整;如果云安全组未开放应用来源,iptables 放行也无法绕过它。
验收:从应用主机连接数据库验证成功,其他测试主机应无法连接;同时核对 PostgreSQL 的 listen_addresses、pg_hba.conf、用户权限、TLS,以及服务器实际观察到的 NAT 来源。
12.3 场景 C:Linux 双网卡 NAT 网关
目标:内网 192.168.10.0/24 经网关 192.168.10.1 与 WAN 访问外网;公网 :8080 转发到内网 Web 192.168.10.20:80。
操作分为:
- 用
ip -br addr、ip route校验网卡与双向路由。 - 用
sysctl net.ipv4.ip_forward判断是否已经启用 IPv4 转发。 - 在受控实验机添加 LAN→WAN 新连接与 WAN→LAN 返回连接的 FORWARD 规则。
- 对动态 WAN 使用
MASQUERADE(固定 WAN 可以评估 SNAT,不能两者乱叠)。 - 按第 6.2 节设置
DNAT与相应转发白名单。 - 在公网客户端和后端分别抓包验证,确认返回流量经过正确网关。
# 只读验收:查看路由、转发和 NAT 命中
ip -br addr
ip route
sysctl net.ipv4.ip_forward
sudo iptables -L FORWARD -n -v --line-numbers
sudo iptables -t nat -L -n -v --line-numbers
命令解释:ip -br addr 显示接口 IP;ip route 显示路由;sysctl 回读转发开关;iptables -L 查看过滤/转换规则的命中数。这些都不会改动网络。若转发仍不成功,按第 11.3 节抓包确认正反方向,不要继续随机追加 NAT 规则。
12.4 场景 D:Docker 已发布端口但来源限制失效
目标:Docker 的 -p 8080:80 已发布到宿主机;主机 INPUT DROP 443/8080 似乎未限制容器访问。
# 检查 Docker 映射和当前转发链
docker ps --format 'table {{.Names}}\t{{.Ports}}'
sudo iptables -t nat -S
sudo iptables -L FORWARD -n -v --line-numbers
sudo iptables -L DOCKER-USER -n -v --line-numbers
# 如采用 nft 后端,再单独查看实际规则
sudo nft list ruleset
**命令解释:**第一条核对宿主机端口和容器目标端口;NAT 规则判断是否已发生 DNAT;FORWARD 规则判断是否按转发路径处理;DOCKER-USER 仅限传统 iptables 后端;nft list ruleset 用来避免忽略现代 nftables 后端。只查询不修改。
定位后再根据第 10.3 节在 Docker 的正确管理入口、正确 Hook 上部署最小白名单,不要清空 Docker 自动维护的链。如果部署 Docker Swarm 或 Kubernetes,还需分别检查 overlay、ingress 和 CNI 实际数据路径。
12.5 常用命令速查表
| 目标 | 命令 | 特别注意 |
|---|---|---|
| 查看后端 | iptables --version | 区分 nft / legacy |
| 查看 filter | iptables -L -n -v --line-numbers | 只读;看顺序和计数 |
| 查看原始语法 | iptables -S | 只读 |
| 查看 NAT | iptables -t nat -S | 只读 |
| 查看 IPv6 | ip6tables -S | 只读 |
| 查看 nftables | nft list ruleset | 只读 |
| 验证规则存在 | iptables -C ... | 只读检查/返回码 |
| 增加规则 | iptables -A ... | 立即修改 |
| 优先插入 | iptables -I ... | 立即修改,注意顺序 |
| 删除规则 | iptables -D ... | 立即修改 |
| 清空规则 | iptables -F | 高风险,可能失联或放宽访问 |
| 修改默认策略 | iptables -P ... | 高风险 |
| 保存备份 | iptables-save | 输出规则,需要自行保存文件 |
| 测试候选 | iptables-restore --test | 仅解析,不实际应用 |
| 安全试运行 | iptables-apply -t 60 <规则文件> | 实际修改并超时回滚,仍需控制台 |
| 抓包 | tcpdump -ni <接口> ... | 只读网络流量,但有敏感数据 |
| 查看路由 | ip route / ip rule | 只读 |
| 查看监听 | ss -lntp | 只读 |
| conntrack 表 | conntrack -L | 只读 |
12.6 生产变更检查清单
- 已确认 IPv4/IPv6、网卡、默认路由、SSH 端口与管理来源 IP。
- 已确认 firewalld/UFW/nftables/Docker/Kubernetes 哪个组件负责写入规则。
- 已备份现有规则,且具有带外控制台与独立自动回滚机制。
- 放行规则先于最终拒绝规则;新 SSH 会话已验证。
- NAT 的正向、反向路径都已抓包检查,FORWARD 与 ip_forward 状态正确。
- 没有未经评审的全网 0.0.0.0/0 数据库端口或容器端口暴露。
- 已用第二个独立客户端验证服务访问,而不仅仅是当前已建立连接。
- 确认 IPv6 安全、容器服务、DNS、备份、监控均没有受到新规则影响。
- 通过灰度、回滚与审查之后才持久化,记录操作者、时间、差异及恢复路径。
参考资料
- firewalld.conf:FirewallBackend 与 direct 规则例外
- Ubuntu:Firewall 与 UFW/iptables/nftables 的关系
- Ubuntu:nftables 与传统 UFW 实现说明
- xtables-nft(8):iptables-nft 兼容层
- iptables(8) 官方 man page
- iptables-apply(8):带超时回滚的远程规则试运行
- iptables-restore(8):测试与恢复规则
- Red Hat Enterprise Linux 9:Configuring firewalls and packet filters
- Docker Engine:Packet filtering and firewalls
- Docker Engine:Firewall with nftables
- Kubernetes:Virtual IPs and Service Proxies
- Netfilter conntrack-tools 项目
最后记住三句话:先判断报文走 INPUT 还是 FORWARD;NAT 与过滤规则必须配合正确的正反向路由;远程改规则先准备自动回滚,绝不能通过“直接清空”来碰运气。