Linux iptables 与 Netfilter:原理、路径与运维要点
本文从 Linux 内核 Netfilter 框架 出发,说明 iptables (用户态配置工具)与 表(tables)、链(chains)、钩子(hooks)的关系;用流程图与表格 归纳报文路径、常用命令与匹配动作;并说明 iptables-save / iptables-restore 的导出格式与备份恢复、tcpdump 抓包点与 iptables 的先后 、规则数量对转发路径的影响 及持久化思路。具体钩子名、模块名随内核版本可能略有差异,排障请以当前内核文档与发行版说明为准。
目录
- [Netfilter 与 iptables 各自做什么](#Netfilter 与 iptables 各自做什么)
- 五个钩子与四张表
- 表与内置链对应关系
- [IPv4 包处理路径(示意)](#IPv4 包处理路径(示意))
- 命令格式与常用子命令
- 匹配条件与常见扩展模块
- 目标动作(-j)简表
- [配置示例:本机防火墙与 NAT](#配置示例:本机防火墙与 NAT)
- [iptables-save 与 iptables-restore](#iptables-save 与 iptables-restore)
- 查看、计数、日志与持久化
- [tcpdump 与 iptables:谁先谁后](#tcpdump 与 iptables:谁先谁后)
- 规则数量、复杂度与性能
- [nftables 与迁移提示](#nftables 与迁移提示)
- 延伸阅读
- 免责声明
Netfilter 与 iptables 各自做什么
| 概念 | 说明 |
|---|---|
| Netfilter | 工作在内核网络栈中的框架 :在若干固定钩子上注册回调,实现过滤、NAT、mangle、连接跟踪等。 |
| iptables | 用户态工具,通过 netlink 等机制把规则写入内核;日常说的「配防火墙」多数是在改 Netfilter 规则集。 |
| nftables | 新一代配置接口与规则引擎;发行版逐步默认 nft 后端,但 iptables-nft 兼容命令仍常见,概念(链、表、钩子)可对照理解。 |
内核
用户态
配置规则
iptables / ip6tables
Netfilter 钩子与规则
协议栈 / 路由 / 转发
五个钩子与四张表
钩子(hook):报文在网络栈中到达某阶段时,依次执行挂在该点上的规则(分表、分优先级)。
| 钩子 | 大致时机 | 常见用途(举例) |
|---|---|---|
| PREROUTING | 路由判定之前 | DNAT、raw、mangle、连接跟踪相关 |
| INPUT | 判定为本机接收后 | 过滤进入本机的流量 |
| FORWARD | 判定为需转发时 | 网关/路由器上过滤穿越本机的流量 |
| OUTPUT | 本机进程产生的报文离开前 | 过滤本机发出的流量 |
| POSTROUTING | 报文离开网络设备之前 | SNAT、MASQUERADE、mangle |
表(table) :同一钩子上,不同表按约定顺序处理(下列为常见教学顺序;实现细节以内核为准)。
| 优先级(概念上从高到低) | 表名 | 主要用途 |
|---|---|---|
| 1 | raw | 连接跟踪前处理;可标记 NOTRACK 等 |
| 2 | mangle | 改 TTL、TOS、打 MARK 等 |
| 3 | nat | 地址转换:SNAT/DNAT/MASQUERADE |
| 4 | filter | 允许/丢弃/拒绝(最常用) |
表与内置链对应关系
并非每张表都挂接全部钩子。下面为 IPv4 / 经典 iptables 教学用归纳:
| 表 | 常见挂接的链 |
|---|---|
| filter | INPUT、FORWARD、OUTPUT |
| nat | PREROUTING、INPUT、OUTPUT、POSTROUTING |
| mangle | PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING |
| raw | PREROUTING、OUTPUT |
链(chain) :命名规则列表;内置链 与上表钩子对应,也可自建链并用 -j custom_chain 跳转,便于模块化。
IPv4 包处理路径(示意)
下列 ASCII 流程 与 Mermaid 一致,强调「先 PREROUTING → 路由分叉 → INPUT / FORWARD / OUTPUT」。
text
┌── PREROUTING(raw → mangle → nat)
↓
┌─────────────┐
入网 │ 路由决策 │
└─────────────┘
↓
┌───────────┼───────────┐
↓ ↓ ↓
本机接收 转发 (本机发出时从 OUTPUT 进入)
↓ ↓
INPUT FORWARD
↓ ↓
本地协议栈 POSTROUTING(mangle → nat)
↑ ↓
OUTPUT ───────┘(经 POSTROUTING 后出网卡)
本机
转发
本机发出
报文进入协议栈
PREROUTING
raw → mangle → nat
路由:本机 / 转发 / 本地发出
INPUT
mangle → filter
FORWARD
mangle → filter
OUTPUT
mangle → nat → filter
本机进程
POSTROUTING
mangle → nat
POSTROUTING
mangle → nat
出网卡
读图要点 :NAT 多在 PREROUTING(DNAT)与 POSTROUTING(SNAT) ;filter 默认只管 INPUT/FORWARD/OUTPUT,不在 PREROUTING 上挂 filter(教学模型下)。
命令格式与常用子命令
一般形式:
text
iptables [-t 表名] 子命令 [链名] [匹配条件] [-j 目标 [目标选项]]
不加 -t 时默认 filter 表。
| 子命令 | 含义 |
|---|---|
-A |
在链末尾追加规则 |
-I [链] [序号] |
在指定位置插入(默认插到第一条) |
-D |
按规则内容或序号删除 |
-R |
替换某条规则 |
-L |
列出规则(大规则集时可能较慢) |
-S |
打印规则为 shell 可重放形式 |
-F |
清空某链或全表链 |
-P |
设置链的默认策略(如 DROP) |
-N / -X |
新建 / 删除自定义链 |
-Z |
将计数器清零 |
-v / -n |
详细 / 数字形式(不做 DNS 反查) |
推荐习惯 :生产环境列规则时多用 iptables -S 或 iptables-save 做脚本化备份;需要包/字节计数时用 -L -v -n。
匹配条件与常见扩展模块
| 条件 | 含义 | 示例 |
|---|---|---|
-p |
协议 | -p tcp、udp、icmp |
-s / -d |
源 / 目的地址 | -s 192.168.0.0/16 |
-i / -o |
入 / 出接口 | -i eth0 |
--sport / --dport |
端口或范围 | --dport 22、80:443 |
-m conntrack (或老 state) |
连接状态 | -m conntrack --ctstate ESTABLISHED,RELATED |
-m multiport |
多端口 | -m multiport --dports 22,80,443 |
-m iprange |
IP 范围 | --src-range 10.0.0.1-10.0.0.50 |
-m limit |
限速 | -m limit --limit 10/minute |
-m comment |
规则注释 | --comment "allow ssh from vpn" |
状态防火墙 常用写法:先放行 已建立连接 ,再开放少量端口,最后默认 DROP(见下节示例)。
目标动作(-j)简表
| 目标 | 行为简述 |
|---|---|
| ACCEPT | 放行(在当前链上结束本条规则处理,按路径继续) |
| DROP | 丢弃(对端通常无显式反馈) |
| REJECT | 拒绝并常伴随 ICMP 等错误返回(依协议与模块) |
| LOG | 记日志后继续匹配下一条(注意日志风暴) |
| SNAT / MASQUERADE | 改源地址(多在 POSTROUTING) |
| DNAT | 改目的地址(多在 PREROUTING) |
| RETURN | 从自定义链返回调用处 |
配置示例:本机防火墙与 NAT
1. 较严格的本机入站(示意)
bash
# 默认先拒绝(SSH 会话请先确认有控制台或带外)
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
# 再按需开放业务端口
2. 内网通过网关访问外网(SNAT / MASQUERADE)
bash
# 需 sysctl 打开 ip_forward,此处从略
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
3. 端口转发(DNAT 示意)
bash
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 192.168.1.10:22
以上命令需在测试环境验证;远程服务器 上改
-P INPUT DROP前务必保留 SSH 放行规则,避免被锁在外面。
iptables-save 与 iptables-restore
iptables-save 把当前内核中的 IPv4 规则 按固定文本格式 打印到标准输出;iptables-restore 从标准输入读入同一格式 ,一次性写回内核。二者成对使用,是备份、迁移、开机加载、脚本下发 的常用手段(ip6tables-save / ip6tables-restore 对应 IPv6)。
输出里有什么
典型片段包含:
*filter/*nat/*mangle/*raw:表头,表示后续规则属于哪张表。:CHAIN POLICY [计数]:内置链的默认策略 (如ACCEPT、DROP)及可选计数。-A CHAIN ...:与iptables -S类似的追加规则 行,可被iptables-restore解析执行。COMMIT:每个表结束时提交(格式要求的一部分)。
常用选项(以 man 页为准)
| 命令 | 选项 | 含义 |
|---|---|---|
iptables-save |
-t table |
只导出指定表(如 nat);不写则常见实现为导出全部相关表。 |
-c |
在输出中带上各链、各规则的包计数与字节计数 (与 iptables -L -v 一致方向,便于审计与对比)。 |
|
iptables-restore |
-t table |
只恢复指定表,避免误改其他表。 |
-n / --noflush |
不先清空 该表再导入(是否可用及语义以当前版本 man 为准;误用可能导致规则叠加而非「整表替换」)。 | |
-c |
与带 -c 的 save 文件配合,恢复计数器。 |
与 iptables -S 的对比
| 工具 | 特点 |
|---|---|
iptables-save |
整表快照 :含表头、默认策略、多表一次导出;适合 iptables-restore 与落盘配置文件。 |
iptables -S |
逐条规则 ,无 *filter 表壳;适合 grep、拼 shell、人工阅读单链。 |
典型用法示例
整库备份与恢复(替换式,慎用前先备份):
bash
iptables-save > /root/iptables.backup.v4
# 确认文件内容无误后
iptables-restore < /root/iptables.backup.v4
只导出 / 只恢复 NAT 表:
bash
iptables-save -t nat > /root/nat.only
iptables-restore -t nat < /root/nat.only
带计数备份(便于对比流量是否命中某条规则):
bash
iptables-save -c > /root/iptables.with-counters.v4
# 恢复时若需写回计数:
iptables-restore -c < /root/iptables.with-counters.v4
脚本里快速统计规则条数 (不解析人类可读列,通常比大规则集下反复 iptables -L 更省事):
bash
iptables-save | grep -c '^-A'
注意 :iptables-restore 从 stdin 读入的是「完整表描述」 ,错误文件可能导致策略与预期不符;生产环境建议先 save 再改 ,并保留串口/带外 或定时回滚 手段。发行版自带的 netfilter-persistent 等往往内部也是 save/restore 风格落盘,路径因发行版而异。
查看、计数、日志与持久化
| 需求 | 做法 |
|---|---|
| 看计数 | iptables -L INPUT -n -v;或 iptables-save -c 落盘后对比 |
| 看行号便于删改 | iptables -L INPUT --line-numbers |
| 整表备份 / 下发 | 见上一节 iptables-save / iptables-restore |
| 临时打日志 | iptables -A INPUT -j LOG --log-prefix "ipt-in: "(慎用,量大影响性能) |
| 开机持久化 | Debian/Ubuntu :常将 iptables-save 输出 写入 /etc/iptables/rules.v4 并由 iptables-persistent 加载;RHEL 系 常见 /etc/sysconfig/iptables 或服务封装 |
仅统计规则条数:
bash
iptables-save | grep -c '^-A'
tcpdump 与 iptables:谁先谁后
这与收包 / 发包方向 有关:教学上常记 入站 时 tcpdump 常在 PREROUTING 之前 就能看到帧;出站 时若包在 OUTPUT 被 DROP ,则 tcpdump 可能看不到(因未走到驱动发送路径上的抓包点)。
本机应用 Netfilter PREROUTING/INPUT tcpdump 抓包点 网卡/驱动 本机应用 Netfilter PREROUTING/INPUT tcpdump 抓包点 网卡/驱动 入站(简化) 帧进入 再进入协议栈与 iptables 若 ACCEPT 则交付本机
| 方向 | 常见结论(调试时) |
|---|---|
| 入站 | 常能在 iptables DROP 之后仍于 tcpdump 看到包(抓包点更靠前) |
| 出站 | OUTPUT 上 DROP 可能导致 tcpdump 看不到该包 |
| 排障 | 入站问题:tcpdump + iptables 计数 ;出站问题:iptables LOG 、TRACE (慎用)与 tcpdump 对照 |
规则数量、复杂度与性能
Netfilter 对每条报文常做顺序匹配 直到命中 -j ;规则多、匹配复杂(如大量 string 匹配、滥用 LOG )会拉长软中断路径 上的时间,表现为延迟或 CPU 占用上升。Docker / Kubernetes 也会自动插入大量规则,属常见「条数很多」来源。
| 因素 | 建议 |
|---|---|
| 条数多 | 把命中率高 的规则放前面;大量 IP 用 ipset 合并 |
| 重复端口 | 用 multiport 减少规则条数 |
| 列表很慢 | 规则上千时 iptables-save 往往比 iptables -L 更适合脚本统计 |
| 评估 | 以 业务延迟、吞吐、CPU softirq 实测为准;下表仅为量级感,非保证 |
| 规则量级(经验谈) | 可能现象(依流量与匹配复杂度而异) |
|---|---|
| < 几百 | 一般场景下影响常不明显 |
| 数百~一千多 | 可开始关注顺序与 LOG;容器环境常见 |
| 更多 | 建议审计规则来源、ipset 、评估 nftables 与架构(是否应旁路或卸载) |
nftables 与迁移提示
| 项目 | 说明 |
|---|---|
| 动机 | 更统一的规则表示、内核侧实现演进;部分发行版默认 nft 后端 |
| 兼容 | 可使用 iptables-translate 做单条规则对照学习 |
| 建议 | 新项目可优先读发行版文档选择 nft 或 iptables-nft ;存量脚本仍以 iptables-save / iptables-restore 管理为主时注意发行版迁移公告 |
延伸阅读
同仓库内与网络栈、套接字状态相关的笔记可对照阅读,例如 hnjzsdx_doc/计算机网络/TCP与UDP数据路径_用户态网卡与对端应用.md 、hnjzsdx_doc/操作系统/Linux_ss命令详解与Netlink原理.md(连接与队列观察)。
免责声明
不同内核版本、发行版默认后端(legacy iptables / nft)与模块集合均有差异;NAT、转发 还涉及 ip_forward、rp_filter、策略路由 等全局设置。生产变更前请在测试环境验证,并保留恢复路径。
主题:Linux、Netfilter、iptables、NAT、防火墙、抓包、性能。