防火墙从入门到会配:firewalld、iptables 与云安全组
运维学习路线系列 · 阶段二 系统进阶 · 第 3 篇
适用环境:Ubuntu 24.04 LTS(ufw/iptables)+ CentOS Stream 9(firewalld)+ 公有云安全组
阅读前提:《S2-01》《S2-02》
前言:"安全组我明明放行了!"
新人部署完 Web 服务,从公司电脑死活 curl 不通,在群里喊"安全组我明明放行了!"。老运维上机器跑了两条命令:
bash
ss -lntp | grep :8080 # 服务监听 0.0.0.0 ✅
sudo ufw status verbose # ufw active,8080 不在放行列表 ❌
端到端的"通",要过至少三层门:云安全组 → 机器防火墙 → 服务监听地址。少放一层都进不来。这篇把这三层的职责、工具、排查顺序一次讲透,最后给出"新服务上线"的标准放行流程。
一、三层门:先分清谁管什么
| 层 | 位置 | 控制粒度 | 工具 |
|---|---|---|---|
| ① 云安全组 | 云平台虚拟防火墙(机器外) | 实例级、CIDR+端口 | 控制台/CLI |
| ② 系统防火墙 | 机器内核 netfilter | 端口/协议/源地址 | ufw / firewalld / iptables |
| ③ 服务自身 | 应用配置 | 监听地址、认证 | bind-address / allow 列表 |
排查顺序 = 数据包的行进顺序:① 安全组 → ② 系统防火墙 → ③ 监听地址。任何一层"默认拒绝",后面全白搭。
💡 内核里真正的防火墙只有一套:netfilter。iptables / nftables / ufw / firewalld 全是往 netfilter 写规则的前端工具------理解这一点,就知道为什么"ufw 和 firewalld 别混用"(两套前端同时写规则,排查地狱)。
二、ufw:Ubuntu 的第一选择
bash
sudo ufw status verbose # 状态 + 默认策略 + 现有规则(排错第一步)
sudo ufw allow 8080/tcp # 放行端口
sudo ufw allow from 192.168.1.0/24 to any port 3306 # 只许内网段访问 MySQL(生产标准姿势)
sudo ufw deny 23/tcp # 显式拒绝
sudo ufw delete allow 8080/tcp # 删规则
sudo ufw enable # 启用(首次会警告确认,SSH 会话别断!)
sudo ufw logging medium # 开日志 → /var/log/ufw*
三条生产建议:
- 默认策略保持 deny incoming / allow outgoing(默认就是,别乱改);
- 对外只开 80/443/SSH,数据库、Redis 等一律"只允许内网段"或干脆不对外;
- 改 SSH 相关规则前先验证当前会话不受影响(放行 22 再改端口,顺序反了就机房见)。
三、firewalld:CentOS 系的标准
firewalld 用"zone(区域)+ service(服务)"的抽象,把规则按网络环境分组(public 内网/外网、trusted 信任等):
bash
firewall-cmd --state # 状态
firewall-cmd --get-default-zone # 默认区域(一般是 public)
firewall-cmd --list-all # 当前区域全部规则
firewall-cmd --permanent --add-service=https # 放行 https(--permanent 持久化)
firewall-cmd --permanent --add-port=8080/tcp # 放行裸端口
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.1.0/24 port port=3306 protocol=tcp accept'
firewall-cmd --reload # 🌟 permanent 规则必须 reload 才生效
🚨 firewalld 最大的坑:--permanent 加了但忘了 --reload ------运行时规则(不带 permanent)立即生效但重启消失;permanent 规则 reload 才生效。排错时先 --list-all(运行时)再 --list-all --permanent(持久)两边对照。
四、iptables:所有前端的"底层语言"
ufw/firewalld 出问题或 K8s(它的 SERVICE/NAT 就是 iptables/ipvs 规则)场景下,你必须能直接读 netfilter:
4.1 四表五链(背这个框架就够)
表(优先级):raw → mangle → nat → filter(最常用)
链(报文行进的检查点):
PREROUTING → (路由判断) → FORWARD(转发)
└→ INPUT(进本机)→ 本机进程
本机进程 → OUTPUT → POSTROUTING
- filter 表:放行/拒绝(INPUT 入站、OUTPUT 出站、FORWARD 转发);
- nat 表:地址转换(DOCKER 的端口映射、K8s 的 Service 全在这)。
4.2 排错三连
bash
sudo iptables -L INPUT -n --line-numbers | head -20 # 看入站规则(带序号)
sudo iptables -L -n -t nat | head -30 # 看端口映射(docker run -p 生成在这)
sudo iptables -L -nv | head # -v 看每条规则的包计数(哪条在被命中?)
读规则要点:从上往下匹配,命中即停 。REJECT 是"礼貌拒绝"(回 RST,tcpdump 能看到),DROP 是"石沉大海"(客户端表现为超时)------"对方到底是拒绝还是丢包"这个千古之问,iptables 的 DROP/REJECT 就是答案分界。
五、云安全组:最容易踩的第一层
特点:有状态 (你主动出站的回包自动放行)、默认拒绝入站、规则在实例外生效(机器上看不到)。
典型坑:
| 坑 | 现象 | 解法 |
|---|---|---|
| 只放行 TCP 没放来源 | 全网可访问你的 3306 | 来源写公司出口 IP/内网段,不给 0.0.0.0/0 |
| 内网互访没放安全组 | 同 VPC 两台机器也不通 | 跨安全组要互相放行(或并入同一安全组) |
| 以为安全组=机器防火墙 | ①②职责混淆,改了一处不灵 | 记住排查顺序:安全组 → ufw → 监听地址 |
| SSH 来源写错把自己锁外 | 会话一断回不去 | 保留现有会话 + 云控制台 VNC 兜底 |
六、综合实战:新 Web 服务上线放行清单
场景:192.168.1.10 上线一个 8080 的 Web 服务,仅对公网开放 80/443(经 nginx),8080 只允许本机和内网段:
bash
# ① 应用只听本机与内网:bind 0.0.0.0 但由防火墙控(或直接监听 127.0.0.1:8080 + nginx proxy)
ss -lntp | grep 8080
# ② 系统防火墙(Ubuntu)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 192.168.1.0/24 to any port 8080/tcp
sudo ufw status numbered # 核对
# ③ 云安全组:入站放 80/443(来源 0.0.0.0/0),不放 8080
# ④ 三层验证(在"外部"的 192.168.1.11 上):
curl -sI http://192.168.1.10/ | head -1 # ✅ 200
curl -sI --max-time 3 http://192.168.1.10:8080/ | head -1 # ✅ 超时(外部不通,符合预期)
# ⑤ 在同网段机器上验证 8080 可达
# ⑥ 开日志观察一天:sudo ufw logging medium && tail -f /var/log/ufw.log
验收标准:能口述三层门及排查顺序;能解释 DROP 和 REJECT 在 tcpdump 里的表现差异;给新服务写出"最小放行面"清单。
七、🚨 避坑清单
| # | 坑 | 后果 | 正确姿势 |
|---|---|---|---|
| 1 | 三层职责混淆,改一处不灵就说"玄学" | 排查空转 | 按序查:安全组→系统防火墙→监听地址 |
| 2 | 改 SSH 防火墙规则不保底 | 锁死自己 | 保留现有会话;先放行再修改 |
| 3 | firewalld --permanent 不 --reload |
重启规则才出现 | 改完必 reload;排错对照"运行时 vs 持久"两份 |
| 4 | 数据库端口对 0.0.0.0/0 放行 | 扫描器天天敲门 | 来源限内网段/公司出口 |
| 5 | ufw 和 firewalld/iptables 混用 | 规则互相打架 | 一台机器一个前端 |
| 6 | 安全组放行了就觉得安全 | 机器防火墙可能全 deny | 两层都配,纵深防御 |
| 7 | 忽略 Docker 的 iptables 旁路 | -p 直接写 iptables NAT,ufw 拦不住 |
容器端口不对公网暴露,走 nginx 反代 |
💡 第 7 条展开一句:
docker run -p 8080:80的规则写在 iptables 的 nat/FORWARD 链上,绕过了 ufw 的 INPUT 规则 ------"我明明 deny 了 8080 为什么还能访问"的标准答案。容器对外只出 80/443,其余走内网或127.0.0.1:8080:80(呼应 S5-05 的坑 6)。
八、一句话总结
数据包过三道门:安全组、系统防火墙、监听地址------按行进顺序排查,最小放行面是唯一正解;记住 Docker 的 -p 会绕过 ufw,你就赢过 80% 的面试者。
💬 互动
你有没有"把自己锁在服务器外"或者"Docker 绕过防火墙"的血泪史?评论区聊聊,这类故事永远不嫌多。
下一篇预告:《S2-04 SSH 与系统安全加固:密钥登录、sshd 加固与 fail2ban》------门开好了,接下来教你把门换成防盗门。