前言
今天突然发现,阿里云提供的默认免费的SSH防护,只有异地登录防护。换句话说,只有黑客登录成功了,而且是异地的,才会告警。然后,很多功能有,但是是付费的……提示说,“仅高级版、企业版、旗舰版支持此功能,当前版本过低。”
这些功能都是付费的:
- 防暴力破解
- 设置常用登录IP
- 设置常用登录时间
- 设置常用登录账号
也就是说就一个异地登录是免费告警的!唔,那么怎么让自己的设备更安全呢……
首先,不使用弱密码这些都是老生常谈了。这里就想一想,有没有办法,能够做到:
- 如果说,有恶意登录,能让我知道
- 如果说,有恶意破解尝试,我能阻止
所以就有了这篇文章,首先介绍如何看登录历史,然后对恶意登录IP做出封禁处理。
查看登陆历史
last 命令
last
命令用于查看系统登录记录,默认从 /var/log/wtmp
文件中读取数据。该文件记录成功登录的会话,包括:
- 系统重启事件
- SSH 登录
- 本地终端登录
# 查看最近的登录记录(默认显示全部)
last
# 查看指定用户的登录记录
last username
# 查看重启记录
last reboot
然而,你可能会发现这个玩意不可靠。为什么 last
不显示某些 SSH 登录记录?可能有这几个原因:
- 日志轮转(Log Rotation),系统通过
logrotate
定期将旧的/var/log/wtmp
归档(如wtmp.1
、wtmp.2.gz
),新记录写入新文件。 - SSH 会话复用。如果通过 SSH 复用现有连接(如配置
ControlMaster
),不会生成新记录。 - 非交互式登录。通过
ssh user@host "command"
执行远程命令时,若未分配 TTY,可能不记录到wtmp
。 - 服务器与本地时间不一致导致记录显示异常。
所以这玩意不是很靠谱,有些记录看不到。
看认证日志
接下来介绍如何使用 /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 的工作原理可以比作一个智能门卫,负责监控谁在尝试进入你的服务器,并在发现可疑行为时暂时封锁对方。它主要做三件事:
- 监控日志。fail2ban 会持续查看服务器上的日志文件,比如记录登录失败的日志(例如 SSH 的
/var/log/auth.log
或 FTP 的/var/log/vsftpd.log
)。这些日志里会记录谁在尝试登录、是否成功等信息。 - 判断异常行为。你告诉 fail2ban 规则,比如“1分钟内同一个IP失败3次算攻击”。fail2ban 会根据这些规则分析日志。如果有人短时间内多次登录失败,就会被判定为可疑(比如暴力破解密码)。
- 触发封禁。一旦检测到攻击,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次密码,就会直接封禁。
Comments NOTHING