news 2026/10/8 9:04:45

iptables 防火墙原理与实战:从数据包路径到规则配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
iptables 防火墙原理与实战:从数据包路径到规则配置

记得刚上手服务器那会儿,我第一次配置 Linux iptables 防火墙,顺手把默认策略设成了 DROP,紧接着 SSH 就断了。那一刻我坐在机房门口,看着黑掉的窗口,才真正意识到:防火墙规则不是写给评审看的,是你要亲手交给每一台机器的边界说明书。

从那以后我再也没把 iptables 当命令列表背过。它本质上是一套跑在 Linux 内核网络栈里的包过滤机制,理解数据包怎么进、怎么出、在哪条链上被检查,比记住几十条命令重要得多。这篇文章就把我从入门到实战过程中攒下的经验完整梳理一遍,覆盖原理、规则语法、常用场景和排障技巧。不管你是刚接触 Linux 的运维新人,还是平时用 ufw、firewalld 但想摸清底层的开发者,都能拿到可以直接上手的思路和避坑点。

1. 一眼看懂 iptables 原理:表和链的协作关系

1.1 为什么先理解原理而不是先背命令

很多人学 iptables 的第一反应是打开搜索引擎找“常用命令大全”,然后复制粘贴跑一遍。结果遇到“为什么我加了规则但没生效”“为什么我清空规则后服务还是不通”就彻底懵了。

我个人的经验是:iptables 的命令其实非常有限,翻来覆去就是增删改查那几种,但真正难的是规则背后的流量路径。你只有知道一个数据包从网卡进来之后要经过哪几个检查点,才能解释得清“这条规则为什么写在这里”“为什么这么做”。所以这一节我们先打地基,内容不多,但会管很久。

1.2 四表五链:一张表理清核心结构

iptables 的整个框架可以概括为“四张表、五条内置链”。表是用来分类管理功能的,链则是数据包流经的检查点。不同的表在各自的链上注册规则,同一个链上可能同时存在来自不同表的规则。

常用的四张表:

表名作用常用场景
filter包过滤,决定放行还是丢弃日常防火墙策略,绝大多数人只用这张表
nat地址转换,修改源地址或目标地址端口转发、共享上网、容器网络
mangle修改数据包头部字段,比如 TTL、TOS策略路由、负载均衡标记,日常很少直接操作
raw绕过连接跟踪,主要用于性能优化高流量环境下让部分数据包不进入 conntrack

五条内置链则对应数据包在内核协议栈中的几个关键位置:PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING。名字看着抽象,其实只要把“数据包从外网进来、到本机、转出去”这条路径走一遍就清晰了。

1.3 数据包在链中的走向:走一遍就通

我习惯用一句话概括数据包的一生:进来先过 PREROUTING,目的地是本地就进 INPUT,目的地是别人就进 FORWARD,本地发出去的先逛 OUTPUT 再去 POSTROUTING。

具体展开就是:

  1. 数据包从网卡进入,首先到达 PREROUTING 链。这里是做 DNAT 和其他早期处理的地方,典型场景是“公网访问 80 端口,悄悄转发给内网某台机器的 8080”。
  2. 如果数据包的目标地址是本机,走 INPUT 链。这是绝大多数人写防火墙规则的地方,比如“允许外部访问 22 端口”“拒绝某个 IP 访问”。
  3. 如果数据包的目标地址不是本机,而是需要转发到其他主机,走 FORWARD 链。这就是路由器、网关、容器宿主机上的数据包要走的路。
  4. 本机自己发出去的包,先经过 OUTPUT 链,比如本机主动访问外网,可以在 OUTPUT 控制出站流量。
  5. 无论是要转发的包,还是本机发出的包,最后都会经过 POSTROUTING 链。这里是做 SNAT(源地址转换)的地方,比如内网机器共享一个公网 IP 上网,就是把源地址改写成了网关的公网 IP。

很多初学者会问:为什么我在 INPUT 链上写规则,转发流量不生效?就是因为转发流量根本不经过 INPUT。数据包从 PREROUTING 进来后,判断目标不是本机就直接往 FORWARD 走了。如果你没有理解这条路,写一万条规则也是白搭。

1.4 规则匹配的隐含逻辑:搞定一条就不再匹配

还有一个特别关键、也特别容易忽略的点:iptables 的规则是“顺序匹配,匹配即停”的。数据包到达某条链后,会拿着链上的规则从第一条开始逐条比对,一旦某条规则的所有条件都匹配上,就直接执行这条规则指定的动作(ACCEPT、DROP、REJECT 等),后面的规则不再检查。

这个机制和很多传统访问控制列表(ACL)不一样。ACL 往往是按顺序匹配之后还要继续往下看,iptables 则是“一锤定音”。所以规则顺序极其重要。你自己都能想明白后果:如果有一条DROP 所有来自 192.168.1.0/24 的包的规则排在最前面,那后面再怎么写“允许 192.168.1.10 访问”都是无效的,因为它根本没有机会被检查到。

这也就是为什么我建议在实战中把规则按“量级从大到小”来排:先拦截大网段,再放行具体 IP。或者反过来,如果你想做“先放行少数白名单,再拦截其他所有流量”,就必须把“允许”规则放在前面,把“默认拒绝”放在最后。顺序错了,轻则业务异常,重则把自己挡在门外。

1.5 自定义链:给规则做项目管理

当规则多了以后,全塞进内置链会让排查变成噩梦。比如你这么看iptables -L INPUT -n,看到几十条规则混在一起,根本分不清哪条是防扫描的、哪条是给 Docker 留的、哪条是业务白名单。自定义链就是用来做规则分组的。

你可以创建一条名为SYN-FLOOD的链,把防 SYN 攻击的规则都放进去,然后在 INPUT 链上用一条-j SYN-FLOOD跳转进去。这样主链简洁,子链职责单一,排查的时候直接iptables -L SYN-FLOOD -n --line-numbers看一条链就够了。写自定义链并不复杂,就是-N 链名创建,往里面加规则,然后在需要的位置用-j 链名跳过去,最后要在子链的末尾写一条RETURN,让不匹配的流量回到主链继续检查。我在后面的实战环节里会带大家一起建一条。

2. 规则语法拆解:从一条命令到一套体系

2.1 iptables 命令的通用格式

iptables 的命令说白了就是一条“填空式”的语句,你只需要弄清楚每个空位填什么。我习惯把它拆成五个部分:表 + 操作动作 + 链 + 匹配条件 + 目标动作。

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

这里的-t 表名如果不写,默认就是 filter 表。因为绝大多数场景用的都是 filter 表,所以日常命令里经常会省略-t filter,这是完全正常的。最容易看花眼的是各种单字母参数,我整理了一份常用对照:

参数含义
-A在链末尾追加一条规则
-I在链开头或指定位置插入规则,-I INPUT 3表示插到第 3 条
-D删除指定规则
-F清空链内所有规则
-P设置链的默认策略(ACCEPT/DROP)
-L列出当前规则
-n不做 DNS 反向解析,直接显示 IP,速度更快
--line-numbers显示规则序号,排查顺序问题必备
-p协议类型,比如 tcp、udp、icmp
-s / -d源地址 / 目标地址
--dport / --sport目标端口 / 源端口,常配合 -p tcp 使用
-i / -o数据包进入的网卡 / 出去时用的网卡
-j匹配后执行的动作,比如 ACCEPT、DROP、REJECT、LOG、SNAT、DNAT

实操里记住一个原则:写规则的时候先把这五个部分在心里填一遍。哪个空填不出来,就说明你对这条规则的效果还没想清楚。

2.2 从零拆解一条真实规则

拿一条很典型的规则来拆:

iptables -A INPUT -p tcp -s 10.0.0.5 --dport 22 -j ACCEPT

这条规则的意思是:允许来自 10.0.0.5 的 TCP 数据包访问本机的 22 端口。

拆开看就是:

  • -A INPUT:在 INPUT 链末尾追加规则,也就是检查“进到本机”的包。
  • -p tcp:只匹配 TCP 协议,这是 SSH、HTTP、HTTPS 等绝大多数应用的基础协议。
  • -s 10.0.0.5:源地址限制为 10.0.0.5,其他 IP 发来的包不匹配这条。
  • --dport 22:目标端口是 22。
  • -j ACCEPT:匹配成功就放行。

注意,--dport 22虽然没有显式写-d 本机IP,因为数据包到达 INPUT 链时目标本来就是本机,所以一般不用重复写目标地址。但如果你想限制“只能访问本机的某个特定 IP”,比如本机有多网卡多 IP,那就得加上-d 具体IP。

这里还有个细节:--dport单独使用往往不生效。它必须跟在-p tcp或-p udp之后,因为端口这个概念只存在于 TCP/UDP 协议里。如果你写了iptables -A INPUT --dport 22 -j ACCEPT而没写-p tcp,有些版本的 iptables 会直接报错,有些则行为怪异。别问我怎么知道的,都是踩过的。

2.3 方向与网卡参数:什么时候该用 -i,什么时候该用 -o

-i和-o是新手特别容易搞混的一对参数。简单记:-i是数据包从哪个网卡进来,-o是数据包从哪个网卡出去。

判断依据就看当前在哪个链上。在 INPUT 链上,数据包是“进来”的,所以用-i限定来源网卡,写-o基本没意义。在 OUTPUT 链上,数据包是“出去”的,所以用-o限定出口网卡。在 FORWARD 链上,进和出两个方向都有,所以-i和-o可以同时出现,分别用来限制“从哪个网卡进来再转发到哪个网卡出去”。

举个实际例子,公司网关上有两张网卡,eth0 接内网,eth1 接外网。你想限制“只有内网网卡 eth0 进来的包才允许转发”,就可以写:

iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT

这条规则就是告诉内核:只有从 eth0 进来、准备从 eth1 出去的转发流量才放行。如果你不关心具体网卡,只按 IP 和端口做策略,那-i/-o不写也行,但写清楚能让规则的语义更严谨,也能避免某些情况下出现“内网进来的包也能伪装成外网流量被放行”之类的问题。

2.4 三种常见目标动作:ACCEPT、DROP、REJECT 到底怎么选

很多新手卡在 DROP 和 REJECT 的区别上。这两个动作都是“拒绝”,但表现截然不同:

  • DROP 是直接把数据包扔掉,不回复任何信息。外部客户端的表现就是“一直转圈直到超时”,像是主机根本不存在。
  • REJECT 是拒绝这个包,同时给发送方回一个错误信息,比如icmp-port-unreachable。客户端会立刻收到“连接被拒绝”,反馈更快,方便排查问题。

实际使用中,我对外部未知流量倾向于用 DROP,因为它不会暴露主机的存在感,也不容易让扫描工具通过“拒绝报文”的类型来判断你在用什么防火墙策略。但在调试阶段或者内网环境,用 REJECT 更舒服,因为一眼就能看出来是被拒绝还是网络不可达。

ACCEPT 就不多说了,放行。还有几个动作虽然不常用但必须知道:

  • LOG:把匹配到的数据包记录到内核日志,但不做拦截,通常配合 DROP 写在一起,既能记日志又能拦截。
  • SNAT:源地址转换,典型场景是内网机器上网共享一个公网 IP。
  • DNAT:目标地址转换,典型场景是端口转发。

关于 LOG 有个细节:LOG 不会终止匹配。如果你写了iptables -A INPUT -j LOG,数据包匹配 LOG 之后还会继续往下检查后面的规则。所以如果你想“记录并丢弃”,需要写两条规则,先 LOG 再 DROP,而且两条规则的条件必须一样。

3. 实战:用 iptables 搭建一套可用的防火墙策略

3.1 第一步:确定初始策略

动手之前先想清楚:你想要的模型是“默认拒绝,仅放行白名单”,还是“默认放行,手动拦截黑名单”?

我的建议是,对新部署的服务器或者安全要求较高的业务,直接上“默认拒绝”模型。这就像门禁系统的逻辑:没有明确授权的人一律不让进,而不是先让所有人进来再说。虽然前期配置麻烦一点,但长期来看安全收益最大。

先写一个最小化基线:

# 清除现有规则 iptables -F iptables -X iptables -Z # 设置默认策略 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT

这里有个极其重要的顺序问题:必须先加“放行”规则,再设置默认策略为 DROP,或者至少确保你当前的操作终端流量会被放行。如果你已经有 SSH 連上服务器,直接上来一句iptables -P INPUT DROP,恭喜你,下一秒你的 SSH 就掉了。我自己干过这事,后来学乖了:每次改默认策略之前,先检查现在的 SSH 连接是不是稳定,或者干脆先加一条“放行当前来源 IP 的 22 端口”规则垫底。

-X清空自定义链,-Z清零计数器,这两步在重置规则时是常规操作。需要注意,-F只是清空规则,并不会改默认策略,所以默认策略要单独用-P设置。

3.2 放行回环接口和必要服务

确认默认策略后,一般先放行回环接口 lo,否则很多本机程序之间的通信会莫名其妙出问题。然后是已经建立的连接和关联连接,这一条几乎是必写的:

# 放行回环 iptables -A INPUT -i lo -j ACCEPT # 放行已建立连接及关联连接 iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

ESTABLISHED,RELATED这条规则是 iptables 状态机制的灵魂。它允许所有“你已经建立起来的连接”的返回流量进入本机。比如你的服务器主动向外发起了一个 HTTP 请求,返回的数据包到达 INPUT 链时,conntrack 发现这是某个已建立连接的一部分,就直接放行了。如果没有这条,哪怕你服务器本身对外提供服务没影响,但主动访问外网的返回包全都会被默认策略丢掉,表现就是“能发请求但收不到响应”。

从这里也能看出 iptables 是“有状态防火墙”,它不只是逐包孤立判断,而是能记住连接的状态。这个概念理解透了,后面很多问题都可以自己推导出答案。

接着放行你真正想要对外开放的服务。以最常见的 SSH + HTTPS 为例:

# SSH 建议限制来源 IP iptables -A INPUT -p tcp -s 你的办公网段/32 --dport 22 -j ACCEPT # HTTPS 对外开放 iptables -A INPUT -p tcp --dport 443 -j ACCEPT

这里长时间踩的坑是“我从公司网段访问,为什么还是连不上”。多半是因为你没搞清公司出口 IP 和你的本机 IP 不是一回事。-s后面应该填你公司出口的公网 IP,不是你自己电脑上的内网 IP。你可以先不加-s,测试通了之后再收紧,这样排障更快。

3.3 常用安全加固规则:防扫描、防 SYN Flood

下面这条命令是防止外部对服务器进行无差别端口扫描的常用姿势:

# 记录丢弃的新连接尝试(防止大量扫描日志淹没系统) iptables -A INPUT -m conntrack --ctstate NEW -p tcp --syn -j LOG iptables -A INPUT -m conntrack --ctstate NEW -p tcp --syn -m limit --limit 5/s --limit-burst 10 -j ACCEPT iptables -A INPUT -m conntrack --ctstate NEW -p tcp --syn -j DROP

第一条先记录所有新建 TCP 连接,第二条用limit模块限制新建连接的速率到每秒 5 个,超过这个速度的连接会被第三条 DROP 掉。作用是给正常访问留出余量,同时把一瞬间的高频扫描包拦下来。

limit模块的--limit 5/s表示平均每秒允许 5 个包,--limit-burst 10表示在开始限速前允许先突发通过 10 个包。这个参数要按业务调整,如果服务器同时在线几百人,每秒 5 个肯定不够,可以调到 100/s。我见过有人抄了网上的“防攻击规则”直接上生产,结果正常业务的大批量连接全部被限速误伤,这种“防攻击防到自己”的案例真不少。

如果服务器内存和 CPU 足够,还可以控制单 IP 的并发连接数:

iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 50 -j REJECT

意思是单个源 IP 与本机同时建立的 TCP 连接数超过 50 时,新连接被拒绝。这在某些被恶意占连接数的情况下非常有效,但要小心动态 IP 池用户(比如手机网络出口 IP 是共享的),一个池子里可能几十人共用出口 IP,限制太低会误伤。建议先观察正常业务的连接数量,再把阈值设到两倍左右。

3.4 黑白名单实战:两种思路的区别和写法

黑名单和白名单不是 iptables 的专有概念,但设计思路会影响整套规则形态。

黑名单思路:默认允许一切,只拒绝名单中的 IP。适合公网业务,因为白名单没法覆盖所有真实用户。典型写法:

# 黑名单列表 iptables -A INPUT -s 192.168.1.66 -j DROP iptables -A INPUT -s 192.168.1.88 -j DROP

黑名单很好理解,但维护成本会随恶意 IP 增多而上涨。有没有办法自动维护?有,我常用的一种方式是写脚本定期解析访问日志里的异常 IP,然后批量生成规则。比如统计某个 IP 一分钟内 SSH 登录失败超过 10 次,就把它追加进 DROP 规则。把这段逻辑写进 cron,五分钟跑一次,黑名单就基本自动化了。

白名单思路:默认拒绝所有,只允许名单内 IP。更适合内部系统、管理后台这类只给特定人员使用的资源。写法也简单:

iptables -P INPUT DROP iptables -A INPUT -p tcp -s 10.10.0.0/24 --dport 8080 -j ACCEPT

白名单方案最怕的就是 IP 变动。比如你人在咖啡厅办公,公司出口 IP 却不固定,每次访问都要先在防火墙里加 IP,那体验会很痛苦。我建议把白名单规则的更新脚本化,配合一个简单的 Web 管理界面做“自助申请”,后台批准后自动把申请人的当前出口 IP 加进去,这样既安全又不用每次手动改规则。

还有人说“iptables 反向允许”,其实指的就是状态机制下的返回流量放行——你不需要手动为每一个允许出去的请求写相反方向的允许规则,conntrack 的ESTABLISHED已经帮你处理了返回方向。如果你的规则里漏了ESTABLISHED,RELATED这条,就会看到“只能出不能进”或者“只能进不能出”的诡异现象。

3.5 NAT 转发与端口映射:把内网服务发布出去

很多场景下需要把内网服务的端口映射到公网,或者让内网机器通过一台 Linux 网关共享上网。这两件事分别对应 DNAT 和 SNAT。

先看端口映射。假设内网有台机器 192.168.1.100,跑着 8080 端口的 Web 服务,你想让公网用户通过这台 Linux 网关的 80 端口访问到它。

第一步是开启内核转发:

echo 1 > /proc/sys/net/ipv4/ip_forward sysctl -w net.ipv4.ip_forward=1

第二步加 DNAT 规则,在 nat 表的 PREROUTING 链上把目标端口 80 改写成内网机器的 8080 端口:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:8080

第三步加 SNAT 规则,在内网机器处理完请求返回时,把源地址改回网关地址,让客户端以为始终在和网关通信:

iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.100 --dport 8080 -j SNAT --to-source 网关内网IP

第四步放行 FORWARD 链上对应流量。注意默认策略刚才设了 DROP,所以要在 filter 表的 FORWARD 链放行从任何网卡进来、到 192.168.1.100:8080 的流量,同时放行走内网网卡出去的返回流量:

iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 8080 -j ACCEPT iptables -A FORWARD -p tcp -s 192.168.1.100 --sport 8080 -j ACCEPT

如果你已经写了-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT在 FORWARD 链上,返回流量那条可以不用重复写,但建议还是写出来,语义更清楚。

共享上网的 SNAT 是另一个经典场景。让内网大量设备通过网关上网,只需要一条规则的变体:

iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth1 -j MASQUERADE

MASQUERADE 和 SNAT 的区别在于,SNAT 需要显式指定转换后的源 IP,而 MASQUERADE 会自动读取出口网卡上当前的 IP 来做转换。如果网关的出口 IP 是动态获取的(比如拨号上网),用 MASQUERADE 更省心。如果出口 IP 是固定的,用 SNAT 性能更好,也更容易查日志。

3.6 规则持久化:挡不住重启就是白干

很多人的防火墙规则在运行期好好的,一重启就全面失效。这是因为 iptables 的规则是存在内存里的,不落盘就不会自动恢复。

常见的持久化方案有三类。

第一类,发行版自带服务。RHEL/CentOS 系早期版本用service iptables save,规则会写到/etc/sysconfig/iptables。但 CentOS 7 之后的系统默认是 firewalld,iptables 服务要自己安装并启用。

Ubuntu/Debian 系推荐用iptables-persistent:

apt install iptables-persistent netfilter-persistent save netfilter-persistent reload

它会读取/etc/iptables/rules.v4和/etc/iptables/rules.v6,分别对应 IPv4 和 IPv6 规则。

第二类,手动导出导入。不管什么发行版,都可以用:

iptables-save > /etc/iptables.rules

恢复时:

iptables-restore < /etc/iptables.rules

想开机自动恢复,可以把恢复命令写进/etc/rc.local,或者做成 systemd service 写个 ExecStart。这个方法最通用,适合各种“精简版”系统。

第三类,用配置管理工具,比如 Ansible 的iptables模块或直接管理规则文件。团队协作时效果最好,规则文件进 Git,每次变更记录都有迹可循。

我现在的习惯是:所有服务器都把/etc/iptables.rules当成受版本控制的配置文件来管理,写完规则立即iptables-save备份一份,改之前也会先备份一份。哪怕不要自动化,光这一个习惯就救过我很多次。

4. 常见问题与排查技巧实录

4.1 问题速查表:先看现象再下手

现象可能原因排查思路
开启防火墙后 ping 不通ICMP 被默认策略拦截,或没放行 echo-requestiptables -L INPUT -n看是否有 icmp 相关规则,临时加一条-A INPUT -p icmp -j ACCEPT验证
SSH 配置完规则就掉线默认策略改成 DROP 前没放行 SSH用机房 console/带外管理登录,先-P INPUT ACCEPT保住入口,再逐步收紧
本机能访问外网,外网访问不了本机入站端口没放行,或服务只监听在内网 IPss -lntp看监听地址,再用curl到端口测连通性
规则清空后服务还是不通firewalld 或其他工具叠加管理、SELinux 拦截检查systemctl status firewalld,临时关闭 SELinux 测试,确认不是应用层问题
重启后规则丢失没有做持久化,或持久化文件被覆盖检查/etc/sysconfig/iptables或/etc/iptables/rules.v4是否存在、内容是否正确
NAT 转发不生效ip_forward 没开、FORWARD 默认 DROPsysctl net.ipv4.ip_forward查看,再看iptables -L FORWARD -n
连接被限速误伤limit 参数过小,或 connlimit 阈值过低查看iptables -L INPUT -n -v的计数器增长情况,调整阈值后观察业务指标
规则很多但无法判断谁生效重复规则、顺序不对、自定义链跳转有误加--line-numbers列出序号,用iptables -L 链名 -n -v --line-numbers看计数器
配置多了之后性能下降规则过多且结构扁平,匹配每次都从头遍历用自定义链拆分场景,或考虑迁移到 nftables

4.2 最值得说道的四个坑

第一个坑:把自己锁在外面。这是几乎每个 iptables 新手都会经历的事。解决办法除了“先放行后设默认策略”之外,我再补充一个土办法:永远不要在一条命令里同时清空规则、设置默认 DROP 和添加白名单。分三步走,每步之间停顿观察一下 SSH 是否正常。如果 SSH 断了,就用带外管理(比如服务器厂商的远程管理卡)或去机房本地登录。另外,很多云厂商的控制台里有“防火墙规则”和“安全组”两层,它们和系统内 iptables 是独立生效的,排查问题别只盯着一层看。

第二个坑:DROP 和 REJECT 的语义混淆。我见过有人把 SSH 的失败尝试从 REJECT 改成 DROP 以后,排查问题时摸不着头脑,因为从客户端看就是“超时”,完全不知道是被墙了还是线路问题。反过来,生产环境不分青红皂白全用 REJECT,等于告诉扫描器“这里有人”,而且会放大日志量。合理的策略是:对外隐藏敏感端口用 DROP,对内调试和快速反馈用 REJECT,两边各取所需。

第三个坑:FORWARD 链被忽略。只写了 INPUT 链的规则,发现内网机器访问外网不通,或者端口映射不生效。转发流量走的是 FORWARD,和 INPUT 无关。很多厂家设备的“防火墙双机热备”“主备切换”里也会涉及 FORWARD 链状态同步,但这就是另一个话题了。作为运维,记住一条:只要你的 Linux 在扮演路由器、网关或容器宿主机的角色,FORWARD 链就要认真对待。

第四个坑:规则顺序和计数器不分。排查的时候用iptables -L INPUT -n -v看每个规则的 Packet 计数增长情况,能非常直观地判断某条规则到底有没有被匹配到。如果计数一直是 0,说明数据包根本没有走到这条规则,要么是前面已经有规则拦截了,要么是链不对。这个技巧比瞎猜高效十倍,我现在排障第一件事就是看计数器。

4.3 和 firewalld、ufw 的关系:到底用哪个

不少发行版预装的是 firewalld 或 ufw,它们的底层其实还是 iptables(或者 nftables)。firewalld 引入了“区域”概念,ufw 则简化了端口管理命令,对于简单场景都够用。但如果你需要精细的 IP+端口+协议匹配、需要写复杂的 NAT 规则、需要自定义链来做流量分组,直接操作 iptables 反而更顺手。

我的建议是:如果是在同一个环境里,不要混用 firewalld 和直接 iptables 命令。因为 firewalld 有自己的一套规则管理机制,它的规则和手工 iptables 规则可能互相覆盖或冲突,排查起来头大。CentOS 上我一般直接停掉 firewalld,切回原生 iptables 服务;Ubuntu 上如果装了 ufw 就用 ufw 管理,如果要用 iptables 写复杂规则,那就顺手把 ufw 停用。一句话:选一条路走到黑。

4.4 命令不存在的处理:常见精简镜像场景

有些精简版 Linux 镜像默认没有安装 iptables 命令,或者装上之后提示模块没加载。这种情况在自制的精简镜像、容器镜像里特别常见。先看包管理器能不能装:

# Debian/Ubuntu apt install iptables # RHEL/CentOS yum install iptables

装完之后如果服务依然报错,很可能是内核没加载对应模块:

modprobe ip_tables modprobe iptable_filter modprobe iptable_nat modprobe nf_conntrack

模块加载问题通常会报iptables: No chain/target/match by that name这类错误。确认模块加载好之后,再重新执行你的规则。这里也牵扯到一个新趋势:新版内核主推 nftables,iptables命令在很多新发行版上只是一个兼容层,底层可能已经换成了 nftables 的框架。如果你用的是很新的发行版,建议看看内核默认用的是哪个框架,直接学 nftables 也行。但 iptables 的匹配思路和规则设计理念是通用的,学透它再切 nftables 会非常顺滑。

5. 谈谈我个人的维护习惯和技巧

写到这里,我分享一下日常维护 iptables 时的一些习惯,应该能帮你避开不少弯路。

规则文件一定要有注释。iptables-save 导出的规则文件支持注释行,用#开头就行。我会把规则按业务模块分段:# SSH、# HTTP、# 防扫描、# Docker,这样过了几个月再回来改规则,能立刻定位到对应区域。如果规则是纯iptables命令脚本的形式,我也建议在脚本里写清每条规则的目的,以及“这条规则为什么这么写”,因为你自己也未必记得住当时的想法。

变更之前先备份。我已经养成了肌肉记忆:改规则前先iptables-save > /etc/iptables/backup_$(date +%F).rules存一份。这样哪怕新规则把服务搞挂了,也能秒回滚到上一个可用状态。回滚的命令是iptables-restore < 备份文件,前提是备份文件是当时执行iptables-save生成的,规则状态忠实反映了内存里的情况。

新规则先测试再上生产。有条件的话,先在测试环境把规则跑几天,观察计数器、连接数、日志有没有异常,再同步到生产。没条件的话,至少挑业务低峰期操作,并且每条规则的生效范围先放宽一点,比如先不加-s限制,确认放行后再收紧源 IP。这样做看起来慢,但比一次性把规则写“完美”又写错要好得多。

最后分享一个小技巧:iptables -L不带-n时会做 DNS 反向解析,大量规则下会非常卡,而且输出可能对着 IP 解析出的域名发呆。所以我从很早开始就只用iptables -L -n,必要时加-v看计数器。既然是排障,就别让格式问题耽误时间。

iptables 这套东西,说难不难,说简单也不简单。难的不是命令,是你能不能把“数据包怎么走、规则怎么匹配、状态怎么维护”这十几个字真正想透。想透了之后,再复杂的防火墙策略,本质上都是在这条路径上做取舍而已。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 9:04:42

幻尔串口总线舵机Python SDK控制实战:从单舵机到机械臂动作组

做惯了小舵机玩具项目的人&#xff0c;第一次接触幻尔&#xff08;Hiwonder&#xff09;串口总线舵机控制Python SDK时&#xff0c;可能会有点不适应&#xff1a;以前一根PWM信号线驱动一个舵机&#xff0c;现在换成一根串口线挂一串舵机&#xff0c;代码也从“写脉宽”变成了“…

作者头像 李华
网站建设 2026/10/8 9:04:42

MySQL单表能存21亿条吗?亿级数据性能优化与分库分表实战解析

这是一个困扰了很多人的经典问题&#xff0c;我早期刚接触MySQL时也跟同事争论过。今天不打算只丢一个结论&#xff0c;而是把背后的原理、实际测试数据、以及真正会遇到的性能瓶颈一一道来&#xff0c;希望能帮到正在纠结“要不要拆表”、“要不要分库”的你。 先直接说结论&…

作者头像 李华
网站建设 2026/10/8 9:03:53

Android系统调用详解:从Binder到strace,App与内核的桥梁

做了几年Android&#xff0c;你可能见过这种邪门现象&#xff1a;同一个文件&#xff0c;Java层File.exists()返回 false&#xff0c;你用adb shell ls却能看得见&#xff1b;App切到后台再回来&#xff0c;无端卡了两秒&#xff1b;一个Native so在这台手机上好好的&#xff0…

作者头像 李华
网站建设 2026/10/8 9:02:53

IntelliJ Platform插件开发入门:环境搭建到第一个Action

简介&#xff1a;面向Intellij IDEA插件开发者的系统学习手册&#xff0c;基于JetBrains Runtime 17.0.9&#xff0c;兼容IDEA 2023及2024版本&#xff0c;适合具备一定Java基础、希望进入插件开发领域的读者。上册围绕插件开发基础与图形化插件开发展开&#xff1a;从平台术语…

作者头像 李华
网站建设 2026/10/8 9:02:35

3.5公里跑步打卡:如何用微习惯设计轻松坚持的运动计划

有一段时间&#xff0c;我对“3.5打卡”这件事特别着迷&#xff0c;但也特别沮丧。着迷是因为看着日历上连续的对勾会带来一种很踏实的掌控感&#xff0c;沮丧则因为我最初给自己定的目标——每天5公里——坚持到第9天就断了。后来我把目标从5公里改成3.5公里&#xff0c;这个看…

作者头像 李华