☰
CentOS7 Firewalld批量放行端口:配置文件与命令行实战全解析
2026/10/23 1:04:48 网站建设 项目流程

1. 批量放行背后的真实场景

说实话,大部分人对防火墙的认知停留在"装个图形界面、点几下按钮"的阶段,一旦遇到线上服务器就不敢动了。我最早接手某公司的测试环境时,接到一个需求:把内外网交互需要的端口一次性放行,涉及节点十几个,端口少说三四十个。刚开始我也是一台一台敲命令,后来发现纯粹是给自己挖坑——敲错一个端口、记错一个区间,排查起来比写规则本身更痛苦。

CentOS7 默认的防火墙是 Firewalld,它的规则配置方式比传统的 iptables 要"动态"不少,配置文件也更有规律。但规律不等于简单,尤其是当你需要批量操作的时候,文件内容的结构、加载顺序、优先级这些细节全都会冒出来。这篇博文我会从配置文件入手,讲清楚批量放行端口的几种实操方法,也会把踩过的坑一并交代。

这篇文章适合谁看?需要运维服务器的人、刚接触 CentOS7 防火墙的开发者、还有那些已经用了 Firewalld 但一直靠敲命令续命、从来没认真读过配置文件的人。读完你至少能回答这几个问题:Firewalld 配置文件到底怎么组织?批量放行有哪些靠谱手段?为什么有时候规则写了却不生效?

2. Firewalld 的配置文件,到底长什么样

2.1 核心配置目录和文件定位

Firewalld 的配置分两种:一种是运行时配置,修改后立即生效,但机器重启就丢;另一种是持久化配置,写入到磁盘文件里,重启后依然保留。持久化配置默认放在/etc/firewalld/目录下。

这个目录下面常见的子目录有:

  • zones:存放区域配置文件,每个文件对应一个 zone,默认的 public.xml 就在这里面。
  • services:存放服务定义文件,比如 http.xml、https.xml。
  • icmptypes:ICMP 类型定义,一般不需要动。
  • rules:这是新版 Firewalld 提供的富规则目录,标准命名是zone-<区域>.xml。

如果你机器上没找到/etc/firewalld目录,先确认一下 Firewalld 是否安装并启动,很多时候是服务没装,自然没有配置目录。

注意:修改持久化配置文件之前,建议先执行firewall-cmd --state确认当前防火墙状态,再操作。不要在各个配置文件之间来回跳着改,改完不知道哪份是准的,很容易把线上环境搞乱。

2.2 public.xml 的典型结构

public.xml 是 public 区域的配置文件,默认情况下,这是大多数人接入外网的网卡所在区域。看一个典型示例:

<?xml version="1.0" encoding="utf-8"?> <zone target="default"> <short>Public</short> <description>Unsolicited inbound traffic is not allowed.</description> <service name="ssh"/> <port port="80" protocol="tcp"/> <port port="443" protocol="tcp"/> </zone>

这个文件结构不复杂,<service>代表放行某个预定义服务,<port>代表放行某个端口和协议。Firewalld 在启动或者 reload 的时候会读取这些文件,把规则加载进内核。

你要是把配置写错了,比如 protocol 写成了tcp/udp,实际加载就会出问题。协议字段只接受单个协议名称,正确的做法是用两个<port>分别写。

2.3 运行时配置和持久化配置的区别

这个必须说清楚,因为很多人会在这里栽跟头。

运行时配置保存在内存里,firewall-cmd --add-port=8080/tcp这种命令修改的就是运行时配置,立即生效,但不会写进磁盘文件。firewall-cmd --permanent --add-port=8080/tcp才是写入持久化配置的写法。

如果你只用了--permanent而没有 reload,那么内存里仍然没有新规则,看起来就是"规则写了但不生效"。反过来,如果你只用了不带--permanent的命令,规则倒是立即生效了,机器一重启,规则就灰飞烟灭。

批量操作场景下,推荐的做法是全部带上--permanent,最后执行一次重载或者运行时重新加载,让所有规则一次性落地。

3. 批量放行端口的核心思路

3.1 两种批量配置思路的对比

批量放行端口,本质上就是两条路:一是通过命令行循环执行;二是直接改配置文件。

命令行循环适合临时快速放行,配置文件适合需要长期保留、批量部署的场景。二者没有绝对的优劣,关键是看你的使用场景。

如果只是五六台机器、二三十个端口,用命令行循环完全够用,而且执行完了可以用firewall-cmd --list-all验证。如果是几十台机器、上百个端口,逐个敲命令很容易出错,而且每台机器执行一遍,时间成本也不低。这时候直接操作配置文件的优势就出来了:把一份写好的 public.xml 分发到各台机器,reload 一次全部生效。

3.2 为什么推荐用配置文件方式做批量

我的经验是,端口数量越多、机器数量越多,配置文件方式越靠谱。原因很简单:

  • 配置文件可以被版本管理工具追踪,改了什么一目了然。
  • 分发和备份都很方便,复制一份文件就能复现规则。
  • 出问题的时候,打开文件就能看到规则的全貌,不用执行一堆命令去猜测当前状态。
  • 命令行方式在循环里写错一个变量或者跑偏一个区间,排查起来比较痛苦。

当然,配置文件方式也有学习成本,至少得知道 XML 的基本结构,但这也是熟能生巧的事。

4. 批量放行端口的四种实操方法

4.1 方法一:命令行循环批量放行

最直接的做法是写一个简单的 Shell 循环。假设我们要放行 8000 到 8020 的 TCP 端口:

for port in $(seq 8000 8020); do firewall-cmd --permanent --add-port=${port}/tcp done firewall-cmd --reload

这个命令的意思是用seq生成 8000 到 8020 的数字序列,逐个执行--add-port,最后统一重载。执行完可以用firewall-cmd --list-ports查看是否全部生效。

如果你要放的端口不是连续区间,而是不规则的一组,可以把端口写进一个文件,然后按行读取:

cat /root/open_ports.txt # 8080/tcp # 9090/udp # 3306/tcp while read port; do firewall-cmd --permanent --add-port=${port} done < /root/open_ports.txt firewall-cmd --reload

这里有一个小细节要注意:--add-port后面必须带协议,8080/tcp和8080/udp是两个不同的条目,不要以为只写端口号就够了。

实操心得:如果你的端口清单里有重复项,循环执行并不会报错,但会给后续排查带来干扰,建议先用sort -u去重一下。

4.2 方法二:直接编辑 public.xml 文件

如果喜欢"所见即所得"的配置方式,可以手动编辑/etc/firewalld/zones/public.xml。比如要放行多个端口,直接在<zone>节点里加入<port>子节点:

<zone target="default"> <short>Public</short> <description>Unsolicited inbound traffic is not allowed.</description> <service name="ssh"/> <port port="8080" protocol="tcp"/> <port port="8081" protocol="tcp"/> <port port="9090" protocol="udp"/> </zone>

改完之后执行:

firewall-cmd --reload

这里有一个关键点:/etc/firewalld/zones/目录下的文件如果不存在,你可以从默认配置复制一份过来,或者直接新建一个同名文件。默认区域文件的模板在/usr/lib/firewalld/zones/下面。

我个人的习惯是先复制默认文件过来再编辑,这样不会因为漏写基础属性导致加载异常。

4.3 方法三:使用富规则进行批量放行

富规则(Rich Rule)是 Firewalld 提供的一种更精细的规则表达方式,支持来源地址、端口范围、协议组合等。举一个例子,放行来自内网网段访问 TCP 1000-2000 端口的流量:

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="1000-2000" protocol="tcp" accept' firewall-cmd --reload

富规则还可以写进配置文件:

<zone target="default"> <short>Public</short> <description>Unsolicited inbound traffic is not allowed.</description> <service name="ssh"/> <rule family="ipv4"> <source address="192.168.1.0/24"/> <port port="1000-2000" protocol="tcp"/> <accept/> </rule> </zone>

批量场景下,富规则主要有两个优势:一是可以减少规则条数,比如一个端口范围覆盖几十个端口;二是可以加入来源地址限制,让规则更安全,而不是对所有来源完全开放。

4.4 方法四:通过端口范围快速放行

Firewalld 的<port>节点其实支持写成端口范围,<port port="1000-2000" protocol="tcp"/>代表放行从 1000 到 2000 的所有 TCP 端口。

命令行也有对应的写法:

firewall-cmd --permanent --add-port=1000-2000/tcp firewall-cmd --reload

需要留心的是,端口范围在--list-ports的输出里会以1000-2000/tcp的形式显示,不要把它当成单个端口。

批量放行连续端口区间时,范围写法能极大减少规则条数。但如果端口范围较宽,建议先想清楚是否真的有这个需求,因为端口放得越开,被扫描和利用的风险越大。

4. 完整实操示例:从规划到落地

4.1 需求规划

以我实际处理过的场景为例:某测试环境需要对外开放一组服务端口,包括 Web 服务 8080-8085、调试端口 9090(UDP)、数据库端口 3306,同时只允许来自内部管理网段的 SSH 访问,其余来源一律拒绝。机器上已经装好了 CentOS7,Firewalld 默认开启。

4.2 操作步骤

第一步,确认当前状态:

systemctl status firewalld firewall-cmd --state

第二步,规划配置内容,先备份现有配置:

cp -r /etc/firewalld /etc/firewalld.bak.$(date +%Y%m%d)

第三步,编写新的 public.xml。我推荐用富规则实现来源 IP 的限制,普通端口用<port>节点实现:

<zone target="default"> <short>Public</short> <description>Unsolicited inbound traffic is not allowed.</description> <service name="ssh"/> <port port="8080-8085" protocol="tcp"/> <port port="3306" protocol="tcp"/> <port port="9090" protocol="udp"/> <rule family="ipv4"> <source address="10.20.30.0/24"/> <service name="ssh"/> <accept/> </rule> <rule family="ipv4"> <source address="0.0.0.0/0"/> <service name="ssh"/> <drop/> </rule> </zone>

这里要注意两个富规则的顺序:先放行内网网段 SSH,再丢弃其他来源的 SSH,规则的匹配顺序是先到先得,上面的规则优先命中。

第四步,加载配置:

firewall-cmd --reload firewall-cmd --list-all

4.3 验证放行是否生效

验证端口放行是否成功,不能只看配置,还应该从外部发起真实连接。比如用另一台机器执行:

nc -zv <服务器IP> 8080

如果通了,返回 Connected;如果不通,检查中间是否有其他防火墙拦截,以及目标机器上的规则是否真的写入。还有一个常见问题是云厂商的安全组,即使本机放行了,安全组没放行,端口依然不通。这个不在 Firewalld 的管辖范围内,但排查的时候一定要想到。

5. 常见问题与排查技巧

5.1 规则已写入但端口不通

这种情况大概率出在三个方面:

  • 规则写进了配置文件,但没有执行 reload,当前运行时配置里根本没有新规则。解决办法是执行firewall-cmd --reload。
  • 端口放行的协议不对。比如服务跑的是 TCP,你放行的却是 UDP。
  • 服务绑定地址不对。服务只监听了 127.0.0.1,外部网络自然连不上,这不是防火墙的问题,但排查顺序里一定要考虑。

5.2 reload 和完全重启的差异

firewall-cmd --reload会保留当前运行时规则,只是重新加载持久化配置。systemctl restart firewalld则是完全重启服务,所有运行时规则都会丢失,重新从配置文件加载。

批量修改配置后的常规操作是firewall-cmd --reload,不建议直接 restart,因为 restart 会瞬间断开所有已建立的连接,对线上影响比较大。

5.3 端口范围写法的坑

<port port="8080-8085" protocol="tcp"/>这种写法在配置文件里是合法的,但如果你使用firewall-cmd --add-port=8080-8085/tcp命令,得到的效果和配置文件写法相同。二者不要混用时产生误解。

还有一个容易踩的坑:命令行工具的补全或者引号问题。在 Shell 里如果端口区间写成8080-8085/tcp,没问题;但如果你漏了协议后缀,命令会直接报错:

Error: INVALID_PORT: Bad port (and/or protocol)

5.4 配置文件权限错误导致加载失败

如果你是从其他地方复制来的 public.xml,复制后文件属主和权限可能不对。Firewalld 正常要求配置文件属主是 root,权限至少是 644。如果权限过严,服务可能读不了;如果权限过宽,会有安全风险。检查方法:

ls -l /etc/firewalld/zones/public.xml

如果不是 root 所有,执行修正:

chown root:root /etc/firewalld/zones/public.xml chmod 644 /etc/firewalld/zones/public.xml

5.5 常见问题速查表

问题现象可能原因检查/解决方式
规则写了但端口不通未 reload执行firewall-cmd --reload
端口通但来源不受限制规则里没有来源限制改用富规则并指定 source address
重启后规则丢失用了运行时配置没加 --permanent改用--permanent写入持久化配置
reload 后服务连接受影响不该用 restart 却用了 restart尽量用 reload,必要时分批次操作
配置文件报错权限、属主错误或 XML 结构错误修正权限、检查 XML 标签闭合

6. 批量操作中的避坑经验

批量操作最怕的不是规则复杂,而是"改完不知道改了什么"。我见过有人一次性批量放行了 20 个端口,然后其中一个写错协议,排查了几个小时才定位到问题。

建议在批量操作前,先把端口清单整理成表格,包含端口号、协议、用途、目标来源,再决定用哪种方式落地。如果端口是连续区间,直接用范围写法;如果端口是零散的一组,建议写进文件循环执行;如果想做来源限制,优先考虑富规则。

这里也有一个经验:规则不要追求"一次全写完",而是分模块写。先把基础放行端口写好,再写来源限制,最后再加拒绝规则。每写一个模块,做一次验证,这样即使出问题,也能快速定位到是哪一类规则引起的。

另一个容易忽略的点是:/etc/firewalld/zones/下可能有多个 zone 配置文件,比如public.xml、internal.xml。很多服务器有多个网卡,每个网卡可以绑定到不同 zone。如果你改了 public.xml,但是实际流量从 internal 区域进入,那么你的规则根本没有作用到对应的网卡流量上。检查网卡和区域的绑定关系:

firewall-cmd --get-active-zones

这个命令会显示每个活跃 zone 绑定了哪些网卡或来源。确认当前服务所在的网卡绑定的区域,再决定改哪个配置文件。

7. 把批量操作变得更可靠的一些小技巧

如果你需要频繁批量调整端口,比如每周都在测试环境上加临时端口,重复写 XML 或者循环命令确实有一点枯燥。我后来做了个小优化:把端口清单写在文本文件里,用一段简单的脚本批量生成 XML 片段,再手动粘贴到 public.xml 中。

虽然手动拼 XML 也不是完全自动化,但至少避免了命令循环里逐条执行带来的耗时。你也可以用脚本把新规则追加到 XML 中,但要注意 XML 标签闭合的问题,所以更稳妥的做法是生成片段后人工确认再粘贴。

还有一个建议:每次改动 Firewalld 配置之前,至少做好两件事——备份配置文件、记录当前端口放行清单。当前清单可以通过一条命令导出:

firewall-cmd --list-all > /tmp/firewalld_list_$(date +%Y%m%d).txt

这样一旦回滚,就知道最初的规则是什么状态。

8. 最后想说的话

Firewalld 的配置文件批量放行端口,本质上不难,难的是在操作之前把思路理清楚。你是想临时开几个端口,还是一套长期规则要部署到多台机器?想清楚这个问题,方法自然就出来了。

我个人在实际操作中的体会是,不要惧怕命令行循环,也不要一味依赖图形工具。命令行方式看似原始,但在批量场景下反而是最灵活、错误率最低的路径。配置文件方式则需要你对 XML 结构有一定掌控力,而这份掌控力其实来自多次踩坑之后的积累。

最后再分享一个小技巧:如果你经常在 CentOS7 上做防火墙调整,建议把常用的端口清单、网段信息整理成一份文档,放在服务器上或者内部笔记里。下次需要放行端口的时候,直接对照文档操作,比自己临时回忆要快得多,也不容易遗漏。希望这篇内容对你有帮助。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询