云服务器本地防火墙别只靠安全组:用 firewalld 只放行 22/80/443 端口
很多云服务器只在安全组里放行了端口,就以为已经够安全了。其实安全组是云平台那一层的门,系统里还有一道门:本地防火墙。两道门配合,才不容易因为一次误操作就把服务暴露给全网。本文用 firewalld 做一次最小放行:只留 22、80、443,其余端口默认不放行。
一、为什么还要开本地防火墙
安全组放行 22 端口后,全网都能尝试连接这台服务器的 SSH;如果再有人在服务器上起了一个临时服务、装了一个带 Web 界面的组件,安全组里放行的端口范围又比较宽,它可能直接就对外可达了。本地防火墙的作用就是收紧最后一道口子:哪怕安全组放得宽,系统层面也只放行明确需要的服务。
反过来也一样:只开本地防火墙、不配安全组,流量在云平台那一层就被拦住了,服务同样不通。所以正确姿势是两层都配、两层都只放行需要的端口。
二、先确认 firewalld 的状态
在华为云 ECS(以 CentOS / EulerOS / Rocky 这类使用 firewalld 的系统为例)上,先看服务是否在运行:
systemctl status firewalld
firewall-cmd --state
firewall-cmd --get-default-zone
firewall-cmd --list-all
如果显示 running,说明已启用;如果显示 not running,先启动并设为开机自启:
systemctl start firewalld
systemctl enable firewalld
--list-all 的输出里要重点看两项:当前 zone(默认一般是 public)和已放行的 services / ports。做改动前先看一眼现状,改完再对照一次,这是最不容易出错的办法。
三、只放行 22、80、443
SSH、HTTP、HTTPS 在 firewalld 里都有现成的 service 定义,直接按服务名放行比记端口号更不容易错:
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
firewall-cmd --list-all
这几条命令对应 22、80、443 端口。--permanent 表示写入永久配置,--reload 让它立即生效;只加 --permanent 不 reload,规则当时是不生效的;只加临时规则不加 --permanent,重启后就丢了。改完用 --list-all 确认 services 里出现了 ssh http https。
如果你的服务不在标准端口上,例如 Web 服务在 8080 端口,就按端口放行:
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
四、三个最容易把自己锁在外面的操作
第一,千万不要先执行 --remove-service=ssh 再加别的规则。SSH 一关,当前连接断开后就连不回来了。改规则前,先确认当前 SSH 会话正常,并且手头有云控制台的 VNC / 远程登录作为兜底。
第二,改 SSH 端口时顺序不能反。先放行新端口,再关 22 端口:
firewall-cmd --permanent --add-port=2222/tcp
firewall-cmd --reload
# 确认能用 2222 登录后,再移除 ssh 服务放行
firewall-cmd --permanent --remove-service=ssh
firewall-cmd --reload
第三,改完记得同时检查安全组。本地放行了 443,但安全组没放行 443,浏览器还是打不开;反过来安全组放行了,本地没放行,同样不通。两层都要通,服务才通。
五、临时放行:给调试留一个有时限的口子
排查问题时偶尔需要临时开一个端口,例如临时放行 8080 一小时,用带 --timeout 的临时规则,到期自动收回,不用事后惦记着关:
firewall-cmd --add-port=8080/tcp --timeout=3600
firewall-cmd --list-all
不带 --permanent 的规则就是临时的,--timeout=3600 表示 3600 秒后失效。调试结束也可以手动收回:
firewall-cmd --remove-port=8080/tcp
六、想再收紧一点:只允许指定 IP 连 SSH
如果管理服务器的出口 IP 是固定的,可以用富规则只允许这个 IP 访问 SSH,其他 IP 连 22 端口都会被挡住:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" service name="ssh" accept'
firewall-cmd --reload
firewall-cmd --list-rich-rules
注意把 203.0.113.10 换成你自己的出口 IP,执行前务必确认这个 IP 没错,否则等于把自己挡在外面。多人运维、出口 IP 不固定时不要用这一招,改用密钥登录加 fail2ban 这类组合更合适。
七、改完怎么验证
不要只看 --list-all,要从另一台机器实际测一次:
# 在另一台机器上测端口是否可达
curl -I http://服务器公网IP
curl -I https://服务器公网IP
ss -tlnp | grep -E ':22|:80|:443'
再看一条不该放行的端口,例如 3306、6379 这类数据库端口,从外网应该连不上;如果连得上,说明放行范围还是太宽,要回头查 --list-all 和安全组。出了问题就看日志:
journalctl -u firewalld --since "1 hour ago"
firewall-cmd --list-all
八、常见坑
- 只加了
--permanent,忘了--reload,规则没生效。 - 网卡绑到了别的 zone 上,规则加到了 public,却对实际网卡不起作用,先用
firewall-cmd --get-active-zones确认。 - 装了 Docker 后发现规则“失效”了:Docker 会改 iptables 转发规则,容器端口映射可能绕过 firewalld 的部分限制,生产环境要单独核对容器端口映射。
- 把 firewalld 和 iptables 服务混用,两套规则互相打架,选一套统一管理。
小结
安全组管云平台那一层,firewalld 管系统这一层。最小放行的顺序是:先看现状 --list-all,再用 --permanent 加 ssh/http/https,--reload 生效,另一台机器实测验证,临时端口用 --timeout 自动收回。端口越少,暴露面越小;规则越明确,半夜被扫描器扫到弱服务的概率就越低。
- 点赞
- 收藏
- 关注作者
评论(0)