关于iptables那些你必须知道的
很多人第一次接触 iptables,感受通常都差不多:
- 命令很长
- 选项很多
- 一旦写错,可能直接把自己锁在服务器外面
于是大家要么机械记忆几条命令,要么直接复制网上的脚本,却始终不明白 iptables 到底在做什么。
这篇文章想解决的,就是这个问题。
我会站在初学者视角,把 iptables 拆成几个最核心的问题来讲:
- iptables 到底是什么,和 netfilter 是什么关系
- table、chain、rule 分别是什么意思
- 一个包进入机器后,规则到底按什么顺序匹配
- 最常用的命令该怎么写、怎么看、怎么删
- 常见实战场景怎么配置
- 为什么规则明明写了却不生效,以及如何排查
如果你读完后能自己写出一套基础防火墙规则,并且知道每一条为什么这么写,这篇文章就达到目的了。
1. iptables 到底是什么
先说结论:
iptables 不是内核里的防火墙本体,它更像是一个用户态管理工具。
真正做包过滤、NAT、连接跟踪这些工作的,是 Linux 内核里的 netfilter 框架;而 iptables 只是你用来向 netfilter 下发规则的命令行工具。
可以把它理解成:
- netfilter 是发动机
- iptables 是方向盘和仪表盘
你平时写的这些命令:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
本质上就是在告诉内核:
如果进入本机的包是 TCP,目标端口是 22,那么允许它通过。
1.1 iptables 和 nftables 的关系
顺手提一句,现代 Linux 里很多发行版已经逐步转向 nftables。
但这并不意味着 iptables 过时到不能学,原因很简单:
- 大量线上环境仍然在使用 iptables
- 很多云主机、容器环境、旧脚本和运维文档仍然围绕 iptables
- 学懂 iptables 之后,再学 nftables 会更容易
所以本文聚焦 iptables,但你需要知道:
- iptables 是老牌主流方案
- nftables 是更新一代的规则框架
- 有些系统上的
iptables命令,底层可能已经映射到 nft 兼容层
2. 先建立一个最重要的心智模型
初学 iptables,最容易混乱的地方是术语太多。
这里先只记住这三层:
- table:规则表,按功能分类
- chain:规则链,按流量经过的位置分类
- rule:规则,真正的匹配条件和动作
可以类比成:
- table 是一个部门
- chain 是部门里的处理队列
- rule 是队列中的具体检查项
一个网络包到来时,会进入某张表中的某条链,然后按顺序逐条匹配规则。匹配到了,就执行对应动作;没有匹配到,就继续往后走。
这句话非常重要:
iptables 规则通常是按顺序自上而下匹配的,先匹配到的规则先执行。
也就是说,规则顺序本身就是逻辑的一部分。
3. 五张常见的表
iptables 里最常见的是下面几张表。
3.1 filter
这是最常用、也是默认使用的表。
它的职责就是:包过滤。
大多数人日常说“防火墙规则”,通常就是在操作 filter 表。
它最常见的三条链是:
INPUT:处理进入本机的数据包OUTPUT:处理从本机发出的数据包FORWARD:处理经过本机转发的数据包
3.2 nat
负责地址转换,也就是 NAT。
最常见用途:
- 源地址转换,SNAT/MASQUERADE
- 目标地址转换,DNAT/端口转发
常见链有:
PREROUTINGPOSTROUTINGOUTPUT
3.3 mangle
用于修改数据包的一些特殊字段,比如 TOS、TTL、MARK 等。
它更偏高级玩法,很多人长时间都用不到。初学阶段知道它存在即可。
3.4 raw
主要用于在连接跟踪之前做特殊处理,比如决定某些包不进入 conntrack。
这张表也不属于入门高频内容。
3.5 security
和 SELinux 等安全模块联动,普通运维场景中不算常用。
3.6 入门建议
如果你刚开始学,只需要优先掌握两张表:
filternat
只要这两张表吃透,已经能解决大多数主机防火墙和端口转发问题。
4. 三条最核心的链
先只盯住 filter 表中的三条链:
4.1 INPUT
凡是“发给这台机器自己”的流量,都会走这里。
例如:
- SSH 登录这台服务器
- 访问这台服务器上的 Nginx 80/443 端口
- 访问本机监听的数据库端口
4.2 OUTPUT
凡是“这台机器主动发出去”的流量,都会走这里。
例如:
- 服务器主动请求外部 API
- 服务器执行
curl - 服务器发 DNS 查询
4.3 FORWARD
凡是“不是发给本机,而是要经过本机转发”的流量,都会走这里。
例如:
- 这台机器是路由器
- 这台机器做网关/NAT 转发
- 容器网络或虚拟机网络经过本机转发
很多人一开始学 iptables 会把 INPUT 和 FORWARD 搞混。
你只要记住一句:
- 给我自己的,走
INPUT - 借我这台机器过路的,走
FORWARD
5. 一个包到底怎么走
这部分是 iptables 最关键的“地图感”。
5.1 发往本机的包
一个外部包进入网卡,目标就是本机服务,大致路径是:
- 先进入
PREROUTING - 路由判断发现目标是本机
- 进入
INPUT - 交给本机进程
5.2 本机发出的包
本机进程主动发包,大致路径是:
- 从
OUTPUT出发 - 经过路由选择
- 必要时进入
POSTROUTING - 从网卡发出
5.3 经过本机转发的包
一个包进来后发现目标不是本机,而是别的机器,大致路径是:
- 先进入
PREROUTING - 路由判断发现要转发
- 进入
FORWARD - 再进入
POSTROUTING - 发往下一跳
如果你理解这三条路径,很多规则就不会乱写了。
比如:
- 你想限制别人 SSH 到本机,改
INPUT - 你想让本机做公网出口 NAT,改
POSTROUTING - 你想控制内网流量是否允许穿过网关,改
FORWARD
6. 规则长什么样
一个典型规则通常由三部分构成:
- 匹配条件
- 所在链
- 目标动作
例如:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
这条规则可以拆成:
-A INPUT:追加到INPUT链-p tcp:匹配 TCP 协议--dport 22:目标端口是 22-j ACCEPT:匹配后执行允许动作
再比如:
iptables -A INPUT -s 192.168.1.10 -p tcp --dport 22 -j ACCEPT
意思就是:
只允许来源 IP 为
192.168.1.10的主机访问本机 SSH 端口。
7. 最常见的动作 target
匹配到规则后,最常见的动作就是 -j 指定的 target。
7.1 ACCEPT
允许通过。
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
7.2 DROP
直接丢弃,不给对方任何响应。
iptables -A INPUT -p tcp --dport 23 -j DROP
从攻击者视角看,这种方式像“石沉大海”。
7.3 REJECT
拒绝,并返回一个错误响应。
iptables -A INPUT -p tcp --dport 23 -j REJECT
这相当于明确告诉对方:这个请求不被接受。
7.4 LOG
记录日志,常用于调试。
iptables -A INPUT -p tcp --dport 2222 -j LOG --log-prefix "IPTABLES DROP: "
注意,LOG 只负责记日志,不会自动丢包。通常要搭配后续的 DROP 或 REJECT 规则一起使用。
7.5 DNAT / SNAT / MASQUERADE
这些多见于 nat 表:
DNAT:改目标地址SNAT:改源地址MASQUERADE:一种动态 SNAT,常用于出口 IP 会变化的场景
8. 你最该记住的常用命令
这部分是上手最有用的内容。
8.1 查看规则
iptables -L
这会列出默认 filter 表的规则,但通常不够好用。
更常见的是:
iptables -L -n -v
参数含义:
-L:列出规则-n:数字显示 IP 和端口,不做 DNS 反查-v:显示更详细信息,比如命中计数、字节数、网卡
如果你想看行号,方便删除:
iptables -L -n -v --line-numbers
8.2 查看指定表
iptables -t nat -L -n -v
如果不写 -t,默认查看的是 filter 表。
8.3 追加规则
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
-A 是 append,表示追加到链尾。
8.4 插入规则
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
这条命令表示把规则插到 INPUT 链第 1 条。
这在远程维护服务器时尤其重要,因为顺序决定匹配结果。
8.5 删除规则
有两种常用删法。
按完整规则删除:
iptables -D INPUT -p tcp --dport 22 -j ACCEPT
按行号删除:
iptables -D INPUT 3
通常我更推荐先看带行号的列表,再按行号删。
8.6 替换规则
iptables -R INPUT 2 -p tcp --dport 22 -s 10.0.0.10 -j ACCEPT
这表示替换 INPUT 链第 2 条规则。
8.7 清空规则
iptables -F
这会清空默认 filter 表中的所有链规则。
清空指定表:
iptables -t nat -F
这个命令风险很大,线上机器慎用。
8.8 修改默认策略
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
-P 是 policy,用来设置链的默认策略。
这表示:
INPUT默认丢弃FORWARD默认丢弃OUTPUT默认允许
它的思想是典型的“默认拒绝,按需放行”。
9. 先学会看输出
很多人会写命令,但不会读规则列表。
例如:
iptables -L INPUT -n -v --line-numbers
可能看到这样的输出:
Chain INPUT (policy DROP 120 packets, 9000 bytes)
num pkts bytes target prot opt in out source destination
1 100 8000 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
2 15 1200 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
3 2 120 ACCEPT tcp -- * * 10.0.0.10 0.0.0.0/0 tcp dpt:22
4 1 60 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
5 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
重点关注这几列:
num:规则序号pkts/bytes:命中次数和流量大小target:动作prot:协议source/destination:源地址和目标地址
如果某条规则一直命中数为 0,往往说明:
- 流量根本没经过这里
- 前面已经被别的规则匹配掉了
- 你写错了条件
10. conntrack 是 iptables 的半壁江山
如果只学静态端口放行,你会觉得 iptables 很笨;但真正让它变得“像现代防火墙”的关键,是 连接跟踪。
最经典的一条规则是:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
这条规则的意义非常大。
10.1 什么叫 ESTABLISHED
比如你从服务器主动访问外部网站:
- 请求包从
OUTPUT发出去 - 响应包回来时,属于一个已建立连接
- 这时可以通过
ESTABLISHED规则放行
10.2 什么叫 RELATED
表示和已有连接相关联的连接,比如某些 FTP 场景或 ICMP 错误响应。
10.3 为什么这条规则几乎总要写
因为它可以让你:
- 保持已有会话不断开
- 不必为返回流量一条条手写对称规则
- 让默认拒绝策略仍然可用
一个非常经典的最小可用防火墙写法就是:
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 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
这里每一条都很有代表性:
- 回环接口必须放行
- 已建立连接必须放行
- 明确开放 SSH / HTTP / HTTPS
- 其余入站流量默认丢弃
11. 为什么一定要先放行 lo
很多服务之间会通过本机回环地址 127.0.0.1 或 ::1 通信。
例如:
- Nginx 反向代理本机应用
- 本地 agent 和 daemon 通信
- 某些数据库或缓存只监听本地地址
因此常见规则是:
iptables -A INPUT -i lo -j ACCEPT
如果你把回环接口都误伤了,很多本地服务会表现得非常诡异。
12. 常见匹配条件怎么写
这一节专门讲命令拼装。
12.1 按协议匹配
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p udp --dport 53 -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
12.2 按源地址匹配
iptables -A INPUT -s 10.0.0.10 -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT
12.3 按目标地址匹配
iptables -A OUTPUT -d 8.8.8.8 -p udp --dport 53 -j ACCEPT
12.4 按网卡匹配
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 443 -j ACCEPT
-i表示入接口-o表示出接口
12.5 按源端口和目标端口匹配
iptables -A INPUT -p tcp --sport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
实际中更常用 --dport,因为服务监听的是目标端口。
12.6 按连接状态匹配
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
12.7 按多个端口匹配
iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j ACCEPT
12.8 按速率限制匹配
例如限制 ping 洪泛:
iptables -A INPUT -p icmp -m limit --limit 5/second --limit-burst 10 -j ACCEPT
超过速率的流量可以在后续规则中 DROP。
13. 从零写一套安全一点的主机规则
下面给一套适合单机 Web 服务器的基础规则,并解释原因。
13.1 适用场景
假设服务器用途如下:
- 允许 SSH 运维
- 提供 HTTP / HTTPS 服务
- 拒绝其他所有入站访问
- 允许本机主动访问外部网络
13.2 规则示例
iptables -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 -p tcp -s 10.0.0.10 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p icmp -m limit --limit 5/second --limit-burst 10 -j ACCEPT
iptables -A INPUT -j LOG --log-prefix "iptables denied: "
iptables -A INPUT -j DROP
13.3 逐条解释
-F先清空旧规则,避免叠加污染- 默认策略把未显式允许的流量都拒掉
- 放行
lo,确保本地通信正常 - 放行已建立连接,避免正常返回流量被拦截
- SSH 只允许办公机
10.0.0.10登录 - 80/443 对外开放
- ICMP 做基本限速
- 最后记录日志并丢弃其他流量
13.4 远程操作时的顺序建议
如果你是通过 SSH 远程连上去改规则,最安全的顺序不是上面这样一股脑执行,而是:
- 先插入允许当前 SSH 的规则
- 再放行
ESTABLISHED,RELATED - 再设置默认策略为
DROP - 最后补充其他业务端口规则
否则你可能在第 2 步就把自己踢下线。
14. NAT 到底在做什么
NAT 是另一个非常高频的 iptables 用法。
14.1 SNAT / MASQUERADE
典型场景:
- 一台 Linux 主机作为内网出口
- 内网机器通过它访问公网
假设:
- 内网网卡是
eth1 - 外网网卡是
eth0 - 内网网段是
192.168.10.0/24
常见写法:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -P FORWARD DROP
iptables -A FORWARD -i eth1 -o eth0 -s 192.168.10.0/24 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -d 192.168.10.0/24 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE
这里最核心的是最后一条:
把内网源地址伪装成出口网卡地址,再发往公网。
如果公网 IP 固定,也可以用 SNAT:
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j SNAT --to-source 203.0.113.10
14.2 DNAT / 端口转发
典型场景:
- 公网访问网关的 8080 端口
- 实际转发到内网主机
192.168.10.20:80
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp -d 203.0.113.10 --dport 8080 -j DNAT --to-destination 192.168.10.20:80
iptables -A FORWARD -p tcp -d 192.168.10.20 --dport 80 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -p tcp -s 192.168.10.20 --sport 80 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
这就是很经典的“公网端口映射到内网服务”。
15. 自定义链能让规则更清晰
当规则多起来后,全塞进 INPUT 会越来越难维护。
这时可以定义自己的链。
iptables -N TCP_SERVICES
iptables -A TCP_SERVICES -p tcp --dport 22 -j ACCEPT
iptables -A TCP_SERVICES -p tcp --dport 80 -j ACCEPT
iptables -A TCP_SERVICES -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp -j TCP_SERVICES
这相当于把 TCP 服务相关规则拆到一个单独模块里。
好处是:
- 结构清晰
- 便于复用
- 后续排障更容易
查看自定义链也一样:
iptables -L TCP_SERVICES -n -v
16. 保存规则,不然重启就没了
这是初学者最容易踩的坑之一。
很多系统上,你执行 iptables 命令只是改了当前内核运行时规则,机器一重启可能就消失。
16.1 导出当前规则
iptables-save
保存到文件:
iptables-save > /etc/iptables.rules
16.2 从文件恢复
iptables-restore < /etc/iptables.rules
16.3 持久化方式和发行版有关
不同系统做法不一样,比如:
- Debian/Ubuntu 常见
iptables-persistent - CentOS/RHEL 早期常见
service iptables save - 新系统可能配合 systemd 或转向 nftables
所以你在生产环境里,不能只会写规则,还要确认:
规则是如何随开机自动恢复的。
17. 非常实用的排障方法
iptables 的问题,很多时候不是“规则不会写”,而是“看不出来到底卡在哪”。
下面这些方法很实用。
17.1 先看有没有命中
iptables -L -n -v --line-numbers
先看 pkts 和 bytes 是否增长。
如果不增长,说明流量没匹配到这条规则。
17.2 检查规则顺序
iptables 是顺序匹配。
如果你前面先写了:
iptables -A INPUT -j DROP
那后面再写允许 SSH 的规则基本就没意义了,因为流量在前面已经被丢掉了。
17.3 用 LOG 看看到底是谁被拦了
iptables -I INPUT 1 -p tcp --dport 22 -j LOG --log-prefix "ssh debug: "
然后去看系统日志,比如 dmesg、journalctl -k 或 rsyslog 落盘文件。
17.4 确认服务真的在监听
iptables 没问题,不代表服务就通。
例如:
ss -lntp
如果服务压根没监听在对应端口,再怎么放行也没用。
17.5 确认云环境还有一层安全组
在云服务器上,经常有两层防护:
- 云厂商安全组
- 主机内 iptables
你在主机里放行了 80 端口,但安全组没放,也一样访问不了。
17.6 确认是不是 firewalld / ufw 在管理规则
某些发行版上,真正的规则入口可能是:
firewalldufw- 容器运行时自动注入的链
这时你手工写的规则可能会被覆盖,或者根本不是你以为的那套链路。
17.7 确认内核转发开关
如果你在做路由/NAT/端口转发,别忘了:
sysctl net.ipv4.ip_forward
如果值是 0,说明内核没有打开 IPv4 转发。
18. 新手最常犯的错误
这里专门总结一下常见坑。
18.1 忘了放行已有连接
没有这条:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
很多返回流量会异常。
18.2 默认策略设成 DROP 之前没留 SSH 生路
这会导致远程把自己锁死。
18.3 分不清 INPUT 和 FORWARD
- 访问本机服务,用
INPUT - 经过本机转发,用
FORWARD
18.4 只写 nat,不写 FORWARD
很多人做端口转发时只写了 DNAT,却忘了配合 FORWARD 放行,结果仍然不通。
18.5 忘了持久化
机器一重启,规则全没。
18.6 规则越写越多,却没有自定义链
最后自己都看不懂。
19. 一组值得收藏的常用命令清单
19.1 查看当前 filter 规则
iptables -L -n -v --line-numbers
19.2 查看 nat 规则
iptables -t nat -L -n -v --line-numbers
19.3 放行 SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
19.4 只允许某个 IP SSH
iptables -A INPUT -p tcp -s 10.0.0.10 --dport 22 -j ACCEPT
19.5 放行 HTTP/HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
19.6 放行已建立连接
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
19.7 丢弃某个 IP
iptables -A INPUT -s 203.0.113.55 -j DROP
19.8 删除第 3 条规则
iptables -D INPUT 3
19.9 插入规则到最前面
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
19.10 保存规则
iptables-save > /etc/iptables.rules
19.11 恢复规则
iptables-restore < /etc/iptables.rules
20. 给初学者的学习顺序建议
如果你现在还觉得 iptables 有点乱,不要试图一次把所有表、所有模块、所有 target 全背下来。
推荐学习顺序是:
- 先搞清楚
INPUT、OUTPUT、FORWARD - 再理解
filter和nat - 学会看规则列表和命中计数
- 学会
ACCEPT、DROP、REJECT - 学会
conntrack的ESTABLISHED,RELATED - 最后再去看 DNAT、SNAT、自定义链、限速、打标等进阶内容
只要这个顺序不乱,iptables 其实没有看起来那么可怕。
21. 总结
iptables 真正难的地方,不是命令本身,而是你必须在脑子里有一张“包路径地图”。
你可以把这篇文章压缩成下面这几个关键点:
- iptables 是管理工具,底层是 netfilter
- 重点先学
filter表和nat表 - 重点先学
INPUT、OUTPUT、FORWARD - 规则按顺序匹配,顺序非常重要
ESTABLISHED,RELATED是最常见的基础规则之一- 做 NAT 时,不要忘了转发链和内核转发开关
- 写完规则后,一定确认持久化方式
如果你是第一次系统学习 iptables,我建议你找一台测试机,亲手做三件事:
- 只开放 SSH 和 80/443
- 限制 SSH 只能从你的办公 IP 登录
- 做一次简单的端口转发
当这三件事你都能自己完成,并且知道每条命令为什么这么写,iptables 就算真正入门了。