自动封禁恶意 IP 的 Nginx 日志监控脚本(iptables 版本)
简介
上次分享了基于Nginx
配置文件封禁异常访问的IP
的脚本,今天分享基于iptables
+Nginx
封禁异常访问的IP
的脚本。
在运营网站或服务器时,保护系统安全和防范恶意攻击是非常重要的任务之一。
本文将介绍一个自动监控Nginx
日志并封禁恶意IP
的实用脚本,帮助您及时应对恶意攻击,提高系统的安全性。
脚本介绍
在本文中,我们将分享一个基于Bash
脚本的自动封禁恶意IP
的解决方案。
该脚本可以在Nginx
服务器上运行,实时监控访问日志,并根据预设条件自动封禁恶意IP
。这将大大减轻管理员的工作负担,提高服务器的安全性。
实现原理
脚本的实现原理
- 定义起始时间和结束时间,用于过滤出最近
5
分钟内的日志。 - 根据起始时间和结束时间,从
Nginx
日志中提取符合条件的日志并保存到临时文件中。 - 从临时文件中提取出所有的
IP
地址,并保存到另一个临时文件中。 - 处理
IP
地址,只保留前三位,进行排序和去重,并统计每个IP
段的请求次数。 - 根据设定的阈值(默认为
1500
次),筛选出请求次数超过阈值的IP
段,将其封禁。 - 将封禁的
IP
记录到日志文件中。
脚本详解
脚本
#!/bin/bash
# 定义5分钟以前的时间,用于过滤5分钟以前的日志
start_time=$(LC_TIME=en_US.UTF-8 date -d "-5 minutes" "+%d/%b/%Y:%H:%M")
# 定义为当前时间
end_time=$(LC_TIME=en_US.UTF-8 date "+%d/%b/%Y:%H:%M")
# 需要过滤的nginx日志
log="/data/nginx/log/user_access.log"
#排除列表,如有多个可以这样写 '116\\.179\\.37|116\\.177\\.37'
exclude_nets='116\\.179\\.37'
block_ip() {
# 截取5分钟以前至当前的日志
awk -v start="$start_time" -v end="$end_time" -F '[][]' '$2 >= start && $2 <= end' "$log" >/data/nginx/log/tmp_last_minute.log
# 将所有ip都过滤出来,存到临时文件
awk '{print $1}' /data/nginx/log/tmp_last_minute.log >/data/nginx/log/tmp_last_minute_ip.log
# 处理IP,只留前面三位,排除、排序、去重,获取多于1500次请求的ip段,这个数字可以根据实际情况来调整
awk -F '.' '{print $1"."$2"."$3"."}' /data/nginx/log/tmp_last_minute_ip.log | awk -v nets="$exclude_nets" '!($0 ~ nets)' | sort | uniq -c | sort -n | awk '$1 > 1500 {print $2}' >/data/nginx/log/bad_ip_minute.list
# 当ip数大于0时,才会将它写入到封禁IP文件中
ip_n=$(wc -l /data/nginx/log/bad_ip_minute.list | awk '{print $1}')
if [ ${ip_n} -ne 0 ]; then
for ip in $(cat /data/nginx/log/bad_ip_minute.list); do
# 封ip,不能直接封ip段
for ip2 in $(grep "^$ip" /data/nginx/log/tmp_last_minute_ip.log | sort -n | uniq); do
/usr/sbin/iptables -I INPUT -s $ip2 -j REJECT
done
done
# 将这些被封的IP记录到日志里
echo "" >>/data/nginx/log/block_ip2.log
echo "$(date) 封掉的IP段有:" >>/data/nginx/log/block_ip2.log
cat /data/nginx/log/bad_ip_minute.list >>/data/nginx/log/block_ip2.log
fi
# 这句根据需要配置,我这里是因为5分钟的访问量也太多了,导致日志文件体积太大,所以清空一下
cat /dev/null >$log
}
unblock_ip() {
# 先清空计数
/usr/sbin/iptables -Z
# 等待2分钟
sleep 120
# 检查包个数小于5的ip段并记录到一个临时文件里,把它们标记为白名单IP
/usr/sbin/iptables -nvL INPUT | grep REJECT | awk '$1<5 {print $8}' >/data/nginx/log/good_ip2.list
n=$(wc -l /data/nginx/log/good_ip2.list | awk '{print $1}')
if [ $n -ne 0 ]; then
for ip in $(cat /data/nginx/log/good_ip2.list); do
/usr/sbin/iptables -D INPUT -s $ip -j REJECT
done
echo "" >>/data/nginx/log/unblock_ip2.log
echo "$(date) 解封的IP有:" >>/data/nginx/log/unblock_ip2.log
cat /data/nginx/log/good_ip2.list >>/data/nginx/log/unblock_ip2.log
fi
# 当解封完白名单IP后,将计数器清零,进入下一个计数周期
/usr/sbin/iptables -Z
}
# 检查命令行参数
if [[ $# -ne 1 ]]; then
echo "请输入参数,block 或者 unblock。"
exit 1
fi
# 根据命令行参数调用相应的函数
if [[ $1 == "block" ]]; then
block_ip
elif [[ $1 == "unblock" ]]; then
unblock_ip
else
echo "参数输入错误。"
exit 1
fi
如何使用
# 做成定时任务
# 每5分钟执行一次block操作,每2小时执行一次unblock操作
*/5 * * * * root /data/nginx/log/Block_IP_WAF.sh block
0 */2 * * * root /data/nginx/log/Block_IP_WAF.sh unblock
脚本中各部分的详细解释
- 设置起始时间和结束时间: 脚本通过使用
date
命令设置了起始时间和结束时间,起始时间为5
分钟前,结束时间为当前时间。 - 截取日志: 使用
awk
命令根据起始时间和结束时间从Nginx
日志中截取出最近5
分钟内的日志,并保存到临时文件tmp_last_minute.log
中。 - 提取
IP
地址: 使用awk
命令从临时文件中提取出所有的IP
地址,并保存到另一个临时文件tmp_last_minute_ip.log
中。 - 处理
IP
地址: 使用awk
命令对IP地址进行处理,只保留前三位,并进行排序、去重和计数。然后根据设定的阈值(1500
次),筛选出请求次数超过阈值的IP
段,并将其保存到bad_ip_minute.list
文件中。 - 封禁
IP
地址: 当存在需要封禁的IP
段时,使用iptables
命令逐个封禁IP
地址。首先,使用grep
命令根据IP
段提取出具体的IP
地址,然后使用iptables
命令将这些IP
地址添加到封禁列表中。 - 记录封禁的
IP
地址: 将被封禁的IP
段记录到日志文件block_ip2.log
中,包含封禁时间和被封禁的IP
段。 - 解封
IP
地址: 使用iptables
命令清空计数器,等待2
分钟。然后,检查请求次数小于5
次的IP
段,并将其记录到good_ip2.list
文件中,标记为白名单IP
。最后,使用iptables
命令逐个解封白名单IP
。 - 记录解封的
IP
地址: 将被解封的IP
地址记录到日志文件unblock_ip2.log
中,包含解封时间和被解封的IP
地址。
使用方法
脚本接受一个参数,即block
或unblock
,用于执行相应的功能。
通过运行脚本并传入合适的参数,可以实现IP
封禁和解封的操作。
结语
本文介绍了一个自动封禁恶意IP
的Nginx
日志监控脚本。
通过定时运行该脚本,您可以及时发现并封禁恶意IP
,提高服务器的安全性。
希望本文能够帮助您改善服务器安全,并为您的技术工作提供一些灵感。
如有疑问或建议,请随时留言。
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
Linux 小白鼠!
觉得文章不错,打赏一点吧,1分也是爱~
打赏
微信
支付宝