ECS (Ubuntu 22.04) 安全加固实战:SSH 密钥登录 + UFW 防火墙 + Fail2ban 防暴力破解
前面几篇文章记录了在华为云弹性云服务器 ECS(Ubuntu 22.04 LTS)上从零部署 Docker + Nginx 静态服务、做系统运维优化、以及用 Shell + Crontab 实现定时备份。服务跑起来之后,下一个绕不开的问题就是安全。
只要 ECS 绑定了公网 IP,就会持续暴露在公网扫描之下。本文记录一次完整的安全加固落地过程:SSH 改密钥登录、UFW 配置最小化防火墙规则、Fail2ban 自动封禁暴力破解 IP,并在结尾附上加固前后的效果对比和踩坑记录。
一、为什么必须做安全加固
服务器上线第一天,就可以在 /var/log/auth.log 里看到大量这样的记录:
Oct 28 03:12:41 ecs-xxxx sshd[18233]: Failed password for root from 45.x.x.x port 51233 ssh2
Oct 28 03:12:44 ecs-xxxx sshd[18241]: Failed password for root from 103.x.x.x port 41802 ssh2
统计一下暴力破解的规模:
# 统计当天失败登录尝试的来源 IP Top 10
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10
我的这台机器上线不到一周,失败登录尝试已经超过 8000 次,绝大多数是在爆破 root 密码。默认配置下(root + 密码登录 + 22 端口)等于把大门敞开,加固刻不容缓。
本文的加固目标:
| 目标 | 手段 |
|---|---|
| 杜绝密码暴力破解 | SSH 仅允许密钥登录 |
| 最小化攻击面 | UFW 只放行必要端口 |
| 自动封禁恶意 IP | Fail2ban 联动防火墙 |
| 出问题能回滚 | 保留一个已验证的后备通道 |
二、加固前的准备:留好"后悔药"
安全加固最大的风险是把自己锁在门外。动手前先做两件事:
1. 在华为云控制台确认可以 VNC 登录
即使 SSH 全部配错,华为云控制台的「远程登录」(VNC)也能进入系统救急。操作路径:ECS 控制台 → 找到目标实例 → 远程登录。先确认这条路能走通,再开始改配置。
2. 本地生成并验证密钥对
本地电脑执行(Windows 10/11 自带 OpenSSH,PowerShell 直接可用):
# 生成 ed25519 密钥对,比 RSA 更安全且更短
ssh-keygen -t ed25519 -C "huawei-ecs-admin"
# 默认保存在 C:\Users\<你的用户名>\.ssh\id_ed25519
强烈建议同时设置密钥 passphrase,这样即使私钥文件泄露也不会被直接利用。
三、第一步:SSH 改密钥登录
1. 上传公钥到服务器
用当前的密码登录方式先把公钥写上去:
# 在本地执行(PowerShell),把公钥追加到服务器的 authorized_keys
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh ubuntu@<ECS公网IP> "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
注意两点权限细节,配错了密钥登录会直接失败:
~/.ssh目录权限必须为700authorized_keys文件权限必须为600
2. 验证密钥登录成功
不要直接改配置,先新开一个终端验证:
ssh -i $env:USERPROFILE\.ssh\id_ed25519 ubuntu@<ECS公网IP>
# 能免密码直接登录,说明密钥配置生效
3. 修改 sshd 配置
确认密钥可登录后,编辑 /etc/ssh/sshd_config(或规范一点,放到独立配置文件里):
sudo vim /etc/ssh/sshd_config.d/99-hardening.conf
写入:
# 禁止密码登录(密钥验证通过后再开启这一行)
PasswordAuthentication no
# 禁止 root 直接登录
PermitRootLogin no
# 只保留协议 2(新版默认即是,显式声明无妨)
Protocol 2
# 限制最大认证尝试次数
MaxAuthTries 3
建议先用普通用户(如 ubuntu)操作,PermitRootLogin no 生效后 root 就进不来了。日常工作也应以普通用户 + sudo 进行。
重启服务并确认状态:
sudo systemctl restart ssh
sudo systemctl status ssh
此时保持当前会话不要退出,再开新终端测试登录。新终端能正常进,老会话才能关——这是改 SSH 配置的铁律。
四、第二步:UFW 配置最小化防火墙
华为云安全组已经做了第一层端口管控,主机层面的 UFW 是第二道防线,两层配合、纵深防御。
1. 设置默认策略并放行必要端口
# 默认拒绝所有入站
sudo ufw default deny incoming
# 默认允许所有出站
sudo ufw default allow outgoing
# 放行 SSH(必须先放行,否则下一步 enable 会把自己踢下线!)
sudo ufw allow 22/tcp comment 'SSH'
# 放行 Web 服务
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
# 启用防火墙
sudo ufw enable
sudo ufw status verbose
enable 之前务必确认 22 端口规则已存在,这是和 SSH 加固同级别的"自锁"高危操作。
2. 限制 SSH 端口的连接频率
UFW 自带 rate limit,可以对 22 端口做简单限速(30 秒内超过 6 次新连接就暂时拒绝):
sudo ufw limit 22/tcp
3. 一个容易踩的坑:Docker 绕过 UFW
这是本次加固中最大的坑——Docker 发布的端口(-p 参数)会直接写 iptables,绕过 UFW 规则。也就是说即使 UFW 没放行 8080,docker run -p 8080:80 的容器依然对公网可达。
验证方法:
# 从外部扫描,如果容器端口能通,说明被 Docker 绕过了
解决方案(按需选择):
-
容器端口只绑定本机回环,由宿主机 Nginx 反向代理对外(我采用的方式,与上一篇文章的 Nginx 反代架构正好衔接):
# 只监听 127.0.0.1,公网不可达 docker run -d -p 127.0.0.1:8080:80 nginx -
修改
/etc/docker/daemon.json让 Docker 走 UFW 管理链(需重启 Docker,注意会短暂中断容器):{ "iptables": false }此方案影响面较大,需自行处理 Docker 网络出站,慎用。
五、第三步:Fail2ban 自动封禁爆破 IP
UFW 是静态规则,Fail2ban 负责"动态防御":监控日志,对反复失败的 IP 自动封禁。
1. 安装与配置
sudo apt update && sudo apt install fail2ban -y
Ubuntu 22.04 的 Fail2ban 默认没有开启任何 jail,且官方推荐不要直接改 jail.conf,而是新建本地配置:
sudo vim /etc/fail2ban/jail.local
写入针对 SSHD 的规则:
[DEFAULT]
# 封禁时长 1 小时
bantime = 1h
# 10 分钟内
findtime = 10m
# 累计失败次数
maxretry = 5
# 使用 UFW 执行封禁(与我们的防火墙方案联动)
banaction = ufw
[sshd]
enabled = true
port = 22
logpath = /var/log/auth.log
启动并设置开机自启:
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
2. 验证效果
# 查看 sshd jail 状态(重点看 Currently banned / Total banned)
sudo fail2ban-client status sshd
运行一段时间后的输出示例:
Status for the jail: sshd
|- Filter
| |- Currently failed: 2
| |- Total failed: 1437
| `- File list: /var/log/auth.log
`- Action
|- Currently banned: 37
|- Total banned: 89
`- Banned IP list: 45.xxx.xxx.xxx 103.xxx.xxx.xxx ...
手动测试一次封禁(可选,用另一台机器或手机热点故意输错密码 5 次,观察 IP 进入 banned list)。
3. 解封误封的 IP
如果把自己公司的出口 IP 封了(比如内部测试登录失败太多次):
sudo fail2ban-client set sshd unbanip <被误封的IP>
六、加固效果与验收清单
全部完成后,做一次系统性验收:
# 1. 密码登录已被拒绝(应提示 Permission denied (publickey))
ssh -o PreferredAuthentications=password ubuntu@<ECS公网IP>
# 2. UFW 规则符合预期
sudo ufw status numbered
# 3. Fail2ban 正常运行且有封禁记录
sudo fail2ban-client status sshd
# 4. auth.log 中新的失败尝试不再出现 "Accepted password"
grep "Accepted password" /var/log/auth.log | wc -l # 加固后新增应为 0
加固前后对比(我这台机器的实际数据):
| 指标 | 加固前 | 加固后 |
|---|---|---|
| SSH 认证方式 | 密码 + 密钥 | 仅密钥 |
| root 直接登录 | 允许 | 禁止 |
| 入站开放端口 | 全部依赖安全组 | UFW 白名单(22/80/443) |
| 爆破 IP 处理 | 仅记录日志 | 自动封禁 1 小时 |
| 一周失败登录尝试 | 8000+ 次 | 仍会被扫,但全部无法成功且被动态封禁 |
七、写在最后
安全加固不是一个一次性动作,而是一套组合拳 + 持续运营:
- 收缩入口:密钥登录 + 禁 root,让密码爆破直接失效;
- 最小暴露:UFW 白名单,并注意 Docker 端口绕过问题;
- 动态防御:Fail2ban 让扫描和爆破有实际成本;
- 持续观察:定期
fail2ban-client status和审计日志,发现新风险。
到目前为止,这个系列已经覆盖了华为云 ECS 从部署、运维优化、数据备份到安全加固的完整闭环。下一篇文章计划记录用 HTTPS 证书自动续期 + Nginx 安全头进一步完善 Web 层安全,欢迎关注。
如果文章对你有帮助,欢迎点赞、收藏、评论区交流~
- 点赞
- 收藏
- 关注作者
评论(0)