直接进入正题。今天想花点篇幅把 firewalld 防火墙 从头到尾聊透。它是 RHEL/CentOS 7 之后系统自带的动态防火墙管理工具,负责管理 Linux 主机上的网络访问规则,解决的是“这台机器哪些端口能对外、哪些来源可以访问、哪些流量必须拒绝”的问题。这篇文章适合刚接触 Linux 运维的新手,也适合那些早就把 firewalld 用熟了、但没系统梳理过机制的从业者。不管你是要在线上的 CentOS 上开端口、配黑白名单,还是在公司内网折腾双网卡策略,这篇都可以直接照着操作。
我先说一个自己的判断:firewalld 经常被低估。很多人觉得它不过是 iptables 的“马甲”,真正出问题的时候还是绕回去用 iptables。但实际上,firewalld 的 zone 模型、动态加载机制、rich rule 语法在真实生产环境里能省下大量维护成本。文章我不想写成一个命令大全,而是把每个选择背后的逻辑讲清楚,这样你遇到没见过的场景时也能推出来该怎么做。
1. 先搞清楚 firewalld 在系统里到底扮演什么角色
1.1 它和 iptables 不是一回事
很多从 CentOS 6 时代过来的人,习惯性以为 firewalld 就是“iptables 换了个写法”,这个误解会带来很糟糕的排障体验。实际上的链路是这样的:Linux 内核里负责过滤网络数据包的那个模块叫 netfilter,它才是真正的执行者。而 iptables 是用户态的一个命令行工具,用来往 netfilter 里写规则的老式管理程序。firewalld 是 RHEL/CentOS 7 之后引入的另一套用户态管理程序,底层同样操作 netfilter,但管理方式和设计思路完全不同。
你可以把 netfilter 想成是一栋大楼的门禁系统,iptables 相当于管理员直接拿钥匙一组一组门锁去开关,而 firewalld 是一套带控制面板的中央管理系统。你不需要关心具体是哪个门锁、哪条链路,只需要告诉系统“这一片区域属于公共区”“这种服务可以放行”,firewalld 会自动帮你把规则落到 netfilter 上。这就是为什么你在 firewalld 里加入规则后,用 iptables -L 也能看到对应条目,但绝不推荐直接用 iptables 去改,因为两套系统对规则的管理视图不一致,混用容易让状态变得难以追踪。
1.2 为什么生产环境值得用 firewalld
核心优势有两个,一个是动态更新不打断连接,另一个是规则组织方式更接近人的思维。
iptables 时代有一个非常让人头疼的问题:你每次修改规则,通常要先把旧的规则清掉,再重新加载全部规则。如果策略文件很大,或者规则之间有关联,操作期间很可能会闪断现有连接。firewalld 不一样,它支持运行时规则和永久规则分离。你可以直接添加一条规则,立即生效,但不会写进配置文件;等确认没问题了再执行 permanent 保存。整个过程不需要重启 firewalld 服务,也不会重载全部规则,已经建立的连接基本不受影响。
再说规则组织。iptables 的做法是五条链(INPUT、OUTPUT、FORWARD 等)加上一堆规则顺序匹配,规则一多,排在前面的规则可能会拦截本来应该放行的流量,排查起来只能一条一条数。firewalld 把主机划分为多个 zone(区域),每个 zone 有自己的信任级别,网卡可以绑定到不同的 zone,不同的区域应用不同的规则。你可以把“外网接口的规则”和“内网接口的规则”物理隔离在不同的管理单元里,互不干扰,也不用担心规则顺序错乱导致误拦截。
2. 必须理解的核心概念:zone、service、runtime 与 permanent
2.1 zone 区域机制是 firewalld 的魂
zone 是 firewalld 最基本的分层单位,不同 zone 代表不同信任程度的网络环境。系统默认自带九个 zone:drop、block、public、external、dmz、work、home、internal、trusted。从名字就能看出信任程度从低到高排列。drop 直接丢弃所有入站流量,trusted 则接受所有流量。一般服务器上默认用的都是 public,它只放行少量必要的服务,比如 SSH。
这里有一个很多新手没注意到的关键点:zone 是针对“网络接口”来生效的,不是针对“IP 地址”来生效的。你的网卡 ens33 绑定了 public 区域,那么从 ens33 进来的流量都按 public 的规则处理。一台机器有双网卡,一张接外网、一张接内网,你可以把外网网卡放到 public,内网网卡放到 internal,这样不需要写任何复杂的地址判断规则,流量自动按来源接口走不同的策略。查看当前绑定情况用 firewall-cmd --get-active-zones,你会看到类似这样的输出:
public interfaces: ens33这个设计的意义在于,它将“网络环境”和“策略”解耦了。以后内网网卡换了 IP,只要接口没变,规则就不用动。想调整策略,只需要修改对应 zone 的规则,不需要关心哪条规则属于哪一个 IP。
2.2 service 服务是一种规则封装
firewalld 预设了一批 service,每个 service 本质上是“一个名字对应一组端口和协议”。比如 ssh 对应 22/tcp,http 对应 80/tcp,https 对应 443/tcp。你不需要记住端口号,也不需要在同一个规则里又写端口又写协议,直接把服务名丢给 firewalld 就行。
这些 service 的配置文件放在 /usr/lib/firewalld/services/ 目录下,每个服务一个 xml 文件。系统默认已经把常见服务准备好了,但有些业务端口没有现成的 service,比如 8080、3306、6379,这时你有两个选择。第一,直接添加端口规则,这个最常用;第二,写入自定义 service 文件,多见于服务业较多的场景,方便以后复用。我个人建议,如果你在一个环境里反复开放同一个非标准端口,值得花 30 秒创建一个自定义 service,配置文件放在 /etc/firewalld/services/ 下,之后每次加入规则只需要 --add-service=myapp,可读性好很多。
2.3 runtime 和 permanent 的区别直接决定配置是否重启后保留
firewalld 的规则存在两套独立的存储里。运行时规则存放在内存中,立即生效,但一旦 firewalld 服务重启,它就没了。永久规则存放在磁盘配置文件里,服务重启后自动加载。所有 firewall-cmd 命令默认只修改运行时,除非你加了 --permanent 参数。
这个机制的好处前面提过,就是可以先不加 permanent 试水,发现规则有副作用,直接 reload 或者重启 firewalld 就回到之前状态。确认没问题了,再保存。注意 reload 操作的行为:它会重新加载永久配置,把运行时规则全部清掉并按永久配置重建。所以如果你只改了运行时规则、没有加 permanent,执行 firewall-cmd --reload 之后这个规则就消失了。很多人在这上面栽过跟头:加了规则当时能用,一 reload 就失效,然后一脸懵。
两条实用经验:第一,如果你确定规则就是要长期使用,干脆命令里直接加 --permanent,然后执行 --reload 让完整规则集重新加载;第二,如果你已经添加了一批运行时规则,想整体保留,不用一条条反写,直接执行 firewall-cmd --runtime-to-permanent 把当前运行时规则整体写入永久配置。
3. 实操:开放端口、放行服务与基础规则管理
3.1 最常用的端口开放命令
假设服务器上跑了一个 Web 服务,监听 8080 端口,现在要让外部能访问。最直接的命令是:
firewall-cmd --add-port=8080/tcp --permanent firewall-cmd --reload执行完以后可以用 firewall-cmd --list-ports 检查,能看到 8080/tcp 在列表里。这里有几个细节值得说明。
第一,端口后面必须跟协议,/tcp 或者 /udp 二选一。如果业务既用 TCP 又用 UDP,你得写两行,比如 DNS 就需要同时放行 53/tcp 和 53/udp。第二,--reload 这步不能省。上面第一条命令加了 --permanent,意味着它已经写进配置文件了,但运行时规则还没有,只有 reload 之后才会合并加载。如果你不加 --permanent,也不 reload,那规则是即时生效的,但重启后消失。回到前面讲的机制,想明白这两套存储,你就不会乱。
如果需要同时添加多个端口,可以写在一个命令里,端口用逗号分隔,比如:
firewall-cmd --add-port=8080/tcp,9090/tcp --permanent但要注意这种方式只适用于同协议。TCP 和 UDP 混在一起时必须分开写。
3.2 添加服务与移除规则的常用姿势
添加服务更简单。以允许 HTTPS 为例:
firewall-cmd --add-service=https --permanent firewall-cmd --reload对应的移除操作就是把 add 换成 remove:
firewall-cmd --remove-service=https --permanent firewall-cmd --reload端口规则同理,--remove-port=8080/tcp 即可。这里我想专门说一个很容易踩的坑:如果端口曾经通过 service 方式开放过,比如你在 service 里给某个自定义服务定义了 8080/tcp,后来你用 --remove-port 去移除,结果是没用的。因为规则的来源是 service,不是端口。你得从 service 层面移除,也就是先看 firewall-cmd --list-services,确认它来自哪个 service,再执行 --remove-service。
我遇到过不止一次这样的情况:生产环境上有同事用 --remove-port=65534/udp 怎么都删不掉,查了半天发现规则其实来自一个自定义 service 文件。所以规则管理的第一原则是:要知道你添加规则时用的哪种“语法糖”,相应的移除也要用同一种。
3.3 临时规则和按时间失效的规则
有些场景下你只希望规则存在一小段时间。比如你做了一次临时调试,希望快速开个端口给同事联调,两小时后自动关闭。这时可以加 --timeout 参数:
firewall-cmd --add-port=4000/tcp --timeout=7200这里的单位是秒,7200 就是两小时。注意 timeout 只作用于运行时规则,一旦超时自动移除,不会写入永久配置。这比记住手动删除规则稳妥多了,适合那种“借你端口用一下”的场景。我不建议把 timeout 用得太多,毕竟每次重开服务或者 reload,运行时规则被清掉,timeout 逻辑也就失效了,容易造成误解。
4. rich rule 语法:白名单、黑名单与复杂条件控制的正确玩法
4.1 为什么 rich rule 比直接加规则更强大
firewalld 基础命令只能做一件事:开放某个端口或服务,对所有来源生效。但在真实环境里,需求往往是“这个端口只允许某个 IP 访问”或者“这个 IP 访问任何端口都拒绝”。这种条件判断就要用 rich rule(富规则)。
rich rule 的语法比基础命令复杂一些,但表达能力也强得多。它支持根据来源 IP、目标端口、协议、服务名做组合匹配,还能指定 accept、drop、reject 三种动作。我建议所有有一定规模的服务器都优先考虑 rich rule,因为它的语义清晰,可读性好,排障的时候一眼能看懂这条规则想干什么。
4.2 白名单场景:SSH 只允许内网网段访问
服务器上 SSH 端口如果暴露在公网上,每天都会被各种扫描。最有效的对策之一就是限制来源 IP。假如你的内网网段是 192.168.1.0/24,只允许这个网段访问 SSH,可以用:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept' firewall-cmd --reload这条规则的意思是:来源地址为 192.168.1.0/24 的流量,如果目标是 ssh 服务,允许通过。这里有一个隐含的细节:firewalld 的规则是叠加式的,public 区域默认允许的 SSH 依然存在,所以这个白名单实际没有把其他来源挡掉。你要真的实现“只允许白名单”,必须先删除默认的 SSH 服务规则,再添加 rich rule:
firewall-cmd --permanent --remove-service=ssh firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept' firewall-cmd --reload顺序非常重要。先移除宽泛规则,再加入精确规则,最终效果才是只有白名单能访问。如果你反着来,先加 rich rule 再 remove-service,中间那一瞬间 SSH 是完全断开的,有把自己锁在门外的风险。所以我建议操作顺序永远是把风险规则提前准备好,确认无误后一次性 reload。
4.3 黑名单场景:封禁恶意来源 IP
对付暴力破解或者恶意扫描,最简单粗暴的做法是直接封掉来源 IP。用 rich rule 实现:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10" drop' firewall-cmd --reloaddrop 和 reject 的区别在这里值得多说一句。drop 是直接丢弃数据包,客户端那边表现为连接超时,它不会知道自己被封了。reject 是主动返回一个拒绝的响应包,客户端立刻就能看到连接被拒绝。从安全角度讲,drop 更好,因为攻击者无法通过响应判断你的防火墙是否存在,扫描策略会被拖慢。从排障角度讲,reject 更友好,因为你可以迅速判断是规则拦截而不是网络不通。
另外提醒一点,如果封禁的 IP 是本机正在使用的出口 IP,或者是你跳板机的 IP,drop 之后你就可能连不上服务器了。操作前一定确认好来源 IP 是自己可信的,否则这条规则就是把自己锁在外面的钥匙。
4.4 rich rule 里动作的执行优先级
firewalld 的规则匹配遵循一个原则:在一个 zone 内部,多种规则同时存在时,以第一个匹配到的规则为准,但注意它的顺序不是简单按添加顺序排的。firewalld 内部对规则有优先级排序,此外,同一个 zone 内,规则的适用范围也会影响匹配结果。实践中最好不要依赖复杂的规则顺序来执行策略,而是采用“白名单优先”的简洁模式:把所有服务默认拒绝,只开放明确允许的规则。这样即便规则顺序有些微差异,也不会造成意外的放行。
5. 端口转发、IP伪装与多网卡场景的配置思路
5.1 开启 masquerade 实现局域网共享上网
如果你的 Linux 服务器充当网关,内网机器要通过它访问外网,就必须开启 IP 伪装(masquerade)。它是 NAT 的一种实现,简单说就是把内网数据包的来源 IP 改写成服务器自己的公网 IP,让外部看到的是服务器在访问。开启方式:
firewall-cmd --permanent --add-masquerade firewall-cmd --reload用 firewall-cmd --query-masquerade 可以确认是否已开启。这里有个常见误区:开启了 masquerade 后,很多人以为所有流量都会自动转发,其实不然。内核的 ip_forward 选项必须打开,否则数据包根本不会在内网和外网接口之间流转。查看状态:
sysctl net.ipv4.ip_forward如果返回 0,需要打开:
sysctl -w net.ipv4.ip_forward=1持久化需要写到 /etc/sysctl.conf 或者 /etc/sysctl.d/ 下,内容就是 net.ipv4.ip_forward = 1。这一句不写的话,重启之后转发能力就没了,NAT 也随之失效。
5.2 端口转发:把外网端口映射到内网主机
端口转发是另一个高频需求。比如你有一台内网机器,IP 是 192.168.1.10,上面跑着 SSH。你想直接从外网通过网关的 2222 端口访问它,可以这样:
firewall-cmd --permanent --add-forward-port=port=2222:proto=tcp:toport=22:toaddr=192.168.1.10 firewall-cmd --reload这里四个参数的含义分别是:port 是网关对外暴露的端口,proto 是协议,toport 是内网机器上的实际端口,toaddr 是内网机器的 IP。注意,这种转发通常需要配合 masquerade 开启,否则内网机器回包时可能找不到正确的路径。我建议在做端口转发之前先把 masquerade 打开,这是最省心的做法。有些教程会说不是所有转发都需要 masquerade,但对新手来说,开启它不会出错,还能规避大部分回包问题。
转发效果可以用 firewall-cmd --list-forward-ports 查看。如果本机运行了 sshd,而且占用了 22 端口,你把外网 2222 转发到内网 22 没有问题,因为监听 2222 的不是本机服务,而是 firewalld 的转发逻辑。
5.3 多网卡多区域:一张外网一张内网的正确配置
前面提到 zone 和网卡绑定,这里展开讲一个典型场景。服务器有两个网卡,ens33 接外网,ens44 接内网。期望的状态是:外网接口只允许 SSH 和 HTTPS,内网接口完全可信。
首先确认当前默认区域,然后把 ens44 绑定到 internal:
nmcli connection modify ens44 connection.zone internal这里用 nmcli 而不是 firewall-cmd 的原因是 NetworkManager 管理接口区域绑定,firewall-cmd 的 --change-interface 只对当前运行时有效,重启后恢复。用 nmcli 修改的是 NetworkManager 的持久配置,重启后依然保留。改完以后 firewalld 会感知到接口变化,你也可以用 firewall-cmd --get-active-zones 看一下结果。
内网接口绑定到 internal 后,默认放行所有流量,外网接口继续留在 public,只开放必要服务。这样你不需要写任何基于 IP 的规则,策略已经按接口天然分好层。后续要限制内网某些来源,只需要调整 internal 区域的 rich rule 即可。
5.4 规则保存与备份的常见操作
永久规则默认存放在 /etc/firewalld/zones/ 目录下,每个区域一个 xml 文件。比如 public 区域的配置文件就是 public.xml。整个目录备份一下,迁移服务器的时候直接拷贝过去就行。这比人肉记录命令要可靠得多。修改 XML 文件后执行 firewall-cmd --reload 即可生效。我习惯在大版本变更前 cp -a /etc/firewalld /etc/firewalld.bak.日期,回滚成本几乎为零。
6. 常见问题与排查技巧实录
6.1 开启防火墙后 ping 不通,是 ICMP 被拦了
“开启防火墙后 ping 不通”几乎是所有新手遇到的第一道坎。现象是防火墙一开,别的机器 ping 这台服务器就超时。原因在于 public 区域默认不响应 ICMP echo-request。这并不是因为某个端口没有开,而是因为 firewalld 把 ICMP 协议当成一种需要显式放行的流量。
如果你确实需要允许外部 ping,最简单的方式是把 ICMP 请求加进允许列表:
firewall-cmd --permanent --add-icmp-block-inversion firewall-cmd --reload这个参数的意思是“反向放行所有没有被显式阻止的 ICMP 类型”。但这里我提醒一句:生产环境对外网开放 ping 其实没必要,ICMP 可能被用作探测手段,超时反而能降低被扫描的优先级。如果是内网监控需要 ping,可以在 internal 区域测试,或者只对监控服务器的 IP 添加 rich rule 放行 ICMP。
6.2 配置了规则却不生效,先检查 runtime 和 permanent
很多人加完规则说“没用”,第一反应是防火墙坏了。实际上 80% 的情况是规则只存在于运行时,没有持久化。因为 firewall-cmd 默认不加 --permanent 就是只对运行时生效,一旦服务重启、机器重启、或者执行了 reload,规则就没了。排查方法很简单:
firewall-cmd --list-all这条命令显示的是当前运行时所有规则。如果这里能看到规则,就说明规则本身没错,问题出在持久化上。重新用 --permanent 添加一遍,然后 --reload 即可。
还有一种情况是你直接编辑了 XML 文件,然后执行 firewall-cmd --reload,结果没生效。这时候要检查 XML 文件是不是放在正确目录、文件名是否和 zone 名一致、文件权限对不对。firewalld 对 XML 文件格式敏感,个别标签大小写不对都会静默跳过。
6.3 firewalld 和 iptables 到底留哪个
在一台 CentOS 7/8 的机器上,firewalld 和 iptables 服务是互斥的。官方设计就是二选一。如果你启动了 firewalld,就不要再去启动 iptables-services 服务,否则规则集管理会混乱。如果你确实习惯了 iptables 的写法,可以停用 firewalld,启用 iptables,但我不建议这么干。我的经验是 firewalld 完全能覆盖 iptables 90% 以上的使用场景,剩下的 10% 用 rich rule 也能兜底。只有涉及内核层的高性能规则、自定义链等特殊场景,才会考虑退回 iptables。
如果你在前一个环境用的是 iptables,切到 firewalld 后最直观的变化是:iptables -L 看到的大量规则没有了,取而代之的是几个 zone 的规则组。这正是 firewalld 的设计目标:不让你操心底层的链结构。别试图在 firewalld 环境里手工维护 iptables 规则,很容易出现两边配置互相覆盖的诡异问题。
6.4 “请检查您的防火墙和端口转发规则”这类报错
这个提示经常出现在各种局域网联机、远程控制、NAS 映射场景中。它本身不是 firewalld 的报错,而是某个应用在检测端口不可达时给出的通用提示。排查思路分成两层:本机防火墙是否放行了对应入站端口;路由器或者网关有没有把对应端口转发到这台机器。本机层面按前面说的 --add-port 放行即可。如果本机防火墙规则正常,那就去看上一级网关的端口映射。很多情况下问题根本不在防火墙,而是服务只监听了 127.0.0.1,外部访问自然进不来。排查步骤是:ss -lntp 看监听地址是不是 0.0.0.0,如果是 127.0.0.1,那就不是防火墙的问题,而是服务自身绑定限制。
6.5 关闭防火墙真的没事吗
热词里反复出现“关闭防火墙”相关的问题,我直接说结论:生产环境不建议关闭 firewalld。关闭意味着这台主机失去了系统层面的入站防护,任何未被业务程序自身过滤的流量都可能直接到达监听端口。不少人觉得反正前面还有硬件防火墙或者云安全组,系统防火墙不重要,这种想法在纵深防御的角度是站不住脚的。一旦前置设备出现配置失误,系统防火墙就是最后一道防线。
如果你确实因为业务兼容性想关,正确的做法不是 systemctl stop firewalld,而是把它配置成最小化放行模式,只放行业务必要的端口。Windows 上很多人习惯用 bat 脚本一键关防火墙,Linux 上千万别这么干。关防火墙省下的那点管理成本,抵不上被扫描攻击带来的风险。我用过的绝大多数被入侵的机器,事后排查都发现防火墙要么被关了,要么规则全放行。防火墙不是业务的对立面,而是业务安全的第一道闸门。
6.6 firewalld 服务启动失败怎么办
有时候 systemctl start firewalld 会失败,常见原因是当前环境变量或者配置文件有语法错误。先用 systemctl status firewalld 看详细错误,再用 firewall-cmd --state 看状态。如果提示 Unit not found,检查是否装了 firewalld 包。如果提示 Job for firewalld.service failed,重点看 /etc/firewalld/zones/ 下的 XML 文件有没有改坏。我自己碰到过一次把 XML 里的 short 标签名写错导致服务起不来的情况,最后用备份文件替换后恢复正常。这里再一次证明定期备份 /etc/firewalld 目录的重要性。
7. 把 firewalld 放进更广的防火墙全景里
7.1 软件防火墙与硬件防火墙的区别
热词里出现了大量企业与硬件防火墙相关的内容,比如 ensp 配置、锐捷、西门子设置、旁挂、双机热备等等。这里有必要理清边界。firewalld 是运行在 Linux 主机内的软件防火墙,它只保护所在的那一台主机。而 ensp 里配置的、或者锐捷和西门子那类设备,本质上是硬件防火墙,它们是独立工作的安全设备,部署在网络节点上,保护的是整个网段。两者解决的问题不同,策略配置思路也不同。学网络设备的人经常在 ensp 里练习防火墙的 Web 登录、旁挂、双机热备,这些都是硬件防火墙的范畴,和 Linux 的 firewalld 没有直接关系。
我见过不少新人把 ensp 里学到的“安全区域”“策略”直接套到 firewalld 上,发现命令完全对不上,就以为 firewalld 很复杂。其实不是复杂,是两个体系。firewalld 的 zone 和硬件防火墙的安全域概念有一点相似,但实现方式和支持的规则类型差异很大。建议学习路径是:先把 firewalld 这种软件防火墙吃透,再去理解硬件防火墙的策略路由、虚拟化、高可用性,层层递进更顺畅。
7.2 双机热备、IPS/WAF 自动切换不是 firewalld 的功能
热词里还有一个高频话题:各种故障情况下防火墙 IPS WAF 自动切换。这里说的是硬件防火墙的高可用性方案。两台设备一组,主设备故障时备设备接管流量,实现业务不中断。firewalld 本身没有这种能力,它只是单机上的规则管理工具。如果你想在 Linux 层面实现类似的高可用,通常要用 keepalived 或 corosync 这类工具来监测服务和 IP 漂移,firewalld 只负责规则部分。别指望 firewalld 自带双机热备,那超出了它的设计目标。
不过,如果你的业务跑在 Linux 上,可以借鉴硬件防火墙“配置一致”的思想:两台服务器的 /etc/firewalld 保持同步,配合 keepalived 做主备切换,切换过去后防火墙规则天然一致,不会因为节点不同出现策略差别。这个方案在我的生产环境里验证过多次,效果很稳。
8. 安全习惯与长期维护建议
8.1 最小化放行原则
给服务器开放端口时,时刻问自己一个问题:这个端口真的需要暴露给所有人吗。数据库端口(3306、5432)默认应该只允许内网网段访问,Redis 端口(6379)甚至不该对非本机开放。用 rich rule 把来源限制到具体网段,成本很低,收益很高。我的习惯是,每开放一个端口,同时就写一条限制来源的规则。你可以看到,这样做之后,即使被扫描到,攻击者也无法直接从外部访问。
8.2 定期检查与日志审计
firewalld 的日志默认记录在系统日志里。想确认规则有没有生效,可以查看 /var/log/messages 里与 firewalld 相关的记录。更实用的是,配合系统日志把内网流量和外网流量区分开,看看有没有异常的来源 IP 在试探端口。我不主张每天都看日志,但每隔一段时间做一次防火墙配置 review 是必要的:清理不再使用的端口规则,确认没有遗留测试用的临时规则,检查是否有富规则写得过于宽松。维护防火墙和给代码做 code review 是一个道理,不定期清理,规则就会越积越多,最终没人说得清哪些规则在起作用。
8.3 把防火墙规则纳入版本管理
如果你管理的服务器数量上来了,手动一台一台敲命令非常容易遗漏。我的建议是把每个 zone 对应的 XML 配置纳入版本管理,服务器配置变更走 review 流程。这样做的好处是你可以随时知道某台服务器的防火墙是什么状态,出问题的时候可以基于 diff 快速回滚。这是从“能用”到“好用”的分水岭。
8.4 最后的实操体会
我在实际项目中见过太多因为防火墙配置不当导致的故障。有时候是端口没开,有时候是规则没持久化,有时候是直接在 iptables 和 firewalld 之间反复横跳把系统搞乱了。firewalld 本身并不难,难的是建立一套规范:明确每个 zone 的边界,统一使用 rich rule 做精细控制,定期备份和审视配置。如果你能从现在开始把这几条做到,防火墙对你来说就不再是“偶尔打开添条规则的麻烦工具”,而是整个服务器安全体系中一块非常踏实的基石。