安全组、防火墙与端口规划

服务器被扫、数据库被拖,入门级事故里绝大多数都源于“端口开太多”。云上其实有两道门:云平台的安全组在实例外面,主机防火墙在系统里面。只配一层也能用,但两层配合才是稳的。本章先把两道门的分工讲清,再给出一张可直接照抄的端口规划表。

安全组与主机防火墙的分工

维度云安全组主机防火墙(ufw/firewalld)
执行位置云平台网络层,在实例之外操作系统内核 netfilter
生效时机实例没起来、系统没启动也生效系统起来后才生效
规则粒度按安全组绑定实例,支持引用其他安全组按端口、来源 IP、网卡、服务名
典型用途挡住整个公网的扫描,只放行必要端口精细控制本机访问,配合应用调试
常见问题改了安全组忘记保存,规则未生效ufw enable 前没放行 22,把自己关在门外

做法:安全组做粗粒度准入(只放 22/80/443),主机防火墙做细粒度补充(例如只允许公司出口 IP 连 22)。两层都配置,并且明确知道“哪一条规则在拦我”。

端口规划表

端口服务建议监听地址安全组主机防火墙说明
22SSH0.0.0.0仅限公司/家庭出口 IP放行同源有条件就改端口 + 密钥登录
80HTTP0.0.0.00.0.0.0/0 放行(备案后)放行用于跳转 443 与证书校验
443HTTPS0.0.0.00.0.0.0/0 放行放行对外唯一正式入口
8000应用(Gunicorn/uWSGI)127.0.0.1不放行不放行只给本机 Nginx 访问
3000Node 应用127.0.0.1不放行不放行同上
8080Java 应用127.0.0.1不放行不放行同上
3306MySQL127.0.0.1绝不开放绝不开放需要远程连就走跳板机或隧道
6379Redis127.0.0.1绝不开放绝不开放未授权访问是最常见的数据泄露入口
27017MongoDB127.0.0.1绝不开放绝不开放历史泄露重灾区
9090监控指标127.0.0.1仅内网/VPC仅内网需要外部访问就走 Nginx + 鉴权

只暴露必要端口原则

  1. 默认拒绝:入方向默认 deny,只显式放行需要的端口。
  2. 应用一律监听 127.0.0.1,公网入口只留 Nginx 的 80/443。
  3. 管理类端口(SSH、面板、数据库、Redis)用来源 IP 白名单,不用 0.0.0.0/0
  4. 临时调试端口用完立即删除规则,别放在那里“下次方便”。
  5. 出方向一般可放开,但要关注被入侵后的外联行为,必要时对出方向也做限制。

配置 ufw(Ubuntu / Debian)

# 安装并设定默认策略:入站拒绝、出站允许
sudo apt -y install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing

# 先放行 SSH,再启用,否则会把自己关在门外
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# 更严格:SSH 只允许固定出口 IP 访问
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp

sudo ufw enable
sudo ufw status verbose
sudo systemctl enable ufw

配置 firewalld(Alibaba Cloud Linux / CentOS / RHEL)

sudo dnf -y install firewalld
sudo systemctl enable --now firewalld

# 按服务名放行(更语义化,端口变化时不用改规则)
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

# 按端口放行
sudo firewall-cmd --permanent --add-port=8443/tcp

# 富规则:只允许指定网段访问 22
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port port="22" protocol="tcp" accept'

# 让规则生效并查看全部配置
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

注意 --permanent:不加它只改运行时规则,重启即失效;加了它必须 --reload 才生效,两者容易记混,--permanent--reload 是固定套路。

关键参数逐条解释

  • 0.0.0.0/0:表示任意来源 IPv4 地址,即“对全世界开放”,只在 80/443 上使用。
  • 授权对象 CIDR:203.0.113.0/24 表示该网段全部地址;单机管理建议写 /32
  • 安全组优先级:多数云厂商的规则是“拒绝优先”或按序号匹配,放行与拒绝混用时务必看厂商文档的匹配顺序。
  • ufw deny 与未放行的区别:未放行即默认拒绝;deny 用于显式拒绝一个默认允许的端口或来源。
  • firewalld 的 zone:默认 public 区域,--zone= 不写就是默认区域;多网卡机器要确认规则加在了正确区域上。

数据库端口绝不能对公网开放

一个公开的 3306 端口,从被扫到被爆破往往只需要几十分钟。三种正确的远程访问方式:

# 方式一:SSH 本地端口转发,把远程 3306 映射到本地 13306
ssh -N -L 13306:127.0.0.1:3306 deploy@47.98.x.x
# 之后本地用 127.0.0.1:13306 连接,公网从未暴露数据库

# 方式二:仅允许同安全组/VPC 内的应用机器访问 3306
# 安全组来源写另一台机器的内网 IP 或安全组 ID,而不是 0.0.0.0/0

# 方式三:使用云数据库 RDS,走内网地址 + 白名单

验证方法

# 本机监听情况:必须看到 127.0.0.1 而不是 0.0.0.0
sudo ss -lntp

# ufw 规则是否生效
sudo ufw status verbose

# firewalld 生效后的规则集合
sudo firewall-cmd --list-all

# 从外部机器测试端口是否真的可达(在自己电脑上执行)
nc -vz 47.98.x.x 443
nc -vz 47.98.x.x 3306    # 期望:超时或 refused

ss -lntp 里 3306/6379 显示为 127.0.0.1:3306,且外部 nc 连不上,端口这一层才算合格。

常见坑

现象做法
只在安全组放行 80/443,没配主机防火墙能通,但少了内层防线两层都配,或明确只用安全组并记录在案
ufw enable 前没放行 22立刻就断连,只能走 VNC 救援ufw allow 22/tcp 再 enable
应用监听 0.0.0.0:3306即使防火墙拦着也随时可能被绕过应用层直接绑 127.0.0.1
Docker -p 3306:3306绕过 ufw 直接暴露(Docker 自己写 iptables)-p 127.0.0.1:3306:3306 或走自定义网络
调试端口忘记关成了后门用完立即删规则,并定期复核
firewall-cmd 忘了 --permanent重启后规则消失--permanent + --reload 成对使用

小结:安全组管外面、主机防火墙管里面,两层都要配;端口按“对外只开 80/443,应用与数据库只听 127.0.0.1”来规划;管理端口用来源 IP 白名单;Docker 的 -p 会绕过 ufw,必须显式绑 127.0.0.1;每次改完规则都用 ss -lntp 加外部 nc 双向验证一次。

笔记加载中…