强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

iptables 完全指南 / 第 02 章:核心概念——四表五链

第 02 章:核心概念——四表五链

本章目标:彻底理解 iptables 的四表(raw、mangle、nat、filter)五链(PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING)架构,掌握规则的匹配逻辑和数据包的完整处理流程。


2.1 四表(Tables)

iptables 的"表"是具有相同功能目标的规则集合。四张表按固定的优先级顺序排列:

2.1.1 表的优先级顺序

raw → mangle → nat → filter
  1      2       3      4
(高优先级 ──────────→ 低优先级)
表名 优先级 用途 内核模块
raw 1(最高) 连接跟踪之前处理,用于标记不需要跟踪的包 iptable_raw
mangle 2 修改数据包头部(TOS、TTL、MARK 等) iptable_mangle
nat 3 网络地址转换(SNAT、DNAT、MASQUERADE) iptable_nat
filter 4(最低) 包过滤(允许/拒绝),这是默认表 iptable_filter

2.1.2 各表的详细说明

raw 表

raw 表是优先级最高的表,它在连接跟踪(conntrack)之前处理数据包。主要用途是标记不需要进行连接跟踪的数据包,从而提升性能。

数据包进入
    │
    ▼
┌──────────┐
│ raw 表    │ ← 在这里决定是否跳过连接跟踪
└────┬─────┘
     │
     ▼
┌──────────────┐
│ 连接跟踪      │ ← nf_conntrack 处理
└────┬─────────┘
     │
     ▼
┌──────────────┐
│ mangle → nat  │ ← 后续的表处理
│ → filter      │
└──────────────┘

mangle 表

mangle 表用于修改数据包的元数据,而不是做过滤或 NAT:

操作 说明 典型用途
TOS 修改服务类型字段 QoS 流量分类
TTL 修改生存时间 隐藏网络拓扑
MARK 设置标记值 策略路由、tc 流量控制
SECMARK 安全上下文标记 SELinux 网络策略
CONNSECMARK 连接安全标记 SELinux 连接跟踪

nat 表

nat 表负责网络地址转换,它只处理每个连接的第一个数据包,后续包会自动按照连接跟踪的记录进行转换:

操作 方向 说明
SNAT POSTROUTING 出站 源地址转换(内网→公网)
DNAT PREROUTING 入站 目的地址转换(公网→内网)
MASQUERADE POSTROUTING 出站 动态 SNAT(适用于拨号网络)
REDIRECT PREROUTING/OUTPUT 本地 端口重定向到本机

filter 表

filter 表是默认表,用于决定数据包是否被放行:

用途
INPUT 过滤发往本机的数据包
OUTPUT 过滤本机发出的数据包
FORWARD 过滤经过本机转发的数据包

2.2 五链(Chains)

2.2.1 链的定义

“链"是规则的有序集合。数据包经过某个钩子点时,会遍历该钩子点上所有链中的规则,直到某个规则明确接受(ACCEPT)、丢弃(DROP)或拒绝(REJECT)该包。

2.2.2 五条内置链

链名 对应钩子 触发条件 涉及的表
PREROUTING PRE_ROUTING 数据包进入本机之前 raw、mangle、nat
INPUT LOCAL_IN 数据包目的是本机进程 mangle、filter
FORWARD FORWARD 数据包经过本机转发 mangle、filter
OUTPUT LOCAL_OUT 本机进程发出的数据包 raw、mangle、nat、filter
POSTROUTING POST_ROUTING 数据包离开本机之后 mangle、nat

2.2.3 表与链的对应关系(矩阵)

这是 iptables 最重要的知识矩阵:

表 \ 链 PREROUTING INPUT FORWARD OUTPUT POSTROUTING
raw
mangle
nat
filter

记忆技巧

  • raw 表只有两个链:入口(PREROUTING)和出口(OUTPUT)
  • mangle 表五个链都有
  • nat 表在路由决策前后都有(PREROUTING 做 DNAT,POSTROUTING 做 SNAT)
  • filter 表只在本地处理(INPUT、OUTPUT)和转发(FORWARD)

2.3 规则(Rules)

2.3.1 规则的结构

一条 iptables 规则由两部分组成:

iptables [选项] -匹配条件 -j 动作
                 ─────────  ──────
                   匹配(Match)  目标(Target)

完整结构

iptables -t 表名 -A 链名 \
  -p 协议 \
  -s 源地址 \
  -d 目的地址 \
  --sport 源端口 \
  --dport 目的端口 \
  -i 入接口 \
  -o 出接口 \
  -j 目标动作

2.3.2 规则示例解析

iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 22 -j ACCEPT
组成部分 说明
filter(默认) 未指定 -t,使用默认的 filter 表
INPUT 处理发往本机的数据包
操作 -A 追加到链末尾
协议 -p tcp 匹配 TCP 协议
源地址 -s 192.168.1.0/24 来自 192.168.1.0/24 网段
目的端口 --dport 22 目的端口是 22(SSH)
动作 -j ACCEPT 接受该数据包

语义:允许来自 192.168.1.0/24 网段的 SSH 连接请求。


2.4 匹配(Matches)

2.4.1 隐式匹配

隐式匹配是基于协议的内置匹配,不需要额外的 -m 参数:

参数 说明 示例
-p tcp 匹配 TCP 协议 -p tcp --dport 80
-p udp 匹配 UDP 协议 -p udp --dport 53
-p icmp 匹配 ICMP 协议 -p icmp --icmp-type echo-request
# 隐式匹配:--dport 依赖 -p tcp
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# ❌ 错误:没有指定协议就使用端口匹配
iptables -A INPUT --dport 80 -j ACCEPT   # 报错!

2.4.2 显式匹配

显式匹配需要使用 -m 参数加载扩展模块:

模块 说明 示例
-m conntrack 连接跟踪状态 -m conntrack --ctstate ESTABLISHED
-m multiport 多端口匹配 -m multiport --dports 80,443
-m iprange IP 范围 -m iprange --src-range 192.168.1.1-192.168.1.100
-m limit 速率限制 -m limit --limit 10/s
-m string 字符串匹配 -m string --string "malware" --algo bm
-m time 时间匹配 -m time --timestart 08:00 --timestop 18:00
-m owner 进程/用户匹配 -m owner --uid-owner 1000
-m comment 添加注释 -m comment --comment "Allow SSH"
# 显式匹配:加载 conntrack 模块
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 多端口匹配
iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j ACCEPT

# 带注释的规则
iptables -A INPUT -p tcp --dport 22 -m comment --comment "Allow SSH access" -j ACCEPT

2.5 动作(Targets)

2.5.1 基本动作

动作 说明 能否继续匹配
ACCEPT 接受数据包
DROP 静默丢弃数据包
REJECT 拒绝并返回错误消息
RETURN 返回到调用链继续匹配
QUEUE 传递给用户态程序处理 取决于程序

2.5.2 DROP vs REJECT

对比维度 DROP REJECT
行为 静默丢弃,不回复 发送 ICMP/TCP RST 回复
安全性 更高(不暴露防火墙存在) 较低(暴露主机存在)
调试 困难(对端超时) 方便(对端立即收到拒绝)
性能 更好 需构造回复包
适用场景 生产环境外部接口 开发/测试环境、内部网络
对端体验 连接超时 “Connection refused”
# DROP:外部流量静默丢弃
iptables -A INPUT -s 0.0.0.0/0 -j DROP

# REJECT:内部测试环境,方便调试
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 3306 -j REJECT --reject-with tcp-reset

2.5.3 自定义链

自定义链用于规则分组,提高可读性和管理效率:

# 创建自定义链
iptables -N SSH_RULES

# 在自定义链中添加规则
iptables -A SSH_RULES -s 192.168.1.0/24 -j ACCEPT
iptables -A SSH_RULES -s 10.0.0.0/8 -j ACCEPT
iptables -A SSH_RULES -j DROP

# 在主链中调用自定义链
iptables -A INPUT -p tcp --dport 22 -j SSH_RULES
INPUT 链规则遍历:
┌─────────────────────────────────────────────┐
│ 1. -m conntrack --ctstate ESTABLISHED -j ACCEPT │
│ 2. -p tcp --dport 22 -j SSH_RULES               │──→ SSH_RULES 链
│ 3. -p tcp --dport 80 -j ACCEPT                      │   ├── 192.168.1.0/24 → ACCEPT
│ 4. -j DROP                                          │   ├── 10.0.0.0/8 → ACCEPT
│                                                     │   └── 默认 → DROP
└─────────────────────────────────────────────┘

2.6 数据包完整流向

2.6.1 入站数据包(到本机)

网卡接收 → PREROUTING → 路由决策 → INPUT → 本机进程
              │                      │
              ▼                      ▼
         raw 表处理              filter 表处理
         mangle 表处理           mangle 表处理
         nat 表(DNAT)

处理顺序(按表优先级):

  1. raw PREROUTING
  2. mangle PREROUTING
  3. nat PREROUTING(DNAT)
  4. 路由决策:目的是本机 → INPUT
  5. mangle INPUT
  6. filter INPUT

2.6.2 转发数据包

网卡接收 → PREROUTING → 路由决策 → FORWARD → POSTROUTING → 网卡发出
              │                      │            │
              ▼                      ▼            ▼
         raw 表处理              filter 表处理  nat 表(SNAT)
         mangle 表处理           mangle 表处理  mangle 表处理
         nat 表(DNAT)

处理顺序

  1. raw PREROUTING
  2. mangle PREROUTING
  3. nat PREROUTING(DNAT)
  4. 路由决策:需要转发 → FORWARD
  5. mangle FORWARD
  6. filter FORWARD
  7. mangle POSTROUTING
  8. nat POSTROUTING(SNAT/MASQUERADE)

2.6.3 出站数据包(从本机发出)

本机进程 → OUTPUT → 路由决策 → POSTROUTING → 网卡发出
              │                      │
              ▼                      ▼
         raw 表处理              nat 表(SNAT)
         mangle 表处理           mangle 表处理
         nat 表(DNAT)
         filter 表处理

处理顺序

  1. raw OUTPUT
  2. mangle OUTPUT
  3. nat OUTPUT(DNAT)
  4. filter OUTPUT
  5. 路由决策
  6. mangle POSTROUTING
  7. nat POSTROUTING(SNAT/MASQUERADE)

2.7 规则匹配的遍历逻辑

数据包到达某条链
        │
        ▼
┌──────────────────┐
│ 取出第一条规则     │
└───────┬──────────┘
        │
        ▼
┌──────────────────┐    是    ┌────────────┐
│ 规则匹配?        │────────→│ 执行动作     │
└───────┬──────────┘         └──────┬─────┘
        │ 否                        │
        ▼                           ▼
┌──────────────────┐         ┌──────────────┐
│ 有下一条规则?    │         │ ACCEPT/DROP? │
└───────┬──────────┘         │ → 结束遍历    │
        │ 是                 │ RETURN?      │
        ▼                    │ → 返回调用链   │
  取出下一条规则              │ 其他?        │
                             │ → 继续遍历    │
                             └──────────────┘
        │ 否
        ▼
┌──────────────────┐
│ 执行默认策略      │
│ (Policy)         │
└──────────────────┘

重要:当所有规则都不匹配时,执行链的默认策略(Policy)。默认策略只能设置为 ACCEPTDROP,不能设置为 REJECT


2.8 实验:理解规则执行顺序

实验 1:观察表的优先级

# 在 raw 表的 PREROUTING 链添加日志
sudo iptables -t raw -A PREROUTING -p icmp -j LOG --log-prefix "RAW-PREROUTING: "

# 在 mangle 表的 PREROUTING 链添加日志
sudo iptables -t mangle -A PREROUTING -p icmp -j LOG --log-prefix "MANGLE-PREROUTING: "

# 在 nat 表的 PREROUTING 链添加日志
sudo iptables -t nat -A PREROUTING -p icmp -j LOG --log-prefix "NAT-PREROUTING: "

# 在 filter 表的 INPUT 链添加日志
sudo iptables -A INPUT -p icmp -j LOG --log-prefix "FILTER-INPUT: "

# 从另一台机器 ping 本机,然后查看日志
sudo dmesg | grep -E "(RAW|MANGLE|NAT|FILTER)-PREROUTING|FILTER-INPUT"

预期输出顺序

RAW-PREROUTING: IN=eth0 ...
MANGLE-PREROUTING: IN=eth0 ...
NAT-PREROUTING: IN=eth0 ...
FILTER-INPUT: IN=eth0 ...

实验 2:第一条匹配规则生效

# 清空规则
sudo iptables -F

# 先添加 ACCEPT,再添加 DROP(针对同一条件)
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j DROP

# 测试:curl 本机 80 端口(如果运行了 web 服务)→ 应该能连接
# 因为第一条规则 ACCEPT 已经匹配,第二条 DROP 不会执行

实验 3:调换顺序观察不同结果

# 清空规则
sudo iptables -F

# 先 DROP,再 ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j DROP
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# 测试:curl 本机 80 端口 → 应该被拒绝
# 因为第一条规则 DROP 已经匹配并终止遍历

2.9 常见误区

误区 1:规则越多越安全

事实:规则越多,遍历时间越长,性能越差。应将高频命中的规则放在前面

# ❌ 性能差:高频规则在后面
iptables -A INPUT -p tcp --dport 8443 -j ACCEPT          # 罕见
iptables -A INPUT -p tcp --dport 53 -j ACCEPT             # 罕见
iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT  # 高频

# ✅ 性能好:高频规则在前面
iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT  # 高频
iptables -A INPUT -p tcp --dport 8443 -j ACCEPT          # 罕见
iptables -A INPUT -p tcp --dport 53 -j ACCEPT             # 罕见

误区 2:nat 表可以做过滤

事实:nat 表的设计目的不是过滤,而是地址转换。过滤应在 filter 表中完成。

误区 3:-F 就够了

事实iptables -F 只清空 filter 表的规则,不会清空其他表。完整清空需要:

iptables -F           # 清空 filter 表
iptables -t nat -F    # 清空 nat 表
iptables -t mangle -F # 清空 mangle 表
iptables -t raw -F    # 清空 raw 表

2.10 注意事项

⚠️ 规则顺序至关重要:iptables 采用"首次匹配"策略,第一个匹配的规则就决定了数据包的命运,后续规则不再检查。

⚠️ 自定义链不能设置默认策略:只有五条内置链才能用 -P 设置默认策略。

⚠️ nat 表的特殊性:nat 表只处理每个连接的第一个包(新建连接),后续包根据 conntrack 记录自动处理,因此在 nat 表中做状态匹配(ESTABLISHED)是多余的。


2.11 扩展阅读

资源 说明
man iptables iptables 官方手册
man iptables-extensions 扩展匹配和目标的手册
RFC 3234 - Middlebox 中间件(防火墙/NAT)标准
《Understanding Linux Network Internals》 Christian Benvenuti 著

本章小结

概念 要点
四表 raw → mangle → nat → filter(按优先级)
五链 PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
规则 匹配条件 + 目标动作,按顺序遍历
匹配 隐式(协议内置)和显式(-m 模块加载)
动作 ACCEPT、DROP、REJECT、RETURN
数据包流向 入站:PREROUTING→INPUT;转发:PREROUTING→FORWARD→POSTROUTING
首次匹配 第一条匹配规则生效,后续规则不再检查

下一章第 03 章:基本语法与操作,将学习 iptables 命令行的具体用法。