
记得刚上手服务器那会儿我第一次配置 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。具体展开就是数据包从网卡进入首先到达 PREROUTING 链。这里是做 DNAT 和其他早期处理的地方典型场景是“公网访问 80 端口悄悄转发给内网某台机器的 8080”。如果数据包的目标地址是本机走 INPUT 链。这是绝大多数人写防火墙规则的地方比如“允许外部访问 22 端口”“拒绝某个 IP 访问”。如果数据包的目标地址不是本机而是需要转发到其他主机走 FORWARD 链。这就是路由器、网关、容器宿主机上的数据包要走的路。本机自己发出去的包先经过 OUTPUT 链比如本机主动访问外网可以在 OUTPUT 控制出站流量。无论是要转发的包还是本机发出的包最后都会经过 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 ACCEPTESTABLISHED,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_forward1第二步加 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 MASQUERADEMASQUERADE 和 SNAT 的区别在于SNAT 需要显式指定转换后的源 IP而 MASQUERADE 会自动读取出口网卡上当前的 IP 来做转换。如果网关的出口 IP 是动态获取的比如拨号上网用 MASQUERADE 更省心。如果出口 IP 是固定的用 SNAT 性能更好也更容易查日志。3.6 规则持久化挡不住重启就是白干很多人的防火墙规则在运行期好好的一重启就全面失效。这是因为 iptables 的规则是存在内存里的不落盘就不会自动恢复。常见的持久化方案有三类。第一类发行版自带服务。RHEL/CentOS 系早期版本用service iptables save规则会写到/etc/sysconfig/iptables。但 CentOS 7 之后的系统默认是 firewalldiptables 服务要自己安装并启用。Ubuntu/Debian 系推荐用iptables-persistentapt 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看计数器配置多了之后性能下降规则过多且结构扁平匹配每次都从头遍历用自定义链拆分场景或考虑迁移到 nftables4.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这类错误。确认模块加载好之后再重新执行你的规则。这里也牵扯到一个新趋势新版内核主推 nftablesiptables命令在很多新发行版上只是一个兼容层底层可能已经换成了 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 这套东西说难不难说简单也不简单。难的不是命令是你能不能把“数据包怎么走、规则怎么匹配、状态怎么维护”这十几个字真正想透。想透了之后再复杂的防火墙策略本质上都是在这条路径上做取舍而已。