iptables

本文由 Codex 辅助生成,内容整理自 B 站「米拉一老王」的 iptables 学习资料。

简介

iptables 常被直接叫做 Linux 防火墙,但更准确一点说,它是一个用户态命令行工具,用来给 Linux 内核里的 netfilter 写规则。

netfilter 才是真正工作在内核里的包处理框架。数据包进入协议栈后,会在几个固定位置经过 netfilter 的 hook 点;iptables 把规则挂到这些 hook 对应的链上,内核经过链时按顺序匹配规则,匹配到了就执行对应动作。

写 iptables 规则时,可以先把需求翻译成下面这几个问题:

1
需求是什么 -> 要做什么动作 -> 用哪张表 -> 写到哪条链 -> 补上匹配条件

例如:

  • 需求:禁止别人访问本机 80 端口
  • 动作:丢弃数据包
  • 表:filter 表
  • 链:INPUT 链
  • 规则:匹配 TCP 目标端口 80,然后 DROP

先建立一个简单模型

刚开始学 iptables 时,不要先背命令,先记住一句话:

1
数据包经过内核时,netfilter 在几个固定位置设置了检查点,iptables 用来给这些检查点写规则。

这些检查点就是常说的“链”。每条规则本质上都在回答三个问题:

  1. 在哪里检查?也就是选哪条链。
  2. 检查什么包?也就是写匹配条件。
  3. 命中后怎么办?也就是选动作。

数据包会经过哪些链

入站和出站流量

2026-06-05_13-55-22

这张图画了两种最常见的流量。

第一种是别人访问本机,比如访问这台机器的 80 端口:

1
数据包进入网卡 -> PREROUTING -> 路由判断目标是本机 -> INPUT -> 本机进程

第二种是本机主动访问外部服务,比如执行 curl https://example.com

1
本机进程 -> OUTPUT -> POSTROUTING -> 数据包通过网卡发出

这里图里的 localhost 可以先理解为“本机上的进程或服务”,不必纠结它是不是 127.0.0.1

先记结论:

  • 别人访问本机:重点看 INPUT
  • 本机主动访问别人:重点看 OUTPUT

转发流量

20260605135926

这张图画的是 Linux 作为路由器或网关时的场景。

如果数据包进入本机后,路由判断发现目标不是本机,而是需要从另一块网卡转发出去,就会走 FORWARD 链:

1
数据包进入网卡 -> PREROUTING -> 路由判断目标不是本机 -> FORWARD -> POSTROUTING -> 网卡发出

FORWARD 链只处理经过本机转发的流量,不处理访问本机服务的流量。

常见链可以这样记:

初学者理解 常见场景
PREROUTING 数据包刚进来,还没决定去哪 DNAT、提前标记
INPUT 数据包要进入本机 控制别人访问本机
FORWARD 数据包经过本机转发 Linux 当路由器或网关
OUTPUT 本机发出去的数据包 控制本机访问外部
POSTROUTING 数据包准备从网卡出去 SNAT、MASQUERADE

表:规则按用途分类

20260605140000

链解决的是“数据包走到哪里”,表解决的是“我要对数据包做哪类事情”。

图中含义 我的理解
raw 在连接跟踪处理前进行特定处理,优先级最高 很早期介入,常用于跳过连接跟踪
mangle 对数据包进行拆包、修改、再封包的处理 修改包的属性,比如 mark、TTL、TOS
nat 所有地址转换相关的操作 做 DNAT、SNAT、MASQUERADE
filter 负责过滤,比如防火墙功能 最常用,用来 ACCEPT、DROP、REJECT

初学阶段先重点记两张表:

  • filter:控制包能不能通过,也就是最常见的防火墙规则。
  • nat:修改源地址或目标地址,比如端口转发、共享上网。

rawmangle 可以先知道名字,等遇到连接跟踪、打 mark、改 TTL 这类需求时再深入。

表和链的关系

20260605140021

不是每张表都能写到每条链上。比如 filter 表没有 PREROUTINGPOSTROUTING,因为过滤本机流量通常发生在 INPUTOUTPUTFORWARD 这些位置。

表 / 链 PREROUTING INPUT FORWARD OUTPUT POSTROUTING
raw 支持 不支持 不支持 支持 不支持
mangle 支持 支持 支持 支持 支持
nat 支持 部分系统支持 不支持 支持 支持
filter 不支持 支持 支持 支持 不支持

初学时不用把整张表硬背下来,先记这几个高频组合:

  • 过滤访问本机的流量:filter 表 + INPUT
  • 过滤本机发出的流量:filter 表 + OUTPUT
  • 过滤转发流量:filter 表 + FORWARD
  • 修改目标地址:nat 表 + PREROUTING
  • 修改源地址:nat 表 + POSTROUTING

比如“禁止别人访问本机 80 端口”:

  • 访问本机,所以看 INPUT
  • 要过滤流量,所以用 filter

动作:匹配后怎么办

20260605140035

规则匹配成功后,需要告诉内核怎么处理这个包。这个动作写在 -j 后面,也叫 target。

动作 含义 常见用途
ACCEPT 接受数据包,允许通过 放行流量
DROP 丢弃数据包,不返回任何响应 静默拒绝访问
REJECT 拒绝数据包,并返回错误信息 明确告诉对方被拒绝
LOG 记录数据包信息到日志 排障、观察命中情况
DNAT 目标地址转换 端口转发、负载入口
SNAT 源地址转换 固定出口地址转换
MASQUERADE 动态源地址转换 出口 IP 不固定时做 NAT

初学者最常用的是前三个:

  • ACCEPT:放行
  • DROP:丢掉,而且不告诉对方
  • REJECT:拒绝,并告诉对方

从需求推导规则

20260605140101

这张图是写规则的核心方法。不要先背命令,先按这个顺序想:

1
需求 -> 动作 -> 表 -> 链

例如“丢掉访问本机 TCP 80 端口的数据包”:

  • 需求:禁止访问本机 80 端口
  • 动作:丢弃数据包,也就是 DROP
  • 表:过滤流量,用 filter
  • 链:访问本机,用 INPUT

再补上匹配条件:

  • 协议:TCP,写 -p tcp
  • 目标端口:80,写 --dport 80

最后得到完整规则:

1
iptables -t filter -A INPUT -p tcp --dport 80 -j DROP

核心概念

到这里,几个核心概念可以这样收束:

概念 解决的问题 例子
表 table 我要做哪类事情 filternat
链 chain 数据包走到了哪个位置 INPUTOUTPUTFORWARD
规则 rule 具体的一条处理逻辑 匹配 TCP 80 端口然后 DROP
匹配 match 找出我要处理的数据包 -p tcp --dport 80
动作 target 命中后怎么处理 ACCEPTDROP

iptables 会从链的第一条规则开始往下匹配。匹配到规则后就执行对应动作;如果一直没有匹配到,就执行这条链的默认策略。

基本语法

iptables 命令大体长这样:

1
iptables [-t 表名] 操作 链名 匹配条件 -j 动作

常用操作:

操作 含义
-A append,追加到链末尾
-I insert,插入到指定位置,默认插到第一条
-D delete,删除规则
-L list,查看规则
-P policy,设置内置链默认策略
-F flush,清空规则

参数是区分大小写的,这点很容易踩坑:

  • -p 表示协议,比如 -p tcp
  • -P 表示默认策略,比如 -P INPUT DROP
  • -i 表示入接口
  • -I 表示插入规则
  • INPUTOUTPUTACCEPTDROP 这些链名和动作通常大写
  • filternatmangleraw 这些表名通常小写

使用场景

丢掉访问本机 TCP 80 端口的数据包

1
iptables -t filter -A INPUT -p tcp --dport 80 -j DROP

因为默认就是 filter 表,也可以省略 -t filter

1
iptables -A INPUT -p tcp --dport 80 -j DROP

这条规则的意思是:

  • -A INPUT:追加到 INPUT 链,处理访问本机的数据包
  • -p tcp:匹配 TCP 协议
  • --dport 80:匹配目标端口 80
  • -j DROP:匹配后直接丢弃

默认拒绝全部入站,只打开 UDP 53

注意:如果是在远程服务器上操作,先确认 SSH 端口已经放行,否则很容易把自己锁在门外。

先放行已有连接和本机回环流量:

1
2
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT

再放行 UDP 53:

1
iptables -A INPUT -p udp --dport 53 -j ACCEPT

最后把 INPUT 链默认策略改成 DROP

1
iptables -P INPUT DROP

为什么要加 ESTABLISHED,RELATED

因为默认丢弃入站包后,本机主动访问外部服务时,请求可以从 OUTPUT 出去,但对方回来的响应包会进入 INPUT。如果不放行已有连接的回包,本机很多主动出站请求也会表现得像失败。

旧写法也常见:

1
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

现在更推荐使用 conntrack

1
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

查看 filter 表 INPUT 链规则

1
iptables -t filter -L INPUT -n -v --line-numbers

参数说明:

  • -L INPUT:查看 INPUT
  • -n:不要反查域名和服务名,显示更快更直观
  • -v:显示命中次数、字节数、接口等详细信息
  • --line-numbers:显示规则编号,方便插入和删除

在指定位置前插入新规则

把允许 UDP 54 的规则插入到 INPUT 链第 4 条之前:

1
iptables -t filter -I INPUT 4 -p udp --dport 54 -j ACCEPT

这里要用 -I,不是 -A-A 只能追加到链末尾。

删除指定规则

删除 filterINPUT 链的第 8 条规则:

1
iptables -t filter -D INPUT 8

删除前建议先查看编号:

1
iptables -t filter -L INPUT -n -v --line-numbers

查看完整规则

iptables -L 更适合人工查看,iptables-save 更适合备份和排障:

1
iptables-save

它会按可恢复的格式输出当前所有表和规则。

小结

学习 iptables 可以先抓住四个问题:

  1. 我要处理什么流量?入站、本机出站,还是转发?
  2. 这个流量会经过哪条链?INPUTOUTPUTFORWARDPREROUTING 还是 POSTROUTING
  3. 我要做什么动作?过滤就用 filter,地址转换就用 nat
  4. 规则顺序对不对?iptables 从上往下匹配,默认策略优先级最低。

记住这条主线后,再看各种参数就不会乱:

1
先判断数据包流向 -> 再选链 -> 再选表 -> 最后写匹配和动作

参考文章