基于Nginx日志通过iptables自动封禁恶意IP的脚本
分享一个自动封禁恶意IP的脚本,这个脚本的核心框架来源于互联网上某位大佬的分享,在其基础上结合了日常生产环境使用情况做了本地化的适配,分享出来供大家参考。
这个脚本的核心逻辑是:实时监控Nginx访问日志,当发现异常状态码(400、403、404、500)的时候,通过调用iptables命令来实现封禁恶意IP功能。
一、Nginx日志格式调整
为了方便获取Nginx访问日志的状态码和客户端IP,需要调整Nginx日志格式:
a.将status字段调整到末位;
b.将host字段调整到倒数第二位;
c.将remote_addr字段调整到首位;
d.将http_x_forwarded_for字段调整到正数第二位,并使用双引号括起来。
其他字段可以根据需要自定义,我的Nginx日志格式配置如下:
log_format main '$remote_addr "$http_x_forwarded_for" $remote_user [$time_local] "$request" '
'$body_bytes_sent "$http_referer" "$http_user_agent" '
'"$request_time" "$upstream_response_time" "$scheme" "$host" $status'; 二、部署IP封禁脚本
1.初始化环境
部署脚本的时候,需要修改脚本中log_path字段为脚本所在目录,同时在该目录下新建iptables.22文件与info、iptables文件夹:

比如将脚本放在/data/blacklist目录下,可以用如下命令建立:
mkdir -p /data/blacklist/{info,iptables}
iptables-save > /data/blacklist/iptables.22 2.自动封禁IP脚本完整内容
#!/bin/bash
source /etc/profile
log_path=/data/blacklist
now_time=$(date "+%Y-%m-%d %H:%M:%S")
start(){
BAN_CODES="400 404 403 500"
while true; do
tail -n 0 -F /var/log/nginx/access.log |while read -r line; do
CODE=$(echo "$line"|awk '{print $NF}')
if [[ "$BAN_CODES" == *"$CODE"* ]];then
echo "$line" >>$log_path/info/$(date +%Y%m%d).log
IP=$(echo "$line"|awk '{gsub(/\"/,"",$2);print $2}')
if [[ "$IP" == "-" ]];then
IP=$(echo "$line"|awk '{print $1}')
fi
if [[ "$IP" != "127.0.0.1" ]];then
iptables -A INPUT -s $IP -j DROP
echo "$(date "+%Y-%m-%d %H:%M:%S") $IP:已封禁" >>$log_path/log.log
fi
fi
done
done
}
kill(){
iptables -I INPUT -s $1 -j DROP
echo "$now_time 封禁了:$1" >>$log_path/log.log
}
remove(){
iptables -D INPUT -s $1 -j DROP
echo "$now_time 解封了:$1" >>$log_path/log.log
}
show(){
iptables -vnL
}
logs(){
tail -f /var/log/nginx/access.log
}
log(){
awk '{print $1}' /var/log/nginx/access.log |sort |uniq -c|sort -n
}
url(){
awk -v p="${1:-}" '(p == "" || $(NF-1) ~ p) {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -k1 -n -r | more
}
uban(){
iptables -vnL >$log_path/iptables/iptables$(date +%Y%m%d).show
iptables-save >$log_path/iptables/iptables$(date +%Y%m%d).bak
iptables -F
echo "$now_time 清除历史封禁ip" >>$log_path/log.log
iptables-restore <$log_path/iptables.22
echo "$now_time 加载历史封禁规则" >>$log_path/log.log
}
status(){
if [ -n "$1" ];then
awk -v temp=$1 '{if($NF==temp)print $0}' /var/log/nginx/access.log|more
fi
awk '{print $NF}' /var/log/nginx/access.log |sort |uniq -c|sort -n
}
showlog(){
ip=$1
results=$(cat log.log |grep $ip |grep 已封禁 |awk '{print $1}'| sort | uniq)
if [ -z "$results" ];then
echo "未找到该ip封禁记录"
else
for result in $results;do
logdate=$(echo $result |awk '{print $1}')
filename=$(date -d $logdate +%Y%m%d).log
if [ -f "info/$filename" ] ; then
echo "匹配时间:$result"
echo "日志文件名称:$filename"
echo "日志内容:"
cat info/$filename |grep --color=auto $ip
echo "==================================================================================="
echo "==================================================================================="
else
echo "未找到日志文件:$filename"
fi
done
fi
}
msg="start 启动IP自动封禁
log 打印访问IP记录
logs 显示nginx实时日志
kill 手动封禁单IP
show 显示当前规则
remove 手动解封IP
url 查看请求频率最高url
uban 解除全部IP封禁
status 查看日志状态码
showlog 查看封禁IP日志"
case "$1" in
start) start ;;
log) log ;;
url) url $2 ;;
logs) logs ;;
kill) kill $2 ;;
remove) remove $2 ;;
show) show ;;
uban) uban ;;
status) status $2 ;;
showlog) showlog $2 ;;
*) echo "$msg" ;;
esac
三、使用脚本自动封禁IP
1.直接后台启动脚本
nohup sh blacklist.sh start 2.使用systemctl服务管理脚本运行
创建服务文件,复制到/usr/lib/systemd/system/目录下,文件内容如下:
[Unit]
Description=IP Blacklist Monitoring Service
After=network.target
[Service]
User=root
WorkingDirectory=/data/blacklist
ExecStartPre=/bin/bash -c '/data/blacklist/blacklist.sh uban'
ExecStart=/bin/bash -c '/data/blacklist/blacklist.sh start'
Restart=on-failure
RestartSec=3
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
[Install]
WantedBy=multi-user.target 注:需要将路径修改为实际脚本位置。
重新加载systemd配置并设置开机启动:
systemctl daemon-reload
systemctl enable blacklist
systemctl start blacklist 四、脚本其他常用功能
1.查看状态码统计
查看状态码分布情况:
sh blacklist.sh status 查看指定状态码详细日志:
sh blacklist.sh status 404 2.封禁单个IP
sh blacklist.sh kill 192.168.1.100 3.解封指定IP
sh blacklist.sh remove 192.168.1.100 4.实时显示Nginx访问日志
sh blacklist.sh logs 5.查看请求url统计
全站请求url统计详情:
sh blacklist.sh url 单独blog站点的url统计详情:
sh blacklist.sh url blog 6.查看指定IP历史封禁记录
sh blacklist.sh showlog 192.168.1.100 扩展说明:
1.脚本中所有涉及iptables的操作都需要root权限。
2.脚本默认监控日志为/var/log/nginx/access.log,如果Nginx日志在其他位置需要修改脚本中的路径。
正文到此结束
- 本文标签: Shell Linux
- 本文链接: https://blog.eyyyye.com/article/151
- 版权声明: 本文由爱做梦的比特原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权
