防止别人一直ssh本机,首先建议更改ssh默认端口,其次使用iptables编写脚本防御
# 因为firewalld其实底层也是iptables所以本文直接使用iptables
关闭selinux、firewalld防火墙
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
systemctl stop firewalld
systemctl disable firewalld
安装iptables
yum -y install iptables-services
systemctl start iptables # 启动iptables后,firewalld自动就会关闭
systemctl enable iptables
# 查看iptables规则命令
iptables -nL --line-number
# 清除iptables规则命令
iptables -F
iptables -X
iptables -Z
iptables基本使用
请在虚拟机测试iptables命令,别直接上生产环境
#将iptables规则保存到文件/etc/sysconfig/iptables
service iptables save
#禁止源ip151主机访问本机任何端口,指定端口可以添加 -p tcp --dport 22
iptables -t filter -I INPUT -s 192.168.159.151 -j DROP
#禁止这个网段的数据包访问本机任何端口
iptables -t filter -I INPUT -s 192.168.151.0/24 -j DROP
#禁止ip访问本机多个端口,(本次脚本使用此命令)
iptables -t filter -I INPUT -s 192.168.159.202 -p tcp -m multiport --dport 22,221,2211,80,443 -j DROP
定时任务
将脚本每30分钟执行一次(路径改为实际脚本存放路径)
*/30 * * * * /usr/local/script/iptables.sh &>>/usr/local/script/iptables_$(date +\%F_\%T).log
脚本思路
1. 从/var/log/secure文件中找出访问本机失败的ip、将ip存放到指定文件A,并加上当前系统时间
2. 将访问本机失败的ip,统计次数放到一个文件B(仅为了查看哪些ip在攻击、是否还在攻击)
3. 封禁ip:循环这些ip、假如文件A中有这个ip、不做操作
没有这个ip、说明没有进行访问限制、执行iptables命令限制、并记录此ip到文件A中
4. 解除封禁:第二次循环ip,判断ip后面的时间+封禁的天数 < 当前时间
执行删除此ip的iptables命令限制
举例 2023年10月15日 上午8点整封禁的192.168.159.151这个ip
那么文件记录的内容是 192.168.159.151 #202310150800
假如我们要禁止此ip 2天、那就看当前时间是否大于 202310150800+20000
#!/bin/bash -l
#2023-10-15
#自动检测IP暴力破解,禁止IP登录sshd服务
systemctl start iptables || exit 9
START_TIME=$(date +%Y%m%d%H%M)
IP_LIST="/tmp/iptables.txt" # 存放被封禁的ip
IPTABLES_RULE="/etc/sysconfig/iptables" # iptables默认配置规则
IP_LIST2="/tmp/ip_$(date +%F_%T).log" # 存放攻击ip的次数
[ -f ${IP_LIST} ] || touch ${IP_LIST}
#封禁ip
refuse_ip() {
# 查找登录失败超过20次的ip
REFUSE_IP=$(grep -i "failed" /var/log/secure |egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}" |sort -nr |uniq -c|awk '$1>=20 {print $2}')
echo -e "输出要封禁的ip \n${REFUSE_IP}"
#存放每个ip攻击的次数、方便排查
echo "$(grep -i "failed" /var/log/secure |egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}" |sort -nr |uniq -c|sort -n -k 1,1)" > $IP_LIST2
for i in ${REFUSE_IP}
do
echo "---- $i"
[ -z "${i}" ] && { echo "当前没有要封禁的ip" ; continue ; }
# IP失败次数达到20就加入iptables防火墙禁止登录ssh服务48小时
if [ $(grep -c ${i} ${IP_LIST}) -eq 0 ];then # ip已经在禁止文件中 不做处理,否则开始封禁
iptables -t filter -I INPUT -s "${i}" -p tcp -m multiport --dport 22,221,2211,80,443,3306 -j DROP
echo "${i} #${START_TIME}" >>${IP_LIST} # 将封禁的ip、时间存放到文件
echo "新增封禁的ip ${i}"
else
echo "${i} 已被封禁"
fi
done
}
#解除ip
delete_ip() {
# 查询IP封停时间,大于等于48小时就删除此IP(解封此ip)
END_TIME=$(date +%Y%m%d%H%M)
DELETE_IP_LIST=$(egrep -v "^$|^#" ${IP_LIST} |awk -F'#' '{print $1,$2}' |awk '{if('${END_TIME}'>=$2+20000) print $1}')
[ -z "${DELETE_IP_LIST}" ] && { echo "当前没有到期的ip" ; } || { echo -e "要解除的ip \n${DELETE_IP_LIST}" ; }
for j in ${DELETE_IP_LIST}
do
iptables -t filter -D INPUT -s "${j}" -p tcp -m multiport --dport 22,221,2211,80,443,3306 -j DROP
sed -i "/${j}/d" ${IP_LIST}
echo "已解除封禁的ip ${j}"
done
}
refuse_ip
delete_ip
service iptables save
iptables -nvL --line-numbers
echo -e "查看当前封禁ip列表 \n$(cat ${IP_LIST})"
echo -e "查看当前防火墙规则 \n$(cat ${IPTABLES_RULE})"
本地测试结果
iptables -nL --line-number # 查看当前规则
lastb | head -10 # 查看最近10条 访问本机失败的ip
tailf /var/log/secure | grep -i Failed