暴力破解安全防护

橘子 发布于 13 天前 55 次阅读


前言

今天突然发现,阿里云提供的默认免费的SSH防护,只有异地登录防护。换句话说,只有黑客登录成功了,而且是异地的,才会告警。然后,很多功能有,但是是付费的……提示说,“仅高级版、企业版、旗舰版支持此功能,当前版本过低。”

这些功能都是付费的:

  • 防暴力破解
  • 设置常用登录IP
  • 设置常用登录时间
  • 设置常用登录账号

也就是说就一个异地登录是免费告警的!唔,那么怎么让自己的设备更安全呢……

首先,不使用弱密码这些都是老生常谈了。这里就想一想,有没有办法,能够做到:

  1. 如果说,有恶意登录,能让我知道
  2. 如果说,有恶意破解尝试,我能阻止

所以就有了这篇文章,首先介绍如何看登录历史,然后对恶意登录IP做出封禁处理。

查看登陆历史

last 命令

last 命令用于查看系统登录记录,默认从 /var/log/wtmp 文件中读取数据。该文件记录成功登录的会话,包括:

  • 系统重启事件
  • SSH 登录
  • 本地终端登录
# 查看最近的登录记录(默认显示全部)
last

# 查看指定用户的登录记录
last username

# 查看重启记录
last reboot

然而,你可能会发现这个玩意不可靠。为什么 last 不显示某些 SSH 登录记录?可能有这几个原因:

  1. 日志轮转(Log Rotation),系统通过 logrotate 定期将旧的 /var/log/wtmp 归档(如 wtmp.1wtmp.2.gz),新记录写入新文件。
  2. SSH 会话复用。如果通过 SSH 复用现有连接(如配置 ControlMaster),不会生成新记录。
  3. 非交互式登录。通过 ssh user@host "command" 执行远程命令时,若未分配 TTY,可能不记录到 wtmp
  4. 服务器与本地时间不一致导致记录显示异常。

所以这玩意不是很靠谱,有些记录看不到。

看认证日志

接下来介绍如何使用 /var/log/auth.log 分析登录行为,这个比较靠谱,但是分析起来比较麻烦。

/var/log/auth.log 记录了所有认证相关的日志,包括:

  • SSH 登录成功/失败
  • sudo 提权操作
  • PAM 模块事件

查看示例:

# 查看 SSH 登录成功记录
sudo grep 'sshd.*Accepted' /var/log/auth.log

# 查看 SSH 登录失败记录
# sudo grep 'sshd.*Failed' /var/log/auth.log

防范暴力破解

原生的SSH只支持设置单次会话中密码重试次数,但是不会封禁,也不会封IP。所以这里介绍一下如何使用fail2ban这个工具,在xxx时间范围内,对于尝试错误超过x次的IP执行封禁,在xxx时间后解封。

安装

安装fail2ban:

sudo apt update
sudo apt install fail2ban -y

配置

防护规则的默认配置位于/etc/fail2ban/jail.conf,这里有默认配置、ssh、mysql、phpmyadmin等大量软件的防护规则。不应该直接修改这个配置文件,因为它可能会在发行版更新中被覆盖或更新。正确的做法是,在以下两个文件路径中选一个,创建一个本地配置:

  • jail.local
  • jail.d/customisation.local.

这里建议大概读一下 /etc/fail2ban/jail.conf 这个文件,了解一下默认配置。然后新建一个jail.local 文件,单独设置sshd:

sudo vim /etc/fail2ban/jail.local

添加 SSH 防护参数,并调整。这里的例子是,10分钟内,尝试错误3次,则封禁30分钟,按需修改:

[sshd]
# 10分钟内,尝试错误3次,则封禁30分钟
enabled   = true
maxretry  = 3
findtime  = 10m
bantime   = 30m

# 日志路径与后端(保持默认即可)
port      = ssh
logpath   = %(sshd_log)s
backend   = %(sshd_backend)s

这里的port、logpath、backend最好不填写,这样就会保持默认。如果需要修改再修改。

此外,最好不要使用行尾注释,之前被FTP坑过。不是所有程序都能正确识别行尾注释的。

进阶配置

思考一下,我们手机输入密码错误,封禁的时间是固定的吗?不是吧,是阶梯式的。比如说第一次错,只会锁定1分钟,后面就锁定几十分钟甚至几个小时。fail2ban也支持这样的设置!

示例如下,每输入密码错误3次,触发1次封禁。初始封禁1分钟,第二次5分钟,第三次25分钟,每次翻5倍,最高封禁1天。

[sshd]
enabled = true
# 在10分钟的窗口内,错误3次触发封禁
maxretry = 3
findtime = 10m
# 阶梯封禁参数。初始封禁1分钟,每次递增倍数为5. 最大封禁时间为一天(24小时)
bantime = 1m
bantime.increment = true
bantime.factor = 5
bantime.maxtime = 24h

此外,bantime的设置甚至支持随机封禁时间、自定义封禁时间计算公式!感兴趣就去读一下他的默认配置中的注释吧。

重启服务并验证

重启服务,看具体状态:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd  # 查看封禁状态

好了,现在可以去作死试一下把自己的IP封掉。如果要试着封禁自己的IP,最好把封禁窗口和时间都调小一点,免得把自己的IP给玩死了。这里我试了一下,删掉自己的公钥,重新尝试登录,立刻就要求我输入密码了。连续尝试三次错误,封禁了。

注意,这里的三次,不是和SSH会话重试的三次做乘法。换句话说,如果你设置了fail2ban 3次就封禁,SSH又默认一次会话就能重试3次,那么在一次会话输入密码错误3次是立刻封禁,不会给第二次会话尝试的机会。也就是封禁依赖的计数是密码错误次数,和会话没有关系。

查看封禁记录

通过日志查看封禁事件:

sudo tail -f /var/log/fail2ban.log

你知道有多恐怖吗!就在我设置完的三分钟内,日志就发现了一个SSH恶意破解尝试!是一个来自荷兰的IP:

INFO    [sshd] Found 196.251.90.9 - 2025-09-03 16:58:14
INFO    [sshd] Found 196.251.90.9 - 2025-09-03 16:58:16

尝试了2次,没试出来,然后就溜了……很吓人!

解封

由于封禁是基于IP的,所以解封也是基于IP解封。比如,现在想要解封SSH的 192.168.1.100 这个IP:

sudo fail2ban-client set sshd unbanip 192.168.1.100

推广到FTP

可以把这里的防范处理扩展到FTP服务上。这里还是需要看一下 jail.conf 的默认配置会比较好。我使用的是vsftp.

首先是看一下日志文件是否存在?毕竟fail2ban是基于日志的。检查一下:

ls /var/log/vsftpd.log

我可以看到文件,说明OK。但是如果没有日志,需确保 VSFTPD 配置启用了日志记录:

# 看一下 VSFTPD 配置启用了日志记录
sudo vim /etc/vsftpd.conf
# 检查以下配置是否存在:
xferlog_enable=YES
xferlog_file=/var/log/vsftpd.log

启用FTP封禁:

[vsftpd]
enabled = true
# 在10分钟的窗口内,错误3次触发封禁。初始封1分钟,每次递增5倍. 最大封禁一天。
maxretry = 3
findtime = 10m
bantime  = 1m
bantime.increment = true
bantime.factor    = 5
bantime.maxtime   = 24h

可以看到和SSH配置是基本一致的,这是因为 port、logpath都在默认配置中确定了,这里不用改。这也是推荐不要修改默认配置的重要原因。

常用命令汇总

常用命令:

# 查看当前运行状态
sudo fail2ban-client status
# 查看ssh的封禁情况
sudo fail2ban-client status sshd
# 查看vsftp的封禁情况
sudo fail2ban-client status vsftpd
# 重启服务
sudo systemctl restart fail2ban
# 编辑配置文件
sudo vim /etc/fail2ban/jail.local
# 查看完整日志文件
sudo vim /var/log/fail2ban.log

fail2ban的原理

这里简要介绍一下fail2ban的原理。

fail2ban 的工作原理可以比作一个智能门卫,负责监控谁在尝试进入你的服务器,并在发现可疑行为时暂时封锁对方。它主要做三件事:

  1. 监控日志。fail2ban 会持续查看服务器上的日志文件,比如记录登录失败的日志(例如 SSH 的 /var/log/auth.log 或 FTP 的 /var/log/vsftpd.log)。这些日志里会记录谁在尝试登录、是否成功等信息。
  2. 判断异常行为。你告诉 fail2ban 规则,比如“1分钟内同一个IP失败3次算攻击”。fail2ban 会根据这些规则分析日志。如果有人短时间内多次登录失败,就会被判定为可疑(比如暴力破解密码)。
  3. 触发封禁。一旦检测到攻击,fail2ban 会自动调用防火墙(比如 iptables 或 ufw),把可疑的IP地址加入黑名单,阻止它继续连接服务器。你可以设置封禁时间,比如第一次封1分钟,第二次封更久,逐渐升级。

那么这个程序会不断去看其他程序的日志对吧?这会很消耗性能吗?有什么优化吗?

这个就问问DeepSeek老师吧,看看他怎么说。

首先,日志是增量读取的。fail2ban 不是每次扫描整个日志文件,而是记录上次读取的位置,只检查新增的日志内容。类似于“看书时用书签标记看到哪里,下次直接翻到书签位置继续读”。

其次,fail2ban是定期检查而非实时监控。默认每隔几秒(可配置)扫描一次日志,而不是实时盯着每一条日志。频率较低时对 CPU 和内存的影响很小。

最后,它使用轻量级规则匹配。虽然需要匹配正则表达式(如检测失败登录),但大多数服务的失败日志行数本身不多,正则表达式也经过优化,匹配速度很快。

弱点和防范

不要轻易让人知道你的防护规则,否则可能出现针对性的爆破手段。比如说,使用这样的规则:

  • 在1分钟的窗口内,错误3次触发封禁;
  • 初始封1分钟,每次递增5倍. 最大封禁一天。

你能发现它的弱点吗?

没错,就是检测的窗口期。这里约定了检测的窗口期是1分钟,只有连续的1分钟内出现3次错误,才会触发封禁。这就意味着,如果黑客每21秒尝试一次,则连续的60秒内至多出现2次错误,则一直不会触发封禁规则!!!如果按一天是86400秒来估计,黑客一天至少可以尝试4100个密码,如果你的密码很弱,还是有可能被撞出来的。

所以,这个检测窗口期可以增大。比如说,在上述例子中,从1分钟增加到30分钟,那么黑客的安全破解频率就下降到了15分钟零1秒,也就是901秒,每天只能无封禁破解95次,次数下降了97%以上!!!

同时你可以注意到,如果你自己不慎输入错密码触发了封禁,惩罚是只有1分钟的,因为检测窗口间隔和封禁惩罚时长无关

所以,可以适度增大检测窗口间隔。使用极限法,如果你把窗口增大到无穷大,则意味着一旦连续输入错误3次密码,就会直接封禁。