云服务器防 SSH 暴力破解:Fail2ban + 密钥登录加固实战

举报
yd_276596855 发表于 2026/11/11 14:56:41 2026/11/11
【摘要】 云服务器一上线,SSH 端口就会被全网扫描器盯上。本文从查看攻击日志开始,一步步完成密钥登录、禁用密码、Fail2ban 自动封禁和告警查看,并附一个用 Python 统计攻击来源的小脚本。

一、为什么要做这件事


新买的云服务器开机不到一小时,查看认证日志往往就能看到成百上千条“Failed password for root”。这些都是自动化脚本在撞库。只要密码足够弱,或者某个测试账号忘了删,服务器就可能沦为挖矿机。本文的目标很简单:让暴力破解在技术上没有意义,同时让异常 IP 自动被封。


环境:Ubuntu 22.04,root 或具备 sudo 权限的用户。


二、先看看自己正在被谁攻击


在 Ubuntu 上,SSH 认证日志位于 /var/log 目录下的 auth 日志中,可以直接用 journalctl 查看:


    sudo journalctl -u ssh --since "1 hour ago" | grep "Failed password" | head


统计尝试次数最多的 IP:


    sudo journalctl -u ssh --since today | grep "Failed password" \

      | grep -oE "from [0-9.]+" | awk '{print $2}' | sort | uniq -c | sort -rn | head


如果你看到某个 IP 一天尝试了几千次,就说明加固刻不容缓。


三、第一步:改用密钥登录


在本地电脑生成密钥(推荐 ed25519):


    ssh-keygen -t ed25519 -C "my-laptop"


把公钥推到服务器:


    ssh-copy-id -i 私钥路径 deploy@服务器IP


推完后务必新开一个终端测试密钥能否登录,确认成功前不要关掉当前会话,避免把自己锁在门外。


四、第二步:关闭密码登录和 root 直登


编辑 SSH 服务端配置(/etc/ssh 目录下的 sshd_config),修改或添加以下几行:


    PermitRootLogin no

    PasswordAuthentication no

    KbdInteractiveAuthentication no

    PubkeyAuthentication yes

    MaxAuthTries 3

    LoginGraceTime 30


检查语法并重载:


    sudo sshd -t && sudo systemctl reload ssh


注意:Ubuntu 22.04 的配置目录 sshd_config.d 中可能有云厂商预置的文件把 PasswordAuthentication 又打开了,用下面的命令确认最终生效值:


    sudo sshd -T | grep -E "passwordauthentication|permitrootlogin"


五、第三步:安装并配置 Fail2ban


密钥登录已经让暴力破解几乎不可能成功,但扫描流量仍会占用日志和连接。Fail2ban 会读取日志,发现某 IP 在短时间内多次失败后,自动调用防火墙封禁它。


安装:


    sudo apt update && sudo apt install -y fail2ban


不要直接修改默认配置,而是在 /etc/fail2ban 目录下新建名为 jail 的 local 本地配置文件,写入:


    [DEFAULT]

    bantime = 1h

    findtime = 10m

    maxretry = 5

    backend = systemd

    ignoreip = 127.0.0.1/8 ::1


    [sshd]

    enabled = true

    port = ssh

    mode = aggressive


    [recidive]

    enabled = true

    bantime = 1w

    findtime = 1d

    maxretry = 3


说明:

1. backend 设为 systemd,直接读 journal,适配新版 Ubuntu。

2. mode = aggressive 会把“无效用户”“预认证断开”等也算作失败。

3. recidive 是“惯犯”规则:一天内被封 3 次的 IP 直接封一周。

4. 如果你有固定办公出口 IP,务必加进 ignoreip,防止误封自己。


启动并设置开机自启:


    sudo systemctl enable --now fail2ban


查看状态:


    sudo fail2ban-client status sshd


输出中的 Currently banned 和 Banned IP list 就是当前被封的地址。


手动解封某个 IP:


    sudo fail2ban-client set sshd unbanip 1.2.3.4


六、第四步:配合云安全组


Fail2ban 是主机层防护,云安全组是网络层防护,两者叠加效果最好:

1. 安全组里 22 端口只对自己的出口 IP 放行,是最彻底的办法。

2. 如果出口 IP 不固定,可以把 SSH 改到高位端口(例如 22022),在 sshd_config 中设置 Port,并同步修改安全组和 jail 本地配置里的 port。改端口不能代替加固,但能大幅减少日志噪音。


七、用 Python 统计攻击来源


下面这个小脚本读取 journal 输出,统计失败次数最多的前 10 个 IP,并给出被 Fail2ban 封禁的数量,适合放进 cron 每天跑一次:


    import re

    from subprocess import run

    from collections import Counter


    def failed_ips(since="today"):

        out = run(

            ["journalctl", "-u", "ssh", "--since", since, "--no-pager"],

            capture_output=True, text=True, check=False

        ).stdout

        pattern = re.compile(r"(?:Failed password|Invalid user).*?from (\d+\.\d+\.\d+\.\d+)")

        return Counter(pattern.findall(out))


    def banned_count():

        out = run(

            ["fail2ban-client", "status", "sshd"],

            capture_output=True, text=True, check=False

        ).stdout

        m = re.search(r"Currently banned:\s+(\d+)", out)

        return int(m[1]) if m else 0


    if __name__ == "__main__":

        stats = failed_ips()

        print(f"今日失败尝试总数: {sum(stats.values())}")

        print(f"当前封禁 IP 数: {banned_count()}")

        for ip, n in stats.most_common(10):

            print(f"{ip:<16} {n}")


把脚本保存为 ssh_report(不带扩展名也可以,加上执行权限并在首行写 python3 解释器声明),用 sudo 运行即可。


八、上线检查清单


1. 密钥登录可用,且已在新终端验证。

2. sshd -T 显示 passwordauthentication no、permitrootlogin no。

3. fail2ban-client status sshd 正常,有封禁记录。

4. ignoreip 已加入自己的固定 IP。

5. 安全组规则与 SSH 实际端口一致。


九、总结


防 SSH 暴力破解的核心思路是“让猜密码这件事不存在”:密钥登录 + 禁用密码解决根本问题,Fail2ban 负责清理噪音并封禁惯犯,安全组在网络层收窄入口。三层加起来,一台小云服务器也能安心地暴露在公网上。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。