随意翻阅 /var/log/secure 日志文件,即可发现如下一组记录(其中 IP 地址后的数字代表失败尝试次数):
118.33.110.52=2834
119.145.254.77=37
121.254.179.199=226
121.88.250.243=35
200.29.110.104=168
202.78.173.199=250
222.221.2.210=373
在这些 IP 中,仅有 119.145.254.77 和 121.88.250.243 属于正常访问,其余均为恶意 IP。由于服务器部署在 LVS 集群后端,最初计划利用 iptables 的 recent 模块进行封禁,但该方案行不通——系统运行 CentOS 5.5 x86_64,其 iptables 并不支持该模块,报错如下:
iptables: Unknown error 18446744073709551615
服务器承载着关键业务,为避免升级内核影响线上稳定性,因此暂时放弃了 iptables 方案。随后考虑使用 hosts.deny 进行封禁,但手动操作繁琐,于是决定编写自动化脚本处理。脚本内容如下:
#! /bin/bash
cat /var/log/secure|awk '/Failed/{print $(NF-3)}'|sort|uniq -c|awk '{print $2"="$1;}' > /root/black.txt
DEFINE="100"
for i in `cat /root/black.txt`
do
IP=`echo $i |awk -F= '{print $1}'`
NUM=`echo $i|awk -F= '{print $2}'`
if [ $NUM -gt $DEFINE ];
then
grep $IP /etc/hosts.deny > /dev/null
if [ $? -gt 0 ];
then
echo "sshd:$IP" >> /etc/hosts.deny
echo "vsftpd:$IP" >> /etc/hosts.deny
fi
fi
done
脚本逻辑非常简单:/var/log/secure 日志按周轮转,每次读取该文件后,通过 shell 统计登录失败次数较多的 IP,并设定阈值 100——若某 IP 的失败次数超过 100,则将其追加至 /etc/hosts.deny,从而阻止其对 sshd 和 vsftpd 的访问。随后将脚本放入 crontab 定时执行,实现周期性排查。当再次检测到同一 IP 时,脚本会先检查其是否已在黑名单中,若已存在则跳过,否则继续添加。
在 /etc/crontab 里加上这样一行:
* */1 * * * root sh /root/hosts_deny.sh
该脚本每隔一小时执行一次。需要说明的是,/var/log/secure 日志每周轮转一次,因此执行周期可根据服务器实际负载灵活调整;若攻击频繁,可适当缩短间隔时间。
运行一段时间后,/etc/hosts.deny 文件的内容变成了这样:
sshd:119.145.254.77
vsftpd:119.145.254.77
sshd:222.221.2.210
vsftpd:222.221.2.210
sshd:118.218.136.25
vsftpd:118.218.136.25
sshd:118.33.110.52
vsftpd:118.33.110.52
sshd:123.196.113.11
vsftpd:123.196.113.11
sshd:14.140.172.74
vsftpd:14.140.172.74
sshd:200.29.110.104
vsftpd:200.29.110.104
sshd:202.102.89.81
vsftpd:202.102.89.81
sshd:202.78.173.199
vsftpd:202.78.173.199
效果立竿见影,这些恶意 IP 再也无法通过 SSH 和 vsftpd 进行攻击。这种基于日志分析的自动封禁方法,虽然实现简单,但在实际运维中非常实用有效。
