在当今数字时代,服务器安全性的重要性不言而喻。作为远程管理服务器的主要方式,SSH(Secure Shell)协议因其加密通信的特点而广泛使用。然而,随着 SSH 的普及,恶意攻击者也越来越频繁地通过暴力破解(Brute Force Attack)尝试登录服务器。暴力破解攻击通过不断尝试用户名和密码的组合,直到找到正确的凭据,从而获取对服务器的访问权限。
背景
防止 SSH 暴力破解登录成为服务器安全管理中的一项关键任务。一般来说,会有以下 4 种方案来应对暴力破解登录
- 复杂密码策略:
确保密码的复杂性是防止暴力破解的首要措施。建议使用长度至少为 16 位的密码,且密码应包含大小写字母、数字和特殊字符,避免使用连贯的数字或字母组合。此外,定期更换密码也是增强安全性的有效方法,建议每月更换一次密码以确保稳妥。 - 修改默认 SSH 端口:
默认情况下,SSH 使用端口 22 进行通信。为了增加安全性,可以将 SSH 服务的端口更改为其他不常用的三位数或四位数端口。此举可以迷惑攻击者,避免大多数针对默认端口的暴力破解攻击。 - 禁用 Root 用户直接登录:
通常情况下,管理员会使用 root 用户进行远程登录。为了提高安全性,可以禁用 root 用户的直接登录,将其设置为仅限于系统用户使用。同时,创建一个普通用户并赋予其 root 权限,这样即使攻击者知道 root 用户的存在,也无法直接通过暴力破解的方式登录。 -
使用密钥认证:
密钥认证是另一种提高 SSH 安全性的有效方法。用户可以在客户端生成一对公钥和私钥,并将公钥上传到需要远程连接的服务器上。首次登录时使用密码认证,之后的登录则通过密钥认证,无需再次输入密码。这不仅提升了安全性,还简化了登录过程。用秘钥方式来说是最安全的,但是相信大多嫌麻烦党,肯定还是 22 端口,root 用户加密码的方式来登录,包括我本人也是这样的。直到不经意看到服务器上的 secure 日志,才认识到问题严重性,几乎每分钟都有 IP 尝试暴力登录服务器。日志路径一般为:
/var/log/secure
大家查看日志,就会发现有很多以下字样的日志输出,证明你的服务器正在遭遇暴力 SSH 登录,攻击者在不断的进行切换账号和密码来尝试登录
Jun 3 07:40:20 iZj6c4m6siqupmu8qiwjcwZ sshd[22582]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=222.186.10.214
Jun 3 07:40:21 iZj6c4m6siqupmu8qiwjcwZ sshd[22582]: Failed password for invalid user user from 222.186.10.214 port 59002 ssh2
Jun 3 07:30:09 iZj6c4m6siqupmu8qiwjcwZ sshd[22017]: Failed password for invalid user test from 130.185.96.113 port 59748 ssh2
Jun 3 06:54:06 iZj6c4m6siqupmu8qiwjcwZ sshd[19986]: Failed password for invalid user liling from 47.76.178.131 port 40312 ssh2
Jun 3 06:47:21 iZj6c4m6siqupmu8qiwjcwZ sshd[19610]: Invalid user nali from 47.76.178.131 port 58256
如果不借助第三方工具,我们自己也能进行一定的处理,来提高服务器的安全性。例如:可以把 SSH 的端口换掉,禁止 root 登录,用指定的用户名登录或者也可以去封掉这些日志里常出现的 IP。 本篇文章主要介绍封掉这些常用的 IP。
思路
- 首先我们要获取的这些攻击 IP 来自日志文件 /var/log/secure
- 尝试从这个文件里取出出现登录失败的 IP,并且统计他们的次数
- 让防火墙封掉这些 IP,丢包
- 定时执行脚本,定时禁止异常 IP 的请求。封禁掉之后,我们把secure日志文件清空。
- 我们先执行命令
grep "Failed password" /var/log/secure
可以从这个日志文件获取到失败的登录用户信息,包括 IP 和尝试使用的用户名。如下:
Jun 3 00:45:02 iZj6c4m6siqupmu8qiwjcwZ sshd[31849]: Failed password for invalid user online from 118.220.172.125 port 47734 ssh2
Jun 3 02:21:55 iZj6c4m6siqupmu8qiwjcwZ sshd[4813]: Failed password for invalid user ubnt2 from 118.220.172.125 port 52138 ssh2
Jun 3 02:49:55 iZj6c4m6siqupmu8qiwjcwZ sshd[6349]: Failed password for invalid user a from 213.109.202.127 port 37800 ssh2
Jun 3 03:33:37 iZj6c4m6siqupmu8qiwjcwZ sshd[8806]: Failed password for root from 111.68.111.100 port 49276 ssh2
Jun 3 04:13:50 iZj6c4m6siqupmu8qiwjcwZ sshd[11033]: Failed password for invalid user ychen from 8.222.179.242 port 43462 ssh2
Jun 3 04:16:16 iZj6c4m6siqupmu8qiwjcwZ sshd[11166]: Failed password for invalid user kwang from 8.222.179.242 port 49276 ssh2
Jun 3 04:42:51 iZj6c4m6siqupmu8qiwjcwZ sshd[12695]: Failed password for invalid user oracle from 213.109.202.127 port 34934 ssh2
Jun 3 05:01:58 iZj6c4m6siqupmu8qiwjcwZ sshd[13779]: Failed password for ftp from 175.202.13.55 port 38714 ssh2
- 我们筛选出其中的 IP,并且通过 sort 排序,然后用 head 取得出现 IP 次数最多的前 5 个。执行命令
grep "Failed password" /var/log/secure | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | sort | uniq -c | sort -nr | head -5
输出如下:
[root@iZjwjcwZ scripts]# grep "Failed password" /var/log/secure | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | sort | uniq -c | sort -nr | head -5
8 118.220.172.125
5 213.109.202.127
4 117.239.204.225
3 54.176.138.12
3 47.76.178.131
- 将这些 IP 封掉,可以执行防火墙命令。到这里我们的完整脚本就出现了。代码如下,可以直接复制使用。新建一个脚本文件(例如 xxxx.sh),将以下内容复制即可
#!/bin/bash
# 日志文件路径
LOG_FILE="/var/log/secure"
BAN_LOG="/var/log/ssh_block.log"
# 获取尝试登录的IP地址及其出现次数
TOP_IPS=$(grep "Failed password" $LOG_FILE | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | sort | uniq -c | sort -nr | head -6)
# 遍历这些IP并封禁
echo "$(date) - Starting IP ban process" >> "$BAN_LOG"
echo "$TOP_IPS" | while read count ip; do
if [ ! -z "$ip" ]; then
# 封禁IP
sudo firewall-cmd --permanent --zone=public --add-rich-rule="rule family='ipv4' source address='$ip' reject"
if [ $? -eq 0 ]; then
echo "$(date) - Banned IP: $ip for $count failed attempts" >> "$BAN_LOG"
else
echo "$(date) - Failed to ban IP: $ip" >> "$BAN_LOG"
fi
fi
done
sudo firewall-cmd --reload
echo "$(date) - IP ban process completed" >> "$BAN_LOG"
echo > $LOG_FILE
- 赋予脚本权限
chmod +x xxx.sh
- 然后设置定时任务 我这里设置每 3 个小时执行一次脚本。定时表达式是
0 */3 * * *
- 然后我们查看生成的封禁 IP 日志。不错不错
Thu Jun 6 16:20:01 CST 2024 - Starting IP ban process
Thu Jun 6 16:20:01 CST 2024 - Banned IP: 158.220.111.161 for 3 failed attempts
Thu Jun 6 16:20:01 CST 2024 - Banned IP: 43.135.1.119 for 2 failed attempts
Thu Jun 6 16:20:02 CST 2024 - Banned IP: 161.35.78.86 for 2 failed attempts
Thu Jun 6 16:20:02 CST 2024 - Banned IP: 124.156.205.16 for 2 failed attempts
Thu Jun 6 16:20:02 CST 2024 - Banned IP: 119.28.158.97 for 2 failed attempts
Thu Jun 6 16:20:03 CST 2024 - Banned IP: 101.126.70.112 for 2 failed attempts
Thu Jun 6 16:20:03 CST 2024 - IP ban process completed
- 至此大功告成。
今天介绍的只是一个简单的防止 ssh 爆破登录的方式,封 IP,如果借助第三方工具,我们可以实现更强的功能,这个后续进行分享,敬请期待。
创作不易,如果您觉得这篇文章对你有帮助,不妨给我点个赞,这将是我继续分享优质内容的动力。