返回归档
🧩网络与 Linux

包进内核之后:iptables 的五条链

iptables 是 netfilter 的用户态接口。包进内核后先过五条链,路由判决决定走 INPUT 还是 FORWARD;filter / nat / mangle / raw 是挂在链上的表,不是另一套路径。

文章目录

iptables 不是防火墙本身。防火墙在内核里,叫 netfilter。iptables 只是往那些 hook 上挂规则的用户态工具。

先不要背参数。先跟一个包:它从网卡进来之后,会按固定顺序穿过五条链。走哪几条,取决于这包是给本机的、路过本机的,还是本机自己发出的

NIC in → PREROUTING → Route → INPUT / FORWARD / OUTPUT → POSTROUTING → NIC out

五条链,不是三条

常见说法是「INPUT / OUTPUT / FORWARD 三条链」。那是 filter 表里默认能看到的三条。netfilter 的钩子有五个:

什么时候经过 典型用途
PREROUTING 包刚进协议栈、还没做路由判决 DNAT、连线追踪入口
INPUT 路由认定:目的是本机 主机防火墙
FORWARD 路由认定:目的是别处,本机只是路过 网关、容器转发
OUTPUT 本机进程构造出来的包 本机访问外网的限制
POSTROUTING 包马上要离开本机、路由已经定了 SNAT / MASQUERADE

三条路径记住就够用:

  1. 别人访问本机:网卡 → PREROUTING → 路由 → INPUT → 进程
  2. 本机当路由器:网卡 → PREROUTING → 路由 → FORWARDPOSTROUTING → 网卡
  3. 本机自己发出去:进程 → OUTPUT → 路由 → POSTROUTING → 网卡

本机发出的包不进 PREROUTING。这就是为什么 kube-proxy 要把 ClusterIP 的 DNAT 同时挂在 PREROUTINGOUTPUT:包可能从别的 Pod 进来,也可能是本机进程自己访问 Service。

表挂在链上

链是路径,表是挂在路径上的规则集。同一个包会按固定顺序穿过多张表,不是「选一张表走一遍」。

常见链 干什么
raw PREROUTINGOUTPUT 最早;常用来 NOTRACK,跳过 conntrack
mangle 五条都有 改 TOS / MARK,少改地址
nat PREROUTINGINPUTOUTPUTPOSTROUTING 改地址。DNAT 在路由前,SNAT 在路由后
filter INPUTFORWARDOUTPUT 放行或丢掉。默认表

顺序可以记成:raw → mangle → nat → filter。查规则时 -t 选表,不写就是 filter

匹配上了会发生什么

规则自上而下,先匹配先生效-A 追加到末尾,-I 插到指定位置(默认最前)。

动作 含义
ACCEPT 这一张表放过,包继续往下走
DROP 丢掉,对端通常只看到超时
REJECT 丢掉,并新造一个 ICMP unreachable 或 TCP RST 回去。不是把原包弹回去
LOG 写日志,然后继续匹配后面的规则
SNAT / MASQUERADE / DNAT 改地址,交给 conntrack 记下来,回程自动改回去

-P--policy,给内置链设默认策略:规则都没中时怎么办。它不是 default 的缩写。用户自定义链没有 policy,用完必须 -j RETURN 或终结动作。

-X 删的是空的自定义链,不是「快速删规则」。清空规则是 -F

一条能看懂的主机防火墙

# 只动 filter / nat,先清空再写
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

# 默认:入站和转发丢掉,本机出站放行
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -s 192.168.0.0/16 -p tcp -m multiport --dports 22,80,443 \
  -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
iptables -A INPUT -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
iptables -A INPUT -j REJECT

读这段时按路径走一遍:SSH 新建连接走 INPUT 的 NEW;对端回包走 ESTABLISHED,不必再开 22。本机访问外网走 OUTPUT(默认 ACCEPT)和 POSTROUTING(这里没改地址)。这台机器如果不是路由器,FORWARD 的 DROP 不会挡住本机自己的流量。

常用匹配:-s / -d-i / -o-p--sport / --dport-m conntrack --ctstate-m limit-m state 是旧写法,现在用 conntrack

和容器、Kubernetes 的交界

Docker / 多数 CNI 会在 FORWARD 放行,在 POSTROUTING 做 MASQUERADE。kube-proxy 的 iptables 模式在 PREROUTING 把 ClusterIP DNAT 成 Pod IP,回程靠这台机器上的 conntrack 把源地址改回 VIP。下一篇 K8s 网络 按包把这条路径画开。

nftables 是后继者,语义仍是同一套 hook。先把五条链走熟,再换工具不亏。