
核心要点(TL;DR)
很多人把云服务器买回来、装好环境就直接解析域名上线,安全组里默认放行全部端口,主机防火墙干脆没开。等到 /var/log/auth.log 里出现成百上千条 SSH 爆破记录,或者数据库被写入勒索信息,才发现暴露面早已失控。本文给出一份可直接照做的云服务器安全组与防火墙配置清单,从端口规划到规则落地再到上线验证,帮你用最小权限原则把服务器收敛到可上线状态。
一、先搞清:安全组与主机防火墙是两层防线
云服务器实际有两道过滤:云平台的安全组工作在虚拟网络层,流量在到达实例网卡前就被判断;主机防火墙(ufw、iptables、firewalld)工作在操作系统内核层。两者是串联关系——任何一层拒绝,连接就失败。这也解释了一个高频困惑:安全组放行了,服务却连不上,多半是主机防火墙没放行,或服务只监听了 127.0.0.1。
因此配置原则是:两层都开,规则保持一致,安全组管粗粒度(哪些 IP 能进哪些端口),主机防火墙做兜底与细粒度控制。
二、端口规划:先列清单再动手
不要边配边想。先按下表把业务端口列清楚,明确每个端口的来源范围,再写规则。
| 端口/服务 | 是否对公网 | 来源限制 | 说明 |
|---|---|---|---|
| 22 / SSH | 尽量不对公网 | 办公 IP 或跳板机 | 改端口只是降噪,密钥登录才是关键 |
| 80 / 443 | 是 | 0.0.0.0/0 | Web 入口,配合 HTTPS |
| 3306 / 6379 | 否 | 同 VPC 内网 IP | 数据库、缓存严禁公网暴露 |
| 8080 等管理后台 | 否 | 内网或跳板机 | 确需公网则加白名单与鉴权 |
| 自定义业务端口 | 按需 | 最小范围 | 能走反向代理就不要直开 |
规划完成后,把「计划开放端口清单」写进上线文档,后续所有验证都以此为准。
三、配置安全组:入站最小化,出站按需收
以主流云平台控制台为例,操作路径基本一致:进入实例详情 → 安全组 → 配置规则 → 入站规则。要点如下:
- 默认拒绝:先删除「允许全部流量」的默认规则,只保留明确放行项。
- 按端口逐条添加:协议选 TCP,端口填具体值而非范围,来源填具体 IP 段。
- SSH 单独收紧:来源填办公固定 IP;若 IP 不固定,用跳板机安全组做中转。
- 出站规则:默认全放行可接受,但高安全场景建议只放行 80/443 与内网段,防止被植入后门后外联。
- 规则排序:拒绝规则优先于放行规则,避免被宽泛规则覆盖。
改完先别关控制台,立刻用另一台机器测试目标端口,确认通断符合预期。
四、配置主机防火墙:ufw 与 iptables 实操
Ubuntu/Debian 推荐 ufw,命令直观:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
sudo ufw enable
sudo ufw status verboseCentOS 系可用 firewalld:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10" port port="22" protocol="tcp" accept'
sudo firewall-cmd --reload
sudo firewall-cmd --list-all习惯 iptables 的话,核心是默认策略加白名单:
sudo iptables -P INPUT DROP
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -p tcp -s 203.0.113.10 --dport 22 -j ACCEPT注意:在远程 SSH 会话中直接执行-P INPUT DROP前,务必先放行 SSH 来源,否则会把自己锁在门外。稳妥做法是先用临时规则测试,确认后再固化并持久化(iptables-save或安装iptables-persistent)。
五、验证与排查:三层对齐才算配完
配置完成不代表生效正确,按下面三步验证:
- 监听层:
ss -lntp查看服务监听地址,确认对外服务是0.0.0.0而非127.0.0.1。 - 主机层:
sudo ufw status verbose或sudo iptables -L -n -v核对放行项。 - 外部层:从公网另一台机器执行
nmap -Pn -p- 你的公网IP,确认只有计划端口为 open。
若出现「安全组放了仍不通」,按顺序排查:服务监听地址 → 主机防火墙 → 安全组方向与来源 → 子网 ACL → 云厂商网络策略。逐层排除,不要一次改多处。
六、上线前检查清单与行动建议
上线前逐项打勾:
- 安全组已删除全放行规则,入站仅保留必要端口
- SSH 已禁用密码登录(
PasswordAuthentication no),密钥可正常登录 - 数据库、缓存、管理后台端口未对公网开放
- 主机防火墙已启用且与安全组规则一致
- 外部全端口扫描结果与计划清单一致
- 已开启登录审计与异常告警,日志留存可查
若希望减少手工核对成本,可在主机侧部署主机入侵检测与基线核查类工具,例如 AegisX 提供的资产暴露面梳理与异常登录告警能力,把「配置是否正确」从一次性检查变成持续监控。行动建议:今天就按本文清单把现有服务器过一遍,优先处理 SSH 与数据库两个高风险端口,再逐步收敛其余规则。
常见问题(FAQ)
安全组和服务器里的防火墙需要同时配置吗?
需要。安全组工作在云平台虚拟网络层,流量在到达实例前就被过滤;主机防火墙(ufw/iptables/firewalld)工作在操作系统内核层。两者是串联关系,任何一层放行、另一层拒绝,连接都会失败。只配安全组而关闭主机防火墙并非不行,但实例一旦迁移或更换镜像就容易失守,建议两层都配且规则保持一致,形成纵深防御。
为什么我安全组放行了端口,外部还是连不上?
最常见原因是主机防火墙未放行,其次是服务只监听在 127.0.0.1。排查顺序:先用 ss -lntp 确认服务监听地址是 0.0.0.0 而非回环地址;再检查 ufw status 或 iptables -L -n 是否放行;然后确认安全组规则方向为入站、协议端口匹配、来源为 0.0.0.0/0 或你的 IP;最后检查云厂商是否有子网 ACL 或网络 ACL 额外拦截。
SSH 端口改成非 22 就安全了吗?
不够。改端口只能减少扫描器命中率,属于降低噪声而非真正的防护。更关键的是禁用密码登录、改用密钥认证,并在安全组里把 22 或自定义端口的来源限制为办公 IP 或跳板机 IP。如果必须对公网开放,建议配合 fail2ban 限制失败次数,并开启云厂商的登录审计与告警,形成可追溯的访问链路。
数据库端口能不能直接对公网开放?
不建议。MySQL 3306、Redis 6379、MongoDB 27017 等端口对公网开放是被入侵的高发原因,弱口令和未授权访问会在数小时内被扫到。正确做法是把数据库放在同一 VPC 内网,安全组只允许应用服务器内网 IP 访问;本地调试用 SSH 隧道,例如 ssh -L 3306:内网IP:3306 跳板机,既方便又不暴露端口。
上线前有没有快速自查的办法?
有。从外部机器用 nmap -Pn -p- 你的公网IP 扫描全部端口,确认只有计划开放的端口处于 open 状态;再用 ss -lntp 核对本机监听清单;检查 ufw status verbose 与安全组规则是否一致;确认 SSH 密钥登录可用、密码登录已关闭;最后查看系统日志 /var/log/auth.log 有无异常爆破记录。三项对齐即可认为暴露面可控。