转载请注明出处,本文仅用于学习交流,不对之处,恳请指正
部分图片摘取网络,如有侵权请联系
最近我的homelab的前端服务器莫名其妙被美国的脚本小子看上了,闲来无事上去打了下lastb,好家伙,近10万条尝试登录的信息。虽然我用的是publickey登录的方式,但是这些小可爱还是不厌其烦的跑着雷打不动的脚本。
既然如此,那么就写个脚本自动拉黑这些IP吧,如果使用SSH pam_tally2模块来限制账号登录,对我来说,也是挺不方便的。这里就暂时不展开描述了,如果有需要我在进行补充。
我的自动拉黑方案是,使用crontab每分钟读取一次/var/log/secure最后一分钟的日志,尝试登录超过3次失败的,则自动加入黑名单,并将拉黑的记录写入/var/log/sshd_ban.log中。需求有了,那么就是实现的过程了。
1. Firewall-cmd
因为CentOS8默认是不支持/etc/hosts.deny的,推荐使用的是firewall-cmd。相关的命令自行查询
# 新建一个分组来存放我们封锁的IP
firewall-cmd --permanent --zone=public --new-ipset=sshd_ban --type=hash:net
# 设置该组的防火墙规则
firewall-cmd --permanent --zone=public --add-rich-rule='rule source ipset=sshd_ban drop'
# 重载一下防火墙
firewall-cmd --reload
# 使用firewall-cmd --list-all可以列出全部服务
# 使用firewall-cmd --info-ipset=sshd_ban可以列出分组的信息
2. 编写脚本
我是新建了一个文件夹来存放我的cron脚本,方便以后管理
# 新建文件夹
mkdir /etc/cron.script
# 创建脚本文件
touch /etc/cron.script/sshd_ban.sh
# 或者直接nano也是可以的
在脚本中写入如下代码,代码我都做了相关的注释,就不详细展开解释了
#!/bin/bash
# 自动封锁恶意IP
#
# 防火墙命令
# firewall-cmd --permanent --zone=public --new-ipset=sshd_ban --type=hash:net
# firewall-cmd --permanent --zone=public --add-rich-rule='rule source ipset=sshd_ban reject'
# firewall-cmd --permanent --zone=public --add-rich-rule='rule source ipset=sshd_ban drop'
# firewall-cmd --reload
# firewall-cmd --list-all
# firewall-cmd --info-ipset=sshd_ban
# 查询一分钟前的的secure内容
start_ban_time=$(date -d '1 minutes ago' "+%h %-d %H:%M:%S")
# 转成数组
arr_ban_date=(${start_ban_time})
# 查询新的内容
cat /var/log/secure | awk '$1 >= target_month && $2 >= target_day && $3 >=target_time' target_month="${arr_ban_date[0]}" target_day="${arr_ban_date[1]}" target_time="${arr_ban_date[2]}" | awk '/Failed|invalid user/{print $(NF-3)}'|sort|uniq -c|awk '{print $2"="$1;}' > /var/log/sshd_attack.log
# 标记防火墙更新
firewall_update=0
# 检查是否需要更新黑名单
for i in `cat /var/log/sshd_attack.log`
do
IP=`echo $i |awk -F= '{print $1}'`
NUM=`echo $i|awk -F= '{print $2}'`
# 检查IP是否有效
VALID_CHECK=$(echo $IP|awk -F. '$1<=255&&$2<=255&&$3<=255&&$4<=255{print "yes"}')
if echo $IP|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
if [ ${VALID_CHECK:-no} == "yes" ]; then
# 超过3次,加入黑名单
if [ ${NUM} -gt 3 ]; then
# 写入更新时间
# 只需要写一次
if [ ${firewall_update} -eq 0 ]; then
# 换行
echo >> /var/log/sshd_ban.log
# 当前时间
current_time=$(date "+%h %-d %H:%M:%S")
echo "#-------- ${current_time} --------" >> /var/log/sshd_ban.log
fi
echo "# Warning! ${IP} trial to log in ${NUM} times" >> /var/log/sshd_ban.log
echo "firewall-cmd --zone=public --ipset=sshd_ban --add-entry=${IP}/24" >> /var/log/sshd_ban.log
echo -n "# " >> /var/log/sshd_ban.log
firewall-cmd --zone=public --ipset=sshd_ban --add-entry=${IP}/24
echo "firewall-cmd --permanent --zone=public --ipset=sshd_ban --add-entry=${IP}/24" >> /var/log/sshd_ban.log
echo -n "# " >> /var/log/sshd_ban.log
firewall-cmd --permanent --zone=public --ipset=sshd_ban --add-entry=${IP}/24
# 标记防火墙更新
firewall_update=1
fi
fi
fi
done
# 判断是否有防火墙更新
if [ ${firewall_update} -eq 1 ]; then
echo "# firewall-cmd --reload" >> /var/log/sshd_ban.log
# 重载
# echo -n "# " >> /var/log/sshd_ban.log
# firewall-cmd --reload
fi
# 定时脚本说明
# nano /etc/crontab
# 每1分钟执行一次sshd_ban脚本
# 根据sshd_ban的内容设定
# 相当于每1分钟, 超过3次错误则加入黑名单
# */1 * * * * root sh /etc/cron.script/sshd_ban.sh >> /var/log/sshd_ban.log 2>&1
3. 开启定时任务
在Linux中,一般使用crontab来管理定时任务,使用起来也很方便,我们只要根据对应的规则在/etc/crontab中写入对应的代码即可
# 定时脚本说明
# nano /etc/crontab
# 每1分钟执行一次sshd_ban脚本
# 根据sshd_ban的内容设定
# 相当于每1分钟, 超过3次错误则加入黑名单
# */1 * * * * root sh /etc/cron.script/sshd_ban.sh >> /var/log/sshd_ban.log 2>&1
* * * * * root sh /etc/cron.script/sshd_ban.sh >> /var/log/sshd_ban.log 2>&1
文章评论