分享一个自动封禁恶意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/bashsource /etc/profilelog_path=/data/blacklistnow_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 donedone}
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=$1results=$(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 donefi}msg="start 启动IP自动封禁log 打印访问IP记录logs 显示nginx实时日志kill 手动封禁单IPshow 显示当前规则remove 手动解封IPurl 查看请求频率最高urluban 解除全部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 ServiceAfter=network.target[Service]User=rootWorkingDirectory=/data/blacklistExecStartPre=/bin/bash -c '/data/blacklist/blacklist.sh uban'ExecStart=/bin/bash -c '/data/blacklist/blacklist.sh start'Restart=on-failureRestartSec=3Environment="PATH=/usr/local/bin:/usr/bin:/bin"[Install]WantedBy=multi-user.target
注:需要将路径修改为实际脚本位置。
重新加载systemd配置并设置开机启动:
systemctl daemon-reloadsystemctl enable blacklistsystemctl start blacklist
四、脚本其他常用功能
1.查看状态码统计
查看状态码分布情况:
查看指定状态码详细日志:
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访问日志
5.查看请求url统计
全站请求url统计详情:
单独blog站点的url统计详情:
6.查看指定IP历史封禁记录
sh blacklist.sh showlog 192.168.1.100
扩展说明:
1.脚本中所有涉及iptables的操作都需要root权限。
2.脚本默认监控日志为/var/log/nginx/access.log,如果Nginx日志在其他位置需要修改脚本中的路径。
阅读原文:点击这里
该文章在 2026/8/5 11:15:17 编辑过