第 3 课 · 防火墙:默认拒绝与最小白名单
防火墙的正确心智模型只有一句话:不是挡住坏的,而是只放行好的——默认拒绝一切入站,业务需要什么门就开什么门,每个门有理由、有记录。这一课用 ufw 走完最小基线(nftables 版与完整维护纪律见安全栏目《防火墙基线》),重点讲清「白名单怎么定」与「怎么不把自己锁外面」。
白名单的依据:先审计再配置
白名单不是拍脑袋,是对「这台机器对外提供什么」的如实回答:
# ① 当前监听清单(每个 0.0.0.0/[::] 监听都要过审)
ss -tlnp
# ② 三问每个监听:什么服务?必须公网可达吗?谁在用?
# 127.0.0.1 监听 = 本地服务,不用进白名单(数据库/缓存的正确姿势)
# 0.0.0.0 监听 = 对全网开放,必须给出理由
# ③ 最小集的典型答案:22(SSH) + 80/443(Web),没了
审计中常见的「意外住客」:装数据库时默认监听了 0.0.0.0、面板服务对全网开放、开发时的测试端口忘了关——防火墙是最后一道网,监听地址是第一道:能改 127.0.0.1 的先改监听(服务配置文件里的 bind/listen 地址),改不了的才进白名单讨论。
ufw 最小基线(五分钟)
sudo ufw default deny incoming # 默认拒绝入站——模型的地基
sudo ufw default allow outgoing # 出站先全放(收紧是进阶话题)
sudo ufw allow 22/tcp comment 'ssh'
sudo ufw allow 80/tcp comment 'http'
sudo ufw allow 443/tcp comment 'https'
# 办公 IP 限定类端口(面板/数据库管理口):
sudo ufw allow from 你的办公IP to any port 8888 proto tcp comment 'panel-office'
# ⚠ 启用前三查:22 在名单里吗?SSH 会话还活着吗?云安全组不冲突吗?
sudo ufw --force enable
sudo ufw status numbered # 带编号的规则清单(删规则用编号)
# 外部验证:
nc -zv -w3 服务器IP 22 && echo "ssh 通(预期)"
nc -zv -w3 服务器IP 3306 2>/dev/null || echo "3306 不通(预期)"
不锁门外:远程改防火墙的三条保险
- ①保持现有会话:ufw enable 不断已建立的连接(状态跟踪放行 established)——当前 SSH 会话活着,改错了还有挽救窗口,别急着退出;
- ②ufw limit 与 allow 顺序:先 allow 必要端口再 enable,顺序反了就是自锁;改过 SSH 端口的先 allow 新端口;
- ③留后门通道:确认机房 IPMI/VNC/云控制台 VNC 可用(第一小时就该测)——所有软件层锁死时,带外通道是唯一的门。
规则卫生:注释、复审与只减不增的例外
每条规则带 comment(为什么开、谁要的);季度对照 ss -tlnp 复审一遍——业务下线的端口从白名单摘掉。白名单只增不减的防火墙,三年后就是一份攻击面清单。双栈注意:ufw 默认同时管 v4/v6(确认 /etc/default/ufw 的 IPV6=yes);跑 Docker 的机器另有一条坑——Docker 会自写转发规则绕过 ufw,容器端口映射本身就是「放行」,宿主机防火墙管不住它,容器暴露面要在 docker 层面管(--ip 绑内网地址或发布到 127.0.0.1 再由反代转发)。
与云安全组的分工:两层门都要管
云/机房侧的安全组与主机防火墙是两层独立的门:安全组在网络边界拦(流量到不了主机),主机防火墙在系统边界拦。两层都按「默认拒绝 + 最小放行」配置的理由是互为兜底——安全组误配(有人在控制台顺手开了 0.0.0.0/0 的 3306)时主机层还在,主机规则被脚本改坏时安全组还在。排查口径也因此分两层:外部连不上时,先分清是安全组挡的还是主机挡的(云控制台的安全组日志/主机防火墙的 log 前缀各看各的)。优先级纪律:能进安全组的规则先进安全组(离攻击者更远一层),主机层保留完整基线不偷懒。
本节小结
- 默认拒绝 + 最小白名单:先审计监听(ss -tlnp)再定规则,每个放行端口有理由有注释;
- 远程改防火墙三保险:保持会话、先放 SSH 再启用、确认带外通道——顺序错了就是自锁;
- 规则季度复审、只减不增是例外;Docker 会绕过宿主防火墙,容器暴露面单独管。