基本操作
$ sudo firewall-cmd --state # 防火墙开着没
running
$ sudo firewall-cmd --list-all # 当前放行了什么 ← 最常用
public (active)
interfaces: enp0s5
services: dhcpv6-client ssh
ports:
...
# 按「服务名」放行(推荐,firewalld 知道 http 就是 80)
$ sudo firewall-cmd --add-service=http --permanent
# 按「端口」放行
$ sudo firewall-cmd --add-port=8080/tcp --permanent
# 必须 reload 才生效!
$ sudo firewall-cmd --reload
--permanent 和 --reload
- 不加 --permanent
- 立刻生效,但重启后消失。改的是"运行时"配置。
- 加了 --permanent
- 写进配置文件永久保存,但当下不生效。改的是"永久"配置。
- 加了 --permanent 但忘了 reload
- 最常见的坑:你以为放行了,实际当下还是不通,要等下次重启才生效。
- 正确做法
--permanent改完,紧跟一条--reload。两条要当成一条来记。
不确定规则对不对时,先不加 --permanent 试一次——万一配错把自己 SSH 关在外面了,重启机器就恢复了。
确认规则没问题,再加 --permanent 正式写进去。这个习惯救过很多远程运维的命。
zone 是什么
firewalld 把网卡分到不同的「区域」,每个区域一套规则。默认都在 public 区,日常运维基本不用动它。
$ firewall-cmd --get-default-zone
public
$ firewall-cmd --get-active-zones
public
interfaces: enp0s5
常见的几个:public(默认,不信任)、trusted(全放行)、internal(内网)。面试时能说出"firewalld 是基于 zone 的,默认 public"就够了。
那道标准面试题
「服务在本机 curl 得通,从别的机器就是访问不了。」
这题几乎每个运维面试都会问。标准答案是三层,而且要按顺序说。
- 第一层 · 服务监听地址
sudo ss -tunlp | grep 端口——确认监听的是0.0.0.0而不是127.0.0.1。是 127.0.0.1 的话,外面永远连不上,改服务配置即可,跟防火墙无关。(昨天学的)- 第二层 · 系统防火墙
sudo firewall-cmd --list-all——看这个端口/服务在不在放行列表里。不在就--add-port加上,别忘了--reload。- 第三层 · 云平台安全组
- 阿里云、腾讯云、AWS 都有自己的安全组,那是在你机器之外的一层防火墙。系统里全放开了也可能被它拦住。
大部分候选人只会答"看防火墙"。能一口气说出三层、并且说清楚每层怎么查,说明你真在生产环境排过这个问题。
顺序也重要:从最靠近服务的一层开始查,比东一榔头西一棒子高效得多。
动手验证一遍
# 在虚拟机上确认 nginx 在跑、监听 0.0.0.0
$ sudo ss -tunlp | grep :80
$ curl -I http://127.0.0.1 # 本机通 → 200 OK
# 确认防火墙没放行 http
$ sudo firewall-cmd --list-all | grep services
# 在你 Mac 的终端里
$ curl -m 5 -I http://虚拟机IP
curl: (28) Connection timed out
↑ 超时,典型的被防火墙拦掉的表现
# 回到虚拟机
$ sudo firewall-cmd --add-service=http --permanent
$ sudo firewall-cmd --reload
# 再从 Mac 上访问
$ curl -I http://虚拟机IP
HTTP/1.1 200 OK
Connection refused(立刻拒绝)→ 端口是通的,但没有程序在监听。服务没起来。
Connection timed out(等半天没反应)→ 包被防火墙丢掉了。防火墙或安全组的问题。
能凭这两种报错分辨方向,排查速度快一倍。
几个实用补充
$ sudo firewall-cmd --remove-service=http --permanent
$ sudo firewall-cmd --reload
# 临时停掉防火墙(排障时用来快速确认是不是它的问题)
$ sudo systemctl stop firewalld
# 测完记得起回来!
$ sudo systemctl start firewalld
临时 stop 来定位问题是可以的,但不能作为解决方案。
正确说法:「我会临时停一下确认是不是防火墙的问题,确认了就精确放行对应端口,然后把防火墙起回来。」
今天的面试点
「我分三层查:」
「一是 ss -tunlp 看服务监听的是 0.0.0.0 还是 127.0.0.1——如果是后者,外面永远连不上,得改服务配置。」
「二是 firewall-cmd --list-all 看防火墙放行没,注意 --permanent 之后要 --reload。」
「三是云平台的安全组,那层在系统之外,本地全放开也可能被它拦。」
「refused 说明包到了,但没有程序监听那个端口——服务没起来。timeout 说明包被中途丢了——防火墙或安全组拦的。」
这题能答对,排查方向立刻就对了。
今天的练习
sudo firewall-cmd --state和--list-all,看当前放行了什么- 完整走一遍上面的三步实验:本机 curl 通 → Mac 上 curl 超时 → 放行后 Mac 上通
- 体会
--permanent忘了--reload的效果:加规则后先别 reload,立刻--list-all看变没变 - 练一次移除:
--remove-service=http --permanent然后--reload,再从 Mac 测(应该又不通了) - 最后把 http 重新放行回来
- 说出声:把三层排查法完整讲一遍,就当在面试
Day 19 讲 SELinux——红帽系的特色,Ubuntu 出身的候选人答不上来的题。
今天的三层排查还漏了一种情况:监听对了、防火墙也放行了,就是访问不了。那多半就是 SELinux 在拦。