iptables-save与iptables-restore:Linux防火墙规则持久化与恢复实战

发布时间:2026/10/4 2:52:57
iptables-save与iptables-restore:Linux防火墙规则持久化与恢复实战 先纠正一个很多人都会踩的误区iptables-restore并不是用来“把规则导出到文件”的它的职责正好相反——从文件里读取规则恢复进内核里的防火墙。真正负责导出的是它的搭档iptables-save。这两个命令一个存、一个取合在一起才是 Linux 防火墙规则持久化的完整闭环。很多人学 Linux 防火墙时习惯用iptables -A一条条加规则加完发现重启服务器规则全没了又不知道怎么把当前规则完整备份出来更不敢在生产环境批量恢复。这篇文章就把这套“保存-恢复”机制讲透从命令用法、规则文件格式到生产环境备份/回滚/批量部署的完整套路最后再分享几个我实际踩过的坑。内容偏向实操Linux 运维、搞网络安全、自学系统管理的人都能用得上。容器环境排查网络问题的人也别划走后面有一小节专门讲iptables v1.8.9 (legacy): cant initialize iptables table nat这个高频报错。1. 先弄清 iptables-restore 的定位别被名字带偏了1.1 它的真实职责与那对“黄金搭档”的关系iptables-restore从标准输入stdin读取规则文件解析后把规则写入内核的 netfilter 框架。也就是说数据流向是“文件 - 内核”这是一个导入操作。我们平时敲iptables -A INPUT -p tcp --dport 22 -j ACCEPT也是在往内核里写规则但iptables-restore真正强的地方在于它能把一整份规则文件一次性恢复进去而不是一条一条敲。反过来iptables-save是从内核里把当前所有规则导出来打印到标准输出stdout。要存成文件用重定向就行iptables-save /etc/iptables.rules这两个命令是配套的。你可以理解为打游戏存档iptables命令负责“玩”iptables-save负责“存档”iptables-restore负责“读档”。没有存档重启系统等于游戏进度清零。命令数据方向典型用法核心用途iptables -A/-D/-I用户 - 内核iptables -A INPUT -j DROP单条增删改查iptables-save内核 - stdoutiptables-save rules.txt导出当前完整规则集iptables-restore文件/stdin - 内核iptables-restore rules.txt从文件批量恢复规则集记住这个关系后面读任何文档都不容易晕。1.2 为什么规则会“丢”内存态规则的宿命初学 iptables 的人有个很大的困惑规则明明用iptables -A加进去了用iptables -L -n也能看到为什么重启服务器就没了因为 iptables 规则只存在于内核内存中。它不像你编辑/etc/hosts、/etc/resolv.conf那样写进了磁盘文件重启后文件还在。iptables命令本身没有提供任何“自动把规则保存到磁盘”的机制——这不是设计缺陷而是有意为之规则属于运行时状态内核只负责执行不负责持久化。这就像你往路由器里临时改了条静态路由没点“保存配置”一断电就还原。Linux 服务器的防火墙规则也是这个道理。生产环境里配置一次规则容易但规则往往几十条、上百条分布在 filter、nat、mangle 多张表里靠人工重新敲一遍不现实而且极容易漏。所以必须依赖iptables-save和iptables-restore这对工具来完成落盘和恢复。1.3 在哪些场景下能真正救你把这两个命令的价值放到实际场景里你会更直观地感受到修改前备份生产服务器的防火墙规则动之前必须iptables-save /backup/iptables-$(date %F).rules。规则改炸了一条iptables-restore 备份文件就能还原比逐条敲回去不知道快多少倍。批量部署一套规则在测试环境验证通过后需要发到几十台服务器上。人工挨个敲命令不现实把规则文件分发过去每台机器执行一次iptables-restore rules.txt就全部对齐了。版本管理与审计规则文件是纯文本天然适合放进 Git 仓库。谁改了什么、加了哪条放行规则、删了哪个端口git diff一目了然。应急回滚最近一次规则更新导致业务异常直接恢复到上一个版本的规则文件把故障时间控制在分钟级别。2. 从导出到恢复的完整实操流程2.1 导出规则iptables-save 的正确用法先看看最常用的几种导出方式# 导出所有表的所有规则默认行为 iptables-save # 导出到文件 iptables-save /etc/iptables.rules # 只导出 nat 表 iptables-save -t nat # 带计数器导出默认就带这里显式写出来 iptables-save -c /etc/iptables.rules-c--counters这个参数值得解释一下。iptables 每条规则都跟着两个计数器匹配了多少个数据包packets和多少字节bytes。iptables-save默认就会把计数器带进输出文件里这也是为什么文件里每条规则末尾有个[123:4567]这样的字段。计数器有什么用主要在两个场景一是做流量统计和排障看看某条放行规则实际命中多少流量二是用iptables-restore -c恢复时能把计数器的值也还原回去保证恢复前后状态完全一致。如果不关心计数恢复时可以不用-c让计数器从零开始。2.2 看懂规则文件一行一行拆给你看用iptables-save导出的文件格式看起来像脚本但并不是脚本。它由若干“表区块”组成每个表以*表名开头、以COMMIT结束。一段典型的输出长这样# Generated by iptables-save v1.8.7 on Mon Jan 1 00:00:00 2024 *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT COMMIT # Completed on Mon Jan 1 00:00:00 2024逐段拆解# Generated by ...和# Completed on ...是注释由iptables-save自动生成恢复时iptables-restore会忽略它们。*filter声明当前要操作的是 filter 表。后面可能还有*nat、*mangle取决于内核里有没有加载对应表。:INPUT DROP [0:0]是链定义。冒号开头格式是:链名 默认策略 [数据包计数:字节计数]。这行的意思是把 INPUT 链的默认策略设为 DROP当前计数器为零。默认策略极其关键它决定了没有匹配到任何规则的数据包最终是放行还是丢弃。-A INPUT -i lo -j ACCEPT是规则行含义和命令行下敲的iptables -A INPUT -i lo -j ACCEPT完全一致追加一条规则到 INPUT 链匹配来自环回接口lo的数据包并放行。COMMIT表示这张表的规则到此为止iptables-restore在读到 COMMIT 后才把这些规则真正提交到内核。给新手提个醒规则文件里不要把COMMIT漏了。漏掉 COMMITiptables-restore会认为这张表的规则还没定义完报语法错误整张表的规则都不会加载。这个错误通常被日志忽略掉等你发现规则没生效时已经过了一段时间。2.3 恢复规则iptables-restore 的三类用法恢复操作的核心命令只有一句iptables-restore /etc/iptables.rules注意iptables-restore不接受把文件名作为参数直接传它只从文件描述符读。所以重定向符号是不能省的也可以用管道cat /etc/iptables.rules | iptables-restore但没人这么写直接用重定向最直观、最不容易出错。完整参数参考参数作用典型场景无参数清空已有规则后把文件里的规则完整加载标准化部署、规则回滚-n不刷新flush现有规则只把文件里的规则追加进去增量追加、临时加载部分规则-c连计数器一起恢复排障时需要保留原始命中数据--test只解析和校验文件不真正修改内核规则上线前语法检查-t只恢复指定的表如-t nat只处理某一张表时实际工作中用得最多的是无参数和--test。我个人的习惯是任何规则文件在正式恢复之前先跑一次--testiptables-restore --test /etc/iptables.rules如果规则文件里有语法错误或者引用了不存在的表/链它会直接报错。测试通过再真正恢复能帮你挡掉一大半低级失误。2.4 开机自动加载规则不落地等于白配上面讲的都是手动恢复但生产环境里服务器重启后必须自动把规则加载回来。这里提供三种方案从推荐到备选排序。方案一systemd 服务适用所有主流发行版创建/etc/systemd/system/iptables-restore.service[Unit] DescriptionRestore iptables rules Beforenetwork-pre.target Wantsnetwork-pre.target [Service] Typeoneshot ExecStart/usr/sbin/iptables-restore /etc/iptables.rules ExecReload/usr/sbin/iptables-restore /etc/iptables.rules RemainAfterExityes [Install] WantedBymulti-user.target注意systemd 服务里的ExecStart/usr/sbin/iptables-restore /etc/iptables.rules这里的写法其实等价于iptables-restore /etc/iptables.rulesiptables-restore自己会处理文件参数并打开读取需要校验你的 iptables 版本是否支持v1.8.x 支持。如果版本老就写成ExecStart/bin/sh -c /usr/sbin/iptables-restore /etc/iptables.rules。启用服务systemctl enable iptables-restore.service方案二iptables-persistentDebian/Ubuntu 系apt install iptables-persistent netfilter-persistent save netfilter-persistent reload安装后规则默认保存到/etc/iptables/rules.v4和/etc/iptables/rules.v6开机自动加载省心。Ubuntu 系服务器我很推荐这个方案。方案三rc.local老系统备选CentOS 6 或一些老环境里把加载命令写进/etc/rc.local/usr/sbin/iptables-restore /etc/iptables.rules需要给rc.local加上执行权限才能生效。不管用哪种方案核心思想都一样把规则文件放到固定位置系统启动时执行一次恢复。规则文件哪来的当然是用iptables-save导出的。3. 参数、文件格式与底层逻辑把每个“为什么”说清楚3.1 为什么恢复要用“整文件”而不是一条条敲有人会问既然iptables -A能加规则为什么还要多此一举搞个iptables-restore最直接的理由是效率。几十上百条规则用iptables -A一条条敲或者写个 for 循环去执行每条命令都要走一遍用户态到内核态慢不说中间任何一个步骤出了问题规则集就处于一个“只加载了一半”的混乱状态。比如你敲了前 10 条放行规则还没敲第 11 条默认拒绝规则这时候防火墙对业务来说就是不可控的。iptables-restore就不一样。它读取整个规则文件把每张表的规则一次性解析再统一提交到内核。更重要的是不带-n参数时iptables-restore会先把现有的规则清空再按文件内容逐个加载。这意味着文件里的内容就成了规则的“最终目标状态”不会出现“旧规则还在、新规则又插入”的叠加混乱。用一句话概括iptables -A是程序化地修改状态iptables-restore是声明式地把规则集对齐到文件内容。这也是为什么很多自动化运维工具里最终落地的都是 save/restore 组合。3.2 默认策略、规则顺序与计数器文件里的三个隐藏陷阱再聊深一点文件内容的三个细节每一个都能让你少踩一次坑。默认策略。链定义行:INPUT DROP [0:0]里写的是链的默认策略。当数据包经过链时如果所有规则都不匹配就走默认策略。生产环境里最常见的默认策略组合是 INPUT 链 DROP、FORWARD 链 DROP、OUTPUT 链 ACCEPT。恢复这样的文件后任何新的入站连接都会被拒绝除非有显式放行规则。规则顺序。iptables 规则的匹配是按文件里的顺序从上到下进行的命中一条就执行动作不再继续往下匹配。所以放行规则必须写在拒绝规则之前。比如-A INPUT -p tcp --dport 22 -j ACCEPT写在前面最后再写-A INPUT -j DROP如果顺序反了DROP 把 SSH 连接全丢了后面的 ACCEPT 永远不会被执行这就是经典的“规则顺序坑”。计数器。[0:0]不是随便写的装饰品。iptables-restore在加载规则时会保留这些计数器的初始值。恢复时若想保留中断前的精确计数用-c若想清零重来就别用-c。这在小流量环境没什么感觉但在高流量生产环境计数器是排障时判断“规则到底有没有生效”的重要依据。3.3 我推荐的“改规则工作流”一套标准化流程基于上面这些原理我整理了一套自己在生产环境用的改规则流程步骤固定、出错率低备份现状iptables-save /backup/iptables-$(date %F-%H%M).rules修改规则文件复制备份文件为工作文件编辑它。别直接改系统里正在生效的规则要通过改“文件”来间接改规则。语法校验iptables-restore --test 工作文件先测后上条件允许的话先在测试机恢复这个文件验证业务端口连通性。生产恢复iptables-restore 工作文件即时验证立刻检查业务端口、SSH 是否正常看iptables-save的实际输出和文件是否一致。重新保存验证通过后把已生效的规则再次iptables-save /etc/iptables.rules保持持久化文件是“当前生效版本”。这套流程的核心理念是永远不要在线上服务器上直接敲 iptables 命令去试一切改动先沉淀成文件再通过 restore 加载。3.4 高频报错iptables v1.8.9 (legacy) 初始化 nat 表失败部署 iptables-restore 时最常遇到的一个报错热词里也出现了iptables v1.8.9 (legacy): cant initialize iptables table nat: table does not exist这个报错我在 Docker 容器里见过最多其次是没有加载 netfilter 相关模块的轻量级云服务器。拆解一下原因。报错里的(legacy)指明 iptables 用的是 legacy 后端走的是老式ip_tables内核模块接口。而内核里如果没有加载iptable_nat之类的模块nat表就不存在自然无法初始化。排查步骤# 1. 确认内核是否有 ip_tables 相关模块 lsmod | grep -E iptable|ip_tables|nf_tables # 2. 手动加载 nat 表模块 modprobe iptable_nat # 3. 再执行导出/恢复 iptables-save -t nat如果modprobe报错或者没有权限比如容器里那就换个思路容器环境确认容器是否具备 CAP_NET_ADMIN 权限。用 docker 的话启动时加--cap-addNET_ADMINK8s 里可能需要调整 securityContext。宿主机环境检查/proc/net/ip_tables_names是否存在如果不存在说明ip_tables模块没加载。还有一个思路把 iptables 切换到 nft 后端有些发行版上用update-alternatives --config iptables切换或者直接用iptables-nft命令。nft 后端走的是 nf_tables 框架很多以前 legacy 模式下报的“表不存在”问题在 nft 模式下直接消失。这里多说一句报错里的 legacy 和 nft 指的是 iptables 命令的两种后端实现。新内核普遍推荐 nft 模式但老脚本和老思路还停留在 legacy所以实际环境里两种模式并存。排障时先看清楚自己的发行版默认走的是哪个后端再决定排查方向。4. 生产环境实战备份、批量部署与应急回滚4.1 定时备份规则脚本既然规则这么容易丢定时备份就是最基本的“保险”。把下面脚本放进 crontab每天凌晨备份一次#!/bin/bash # /usr/local/bin/backup-iptables.sh BACKUP_DIR/backup/iptables mkdir -p ${BACKUP_DIR} iptables-save ${BACKUP_DIR}/iptables-$(date %Y%m%d-%H%M%S).rules find ${BACKUP_DIR} -name iptables-*.rules -mtime 30 -deletecrontab 里加一行0 2 * * * /usr/local/bin/backup-iptables.sh这样至少保留最近 30 天的规则快照。就算某天规则被改得面目全非也能从历史快照里找到回退版本。4.2 多台机器批量部署规则文件一旦定型批量部署就很省事。最简单的思路把文件分发到目标机器然后执行iptables-restore。用 shell 循环for host in 192.168.1.10 192.168.1.11 192.168.1.12; do scp /etc/iptables.rules root${host}:/etc/iptables.rules ssh root${host} iptables-restore /etc/iptables.rules iptables-save /etc/iptables.rules done用 Ansible 更规范- name: 部署 iptables 规则 hosts: all tasks: - name: 分发规则文件 copy: src: files/iptables.rules dest: /etc/iptables.rules - name: 恢复规则 shell: iptables-restore /etc/iptables.rules - name: 持久化规则 shell: iptables-save /etc/iptables.rules不管用哪种方式恢复完成之后的iptables-save /etc/iptables.rules别省。它能在恢复成功的基础上把“当前生效规则”重新固化为持久化文件避免文件里写的和内核实际加载的有细微出入。4.3 回滚策略别把自己关在门外远程管理服务器防火墙最恐怖的事情就是你恢复了新规则默认策略是 DROP而新规则里又忘了放行 SSH 端口结果当前连接被切断你再也登不进去。这种情况我遇到过当时后背一凉。两个习惯可以避免这个问题第一恢复前先把 SSH 端口放行规则放到文件最顶部。无论如何-A INPUT -p tcp --dport 22 -j ACCEPT这种保命规则必须先写确保恢复过程中不会断连。第二用定时自动回滚兜底。如果你在改一批高风险规则担心恢复后误伤业务可以用一个带超时的回滚脚本# 先保存旧规则 iptables-save /backup/rules.bak # 启动一个 60 秒后自动回滚的定时任务 (sleep 60; iptables-restore /backup/rules.bak) # 再恢复新规则然后立刻验证 iptables-restore /etc/iptables.rules.new echo 恢复成功检查服务连通性...如果 60 秒内验证发现新规则有问题等它自动回滚到旧规则就行如果验证没问题就把后台那个定时任务 kill 掉pkill -f sleep 60这个“超时自动回滚”的思路还可以再封装成更完整的脚本加上端口探测等验证逻辑。核心就是要给自己留一条物理上的回退路径别一口气把旧规则全冲了。4.4 顺带说一句屏蔽“某个程序连网”与 iptables 的边界有热词提到“先去防火墙建立出入站规则屏蔽 acrobat.exe 联网”这是 Windows 防火墙的用法按程序路径exe直接屏蔽。Linux 下用 iptables 做不到按完整程序路径屏蔽它本质上是基于 IP、协议、端口的网络层过滤。但也不是完全没有对应方案。Linux 下要限制某个进程联网可以用 iptables 的owner模块# 屏蔽 UID 为 1001 的用户进程出站流量 iptables -A OUTPUT -m owner --uid-owner 1001 -j DROP # 屏蔽具体命令名cmd-owner注意仅对本地生成的数据包有效 iptables -A OUTPUT -m owner --cmd-owner acrobat -j DROP--cmd-owner有一定局限性命令名字匹配有长度限制而且只有 root 能看到所有进程的 owner 信息。所以生产环境里更常见的做法是先定位程序要访问的 IP/域名/IP 段再按目的地址去封禁。比如# 禁止访问某个远程 IP 段注意先放行已建立的连接否则会误伤正常出站 iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT iptables -A OUTPUT -d 203.0.113.0/24 -j DROP顺序上一定要把 ESTABLISHED 放行规则写在前面否则你自己的正常出站连接也会被掐断。这种思路在服务端限制出站、防数据外传的场景里很常用。5. 常见问题与避坑实录5.1 高频坑我从实际环境里踩过来的总结几个高频坑每一个我都亲眼见过有的还亲手踩过。坑 1恢复后 SSH 立刻断开。原因九成是默认策略被设成了 DROP或者放行 SSH 的规则没有覆盖当前连接的网卡/来源 IP。解决办法就是 4.3 节那套“保命规则”“自动回滚”。坑 2规则文件漏了 COMMIT。语法校验时容易忽略这种静默失败。恢复命令不报错但表里的规则一条都没进去。使用--test能不能查出来分情况--test能发现明显的语法错误但漏 COMMIT 的情况不同版本行为有差异。最稳的验证方式恢复完立刻iptables-save和原文件对比。坑 3规则顺序反了。放行规则写在了拒绝规则后面。比如先写-A INPUT -j DROP再写-A INPUT -p tcp --dport 80 -j ACCEPT那 80 端口永远通不了。iptables 匹配是“命中即停”规则顺序就是优先级顺序。坑 4脚本里反复iptables -A导致规则叠加。有些初始化脚本每次启动都执行同样的-A命令重启几次以后规则列表里出现好几条相同的规则计数器和性能都会受影响。解决方式要么先iptables -F清空再添加要么干脆用iptables-restore加载固定文件。坑 5nat 表规则恢复失败。就是 3.4 节那个table does not exist。常见于未加载iptable_nat模块的容器或精简内核环境。注意不仅是 nat 表mangle、raw表也有各自的模块依赖恢复前可以先确认/proc/net/ip_tables_names里列出了哪些表。5.2 一套可靠的测试与上线流程综合前面所有内容我建议你把下面这套流程固化下来每次变更防火墙规则都这么走在测试环境先iptables-restore 新规则文件模拟线上流量做一次连通性验证。对正式规则文件执行iptables-restore --test确保语法层面无问题。恢复前看一眼规则文件头部SSH 放行规则在不在当前业务端口放行规则在不在执行恢复恢复后立即检查两个点当前 SSH 连接是否还活着、业务关键端口是否正常响应。验证通过后用iptables-save -c /etc/iptables.rules固化当前状态以备后续版本对比和回滚。这套流程多花不了两分钟但能挡住 90% 以上的线上事故。5.3 面试题考点与学习建议很多人准备 Linux 面试时会专门刷“linux面试题测试”相关的题目iptables 几乎是必考内容。和 save/restore 相关的考点通常集中在这几个方向iptables-save与iptables-restore的作用和区别iptables 规则为什么不持久化、如何实现开机自动加载规则文件里*表名、链定义、规则行、COMMIT分别是什么意思默认策略 DROP 和 ACCEPT 的区别规则顺序对匹配结果的影响计数器[packets:bytes]在排障中的作用。我的建议很直接搭一个虚拟机开两个终端一个终端敲iptables命令或者编辑规则文件另一个终端用iptables-save观察变化。将规则文件改来改去、恢复来恢复去折腾几次比背十遍面试题都管用。最后再分享一个我自己的体会大概两年前我在一台线上服务器上整理防火墙规则手快直接把带 DROP 默认策略的规则恢复了上去结果 SSH 瞬间断开。当时没有提前备份旧规则脑子里一片空白。后来是通过云控制台的 VNC 登录进去反手用iptables -F清掉所有规则才救回来的。从那以后我养成了两个习惯第一任何一次iptables-restore之前先花一秒钟把当前规则iptables-save留个档第二备份文件名永远带上时间戳而不是覆盖同名文件。这两条操作加起来不到五秒但关键时候值一台服务器。额外分享一个小技巧如果你管理着多台服务器可以考虑把规则文件按服务器角色-日期的方式命名定期归档。需要回溯某个时间点的规则变更时直接查 Git 历史或备份目录比靠脑子记靠谱太多了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询