使用环境:
通过elk等工具,发现web服务器经常受到公网的非法请求(如下图),所以增加自动封禁脚本。
此方式是在被请求成功后根据日志内容进行关键字筛选 然后封禁; 如果有 在被请求前 进行阻止的方式 可以告知我,感谢!
自动封禁脚本内容:
#!/bin/bash
##过滤nginx日志,且日志首个字段为来源IP地址,第七个字段为URL请求地址
##使用iptables封禁80 443端口
##建议配合nginx日志每天切割脚本一起使用
##将脚本放置crontab中,每几分钟循环执行
##建议在iptables先添加完白名单后,再执行本脚本,方式误封无法访问!
#时间格式 2024-03-15 10:09:06
shiJian=`date "+%Y-%m-%d %H:%M:%S"`
riQi=`date "+%Y-%m-%d"`
#nginx日志目录 每条日志首内容为来源IP
logDir='/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/'
logFile='access.log'
#执行日志
zxlogDir='/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/'
mkdir -p ${zxlogDir}
##################################本次执行过滤恶意访问IP###################################
###############################URL过滤关键字#######################################
#使用awk将 行号 访问IP URL地址 输出到具体文件
#1 1XX.XX.XX.XX /XXXXXX/XXXXX/XXXXX/XXXXX/XXXXXX
#2 1XX.XX.XX.XX /XXXXXX/XXXXX/XXXXX/XXXXX/XXXXXX
#awk -F " " '{printf NR"\t"$1"\t"$7 "\n"}' ${logDir}${logFile} > ${zxlogDir}wenjian1.txt
#使用awk将 URL地址 输出到具体文件
#/XXXXXX/XXXXX/XXXXX/XXXXX/XXXXXX
#/XXXXXX/XXXXX/XXXXX/XXXXX/XXXXXX
#awk -F " " '{printf $7 "\n"}' ${logDir}${logFile} > ${zxlogDir}wenjian1.txt
awk -F " " '{printf "%s",$7"\n"}' ${logDir}${logFile} > ${zxlogDir}wenjian1.txt
#URL过滤关键字数组
urlgjzshuzu=(
passwd
password
\/bin\/
\/etc\/
\/home\/
\/admin\/
\/database\/
\/env
\\.php$
\\.sql$
\\.jsp$
\\.gz$
\\.pl$
)
for urlgjz in "${urlgjzshuzu[@]}"
do
#循环执行过滤URL关键字 输出行号和URL 到文件2
#1:/admin/XXXXX/XXXXX/XXXXX/XXXXXX
#2:/etc/XXXXX/XXXXX/XXXXX/XXXXXX
#awk '{printf $3 "\n"}' ${zxlogDir}wenjian1.txt | grep -n "${urlgjz}" > ${zxlogDir}wenjian2.txt
grep -n "${urlgjz}" ${zxlogDir}wenjian1.txt >> ${zxlogDir}wenjian2.txt
done
#将行号 输出到hanghaoJiHe文件
#1
#2
awk -F ":" '{printf $1 "\n"}' ${zxlogDir}wenjian2.txt > ${zxlogDir}hanghaoJiHe.txt
#置空文件2
cat /dev/null > ${zxlogDir}wenjian2.txt
#根据行号 匹配访问IP 输出到临时1文件
#1XX.XX.XX.XX
#1X.XX.XX.XX
sort ${zxlogDir}hanghaoJiHe.txt|uniq |while read hanghao
do
#sed -n "${hanghao}p" ${zxlogDir}wenjian1.txt |awk '{printf $2 "\n"}' >> ${zxlogDir}linshi1.txt
sed -n "${hanghao}p" ${logDir}${logFile} |awk '{printf $1 "\n"}' >> ${zxlogDir}linshi1.txt
done
###############################过滤所有关键字#######################################
#过滤所有关键字数组
sygjzshuzu=(
baidu\.com
google\.com
https\:\/\/XX\.XXX\.XXX\.XX\/
)
for sygjz in "${sygjzshuzu[@]}"
do
#循环执行过滤关键字 将存在恶意关键字请求的 IP追加到 临时1文件
grep "${sygjz}" ${logDir}${logFile} |awk '{printf $1 "\n"}'|sort |uniq >> ${zxlogDir}linshi1.txt
done
###############################部分去重逻辑#######################################
#排序并去重 临时1文件(本次运行初步过滤的IP),覆盖到临时2文件(本次运行去重的恶意IP);删除临时1文件
sort ${zxlogDir}linshi1.txt |uniq > ${zxlogDir}linshi2.txt
cat /dev/null > ${zxlogDir}linshi1.txt
#将时间 和 临时2文件 记录到永久记录文件
mkdir -p ${zxlogDir}yongjiu/
echo "###${shiJian}" >> ${zxlogDir}yongjiu/${riQi}.txt
echo "`cat ${zxlogDir}linshi2.txt`" >> ${zxlogDir}yongjiu/${riQi}.txt
##################################解封历史限制###################################
#设置解封哪天的恶意IP
lastdate=`date +%Y-%m-%d --date="-8 day"`
jiefengFile=${zxlogDir}yongjiu/${lastdate}_5.txt
#判断文件 存在且非空
if [ -s "${jiefengFile}" ]
then
#cat ${jiefengFile} | while read jfiptime
for jfiptime in `cat ${jiefengFile}`
do
#将每个ip 时间段输出到一个临时文件,偌不执行此步骤会报错awk: cannot open 141.98.7.67>2024-03-27_15:20:02
echo $jfiptime > ${zxlogDir}linshi3.txt
#循环执行 解封恶意IP地址
jfip=`awk -F ">" '{printf $1 "\n"}' ${zxlogDir}linshi3.txt`
jftime=`awk -F ">" '{printf $2 "\n"}' ${zxlogDir}linshi3.txt`
/usr/sbin/iptables -D INPUT -s ${jfip} -p tcp -m multiport --dport 80,443 -j DROP -m comment --comment "nginx日志检测恶意访问IP ${jftime}"
echo "###${jfip} ${shiJian} del封禁" >> ${zxlogDir}yongjiu/${riQi}.txt
cat /dev/null > ${zxlogDir}linshi3.txt
done
else
echo "###${jiefengFile}文件不存在,或者文件为空,未删除封禁" >> ${zxlogDir}yongjiu/${riQi}.txt
fi
##################################新增封禁###################################
#过滤 排序 并去重 当天永久文件,覆盖输出为永久文件2(当天恶意IP 去重)
egrep -v "###|add|del|^$|禁" ${zxlogDir}yongjiu/${riQi}.txt |sort | uniq > ${zxlogDir}yongjiu/${riQi}_2.txt
#过滤 防火墙规则 是否已存在封禁中,输出至永久文件3(当天防火墙存在封禁记录 去重)
/usr/sbin/iptables -nL|grep "443"|grep DROP|grep "nginx日志检测恶意访问IP" |awk '{printf $4 "\n"}'|cut -d "/" -f1 |sort|uniq >${zxlogDir}yongjiu/${riQi}_3.txt
#比对 临时2文件(本次运行恶意IP去重版)和 当天永久文件3(当天防火墙存在记录)的差异 ,覆盖至永久文件4(对比差异文件)
duiBi=`diff ${zxlogDir}linshi2.txt ${zxlogDir}yongjiu/${riQi}_3.txt |grep '<'| awk '{printf $2 "\n"}'`
echo ${duiBi} > ${zxlogDir}yongjiu/${riQi}_4.txt
sed -i "s/ /\n/g" ${zxlogDir}yongjiu/${riQi}_4.txt
#判断,对比的内容,是否有新增恶意IP
if [ -n "${duiBi}" ]
then
cat ${zxlogDir}yongjiu/${riQi}_4.txt | while read ip
do
#循环执行 封堵本次查询新产生的 恶意IP地址
fengjintime=`date "+%Y-%m-%d_%H:%M:%S"`
/usr/sbin/iptables -A INPUT -s ${ip} -p tcp -m multiport --dport 80,443 -j DROP -m comment --comment "nginx日志检测恶意访问IP ${fengjintime}"
echo "${ip} ${fengjintime} add封禁">> ${zxlogDir}yongjiu/${riQi}.txt
#永久5文件 记录当天封禁的IP 时间,设置>为分隔符,若不设置则删除封禁的循环会以空格执行
echo "${ip}>${fengjintime}">> ${zxlogDir}yongjiu/${riQi}_5.txt
done
else
echo "###${shiJian} no新增恶意IP" >> ${zxlogDir}yongjiu/${riQi}.txt
fi
##################################删除200天未修改的文件###################################
find ${zxlogDir} -type f -mtime +200 -exec rm -rf {} \;
脚本介绍与注意事项:
1、访问日志文件 不宜过大,否则影响过滤效率。建议使用其他脚本等方式每天切割日志。
2、本环境使用为nginx,且access.log日志的第一个字段为IP
3、请自行更改 web日志目录 和 本脚本执行日志目录 XXXXXXXXXXXX内容,/开头结尾。
4、请根据业务的实际请求,自行修改封禁关键字,防止误封。
5、执行前请先执行白名单放行策略,再执行本脚本,防止误封。
6、本脚本涉及iptables命令,需要放置在root用户中 crontab 定时任务中执行。
7、本脚本会产生如下 执行日志:
linshi1.txt 本次执行 根据封禁关键字,过滤的IP (后续自动删除)
linshi2.txt 本次执行 排序去重后的linshi1.txt文件,违规IP,并追加到yongjiu/${riQi}.txt (自动覆盖)
linshi3.txt 本次执行 拆分封禁IP 封禁时间(yongjiu/${riQi}_5.txt) 后的每条记录 (后续自动删除)
yongjiu/${riQi}.txt 记录当天 执行结果内容,和违规IP (每次追加)
yongjiu/${riQi}_2.txt 记录当天去重后的违规IP (自动覆盖)
yongjiu/${riQi}_3.txt 记录当天防火墙存在的封禁IP (自动覆盖)
yongjiu/${riQi}_4.txt 对linshi2.txt和_3文件比较,仅保留本次新的违规IP (自动覆盖)
yongjiu/${riQi}_5.txt 记录当天封禁的IP与封禁时间文件 (每次追加)