1. 场景还原
在登录阿里云或者其它有公网IP的云服务器时,我们可能收到如下类似"There was xxx failed login attempt since the last successful login"的提示:
Last failed login: Mon Apr 15 07:50:57 CST 2024 from 47.xxx.241.xxx on ssh:notty
There were 34 failed login attempts since the last successful login.
Last login: Sun Apr 14 17:23:47 2024 from 220.xxx.252.xxx
Welcome to Alibaba Cloud Elastic Compute Service !
2. 出现原因
首先需要说明的是:这种情况是很正常的。互联网上存在大量的恶意机器人,它们会定期扫描互联网上的服务器,并尝试进行未经授权的访问。这些恶意机器人可能是用于进行暴力破解的自动化工具,也可能是被黑客操控的僵尸网络中的一部分,我们需要做的是设置复杂的服务器密码并采取一些其它可选的措施增强服务器安全。
3. 查看登录失败的IP
首先,我们可以运行命令查看登录失败的IP地址和次数
CentOS
grep "Failed password for invalid user" /var/log/secure | awk '{print $13}' | sort | uniq -c | sort -nr
输出:
[root@aliyun ~]# grep "Failed password for invalid user" /var/log/secure | awk '{print $13}' | sort | uniq -c | sort -nr
216 47.92.115.49
31 139.196.253.42
15 47.110.241.117
1 124.222.144.28
第一列表示登录失败的次数,第二列表示攻击此服务器的IP,有些失败登录尝试可能来自于内部网络或本地主机,因此需要自行分析这些 IP 。
Ubuntu
sudo grep 'authentication failure' /var/log/auth.log | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | sort | uniq -c | sort -nr
4. 安全措施
除了设置更复杂的服务器密码,还有下列可选的安全措施:
将登录失败的IP添加到/etc/hosts.deny文件中
如果一个客户端的 IP 地址与 /etc/hosts.deny
文件中的规则匹配,那么对应的服务将会拒绝该客户端的连接请求(详情请参考5. 拓展知识)。
1. 编写脚本
创建一个 shell 脚本,用于批量将登录失败次数超过 3 次的 IP 地址添加到 /etc/hosts.deny
文件中,次数请自行修改。以下是CentOS和Ubuntu的示例脚本 block_ips.sh:
CentOS:
#!/bin/bash
# 定义日志文件路径和失败次数阈值
LOG_FILE="/var/log/secure"
THRESHOLD=3
# 解析日志文件,获取登录失败的 IP 地址及其失败次数
FAILED_IPS=$(grep 'Failed password' $LOG_FILE | awk '{print $(NF-3)}' | sort | uniq -c | awk -v threshold=$THRESHOLD '$1 >= threshold {print $2}')
# 遍历失败次数超过阈值的 IP 地址,并将其添加到 /etc/hosts.deny 文件中
for IP in $FAILED_IPS; do
if ! grep -q $IP /etc/hosts.deny; then
echo "sshd: $IP" >> /etc/hosts.deny
fi
done
Ubuntu:
#!/bin/bash
# 定义日志文件路径和失败次数阈值
LOG_FILE="/var/log/auth.log"
THRESHOLD=3
# 解析日志文件,获取登录失败的 IP 地址及其失败次数
FAILED_IPS=$(grep 'authentication failure' $LOG_FILE | awk '{print $(NF-3)}' | sort | uniq -c | awk -v threshold=$THRESHOLD '$1 >= threshold {print $2}')
# 遍历失败次数超过阈值的 IP 地址,并将其添加到 /etc/hosts.deny 文件中
for IP in $FAILED_IPS; do
if ! grep -q $IP /etc/hosts.deny; then
echo "sshd: $IP" >> /etc/hosts.deny
fi
done
2. 设置脚本权限:
为脚本添加执行权限:
chmod +x block_ips.sh
3. 配置定时任务
使用 cron job来定期运行脚本。运行 crontab -e
命令:
crontab -e
然后添加以下行来配置 cron job:
# 每小时运行block_ips脚本
0 * * * * /path/to/block_ips.sh
或者 设置每天凌晨2点运行:
# 每天凌晨2点运行block_ips脚本
0 2 * * * /path/to/block_ips.sh
确保将 /path/to/block_ips.sh
替换为实际的脚本路径。
这样,脚本将每小时运行一次,检查 /var/log/auth.log
文件中的失败登录次数,并将失败次数超过 3 次的 IP 地址添加到 /etc/hosts.deny
文件中。
配置网络防火墙
如果你想减少被攻击的次数,可以尝试配置网络防火墙,如果你有固定IP或者你所在区域运营商分配的IP只在一定范围内变化,可以采取此措施。
请谨慎配置防火墙:请确保你有固定的IP或者你所在的运营商有固定的IP段,并且这些IP段能正常访问你的服务器,如果你按照此配置无法访问服务器,请自行负责。
这里只介绍系统内防火墙的配置,其它云服务器外置的防火墙配置请自行查阅文档。
CentOS:
1. 开启防火墙服务
CentOS 内置的防火墙服务是 firewalld,
运行命令查看服务是否运行:
firewall-cmd --state
如果输出running,表示服务正常运行
[root@tools ~]# firewall-cmd --state
running
如果输出not running,请运行下面的脚本开启防火墙:
systemctl start firewalld
2. 将允许访问的IP或IP段添加到防火墙允许列表
例如我需要将我所在区域的IP段113.246.0.0/16添加到防火墙,自己的运营商IP段请百度搜索ip就能得到,得到的IP一般取前两位,子网掩码长度取16,如果你需要指定IP访问,请自行修改命令中的IP
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="113.246.0.0/16" port protocol="tcp" port="22" accept'
3. 移除防火墙中的ssh service
如果你之前没有处理过防火墙规则,默认ssh服务是在防火墙运行列表中的,运行下面的命令查看:
firewall-cmd --zone=public --list-all
输出:
[root@aliyun ~]# firewall-cmd --zone=public --list-all
public
target: default
icmp-block-inversion: no
interfaces:
sources:
services: dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
因为我们只想让指定IP访问,所以需要将ssh移除,运行下面的命令移除服务:
firewall-cmd --permanent --remove-service=ssh
4. 重新加载防火墙规则
运行下面的命令以确保规则生效:
firewall-cmd --reload
查看已添加的规则:
firewall-cmd --list-rich-rules
Ubuntu:
在 Ubuntu 中,可以使用 ufw
(Uncomplicated Firewall)工具来管理防火墙规则
1. 启用 ufw
运行下面的命令启用ufw:
sudo ufw enable
如果没有安装ufw服务,请运行:
sudo apt install ufw
2. 添加允许的规则:
假设你想允许 113.246.0.0/16 这个 IP 段访问 SSH 服务,可以使用以下命令添加规则:
sudo ufw allow from 113.246.0.0/16 to any port 22
3. 验证规则
可以使用以下命令查看 ufw
的规则是否正确添加:
sudo ufw status
这将列出当前的 ufw
规则,你应该能够看到包含 SSH 规则的条目
5. 拓展知识
/etc/hosts.deny文件
/etc/hosts.deny
文件是用于配置 TCP Wrapper 的一个文件,它用于限制对系统服务的访问。TCP Wrapper 是一个用于控制网络服务访问的工具,它允许你在服务启动之前拒绝或允许连接请求。
在 /etc/hosts.deny
文件中,你可以指定哪些客户端或 IP 地址被拒绝访问特定的服务。如果一个客户端的 IP 地址与 /etc/hosts.deny
文件中的规则匹配,那么对应的服务将会拒绝该客户端的连接请求。
通常,你可以在这个文件中添加类似如下的条目:
sshd: 192.168.1.100
这个条目表示拒绝来自 IP 地址为 192.168.1.100
的客户端对 sshd
服务(SSH)的连接请求。
CentOS7防火墙操作
查看
查看防火墙服务是否运行:
systemctl status firewalld
查看firewall运行状态:
firewall-cmd --state
列出所有规则:
firewall-cmd --zone=public --list-all
查看规则列表:
firewall-cmd --list-rich-rules
查看source:
firewall-cmd --permanent --zone=public --list-sources
添加
添加IP:
firewall-cmd --permanent --zone=public --add-source=192.168.100.0/24
添加服务:
firewall-cmd --permanent --add-service=ssh
允许IP访问指定端口:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="103.0.0.0/8" port protocol="tcp" port="22" accept'
添加端口:
firewall-cmd --permanent --zone=public --add-port=3306/tcp
删除
移除服务:
firewall-cmd --permanent --remove-service=ssh
移除规则:
firewall-cmd --permanent --remove-rich-rule 'rule family="ipv4" source address="103.0.0.0/8" port protocol="tcp" port="22" accept'
移除端口:
firewall-cmd --permanent --zone=public --remove-port=3306/tcp
重新加载
firewall-cmd --reload