太多机器人了,将服务器压的破烂不堪,写了一个脚本,解决这个问题:
- 每小时检测所有IP访问次数,超过 1000 次就添加到 ban.list 中,返回 403
- 检测成功后发送邮件通知
- 这个 nginx 在 Docker 中
#!/bin/bash
# 配置路径及变量
LOG_FILE="/var/logs/nginx/wwwaccess.log"
BAN_FILE="/etc/nginx/conf/ban.www.appinn.list"
NGINX_CONTAINER="nginx-1"
SMTP_SERVER="邮件服务器"
SMTP_PORT="2525"
FROM_EMAIL="发信邮箱"
TO_EMAIL="收信邮箱"
SUBJECT="新添加 ban.list.conf 地址"
MAIL_BODY="/tmp/nginx_ban_mail.txt"
# 查找访问超过1000次的IP(排除403)
BAD_IPS=$(awk '$9 != 403 {print $1}' "$LOG_FILE" | sort | uniq -c | sort -nr | awk '$1 > 1000 {print $2}')
if [ -z "$BAD_IPS" ]; then
echo "没有超限IP"
exit 0
fi
# 标记添加信息
ADD_STR=""
for ip in $BAD_IPS; do
# 确保这个IP还没被ban
if ! grep -q "deny $ip;" "$BAN_FILE"; then
echo "deny $ip;" >> "$BAN_FILE"
ADD_STR="$ADD_STR$ip"$'\n'
fi
done
if [ -z "$ADD_STR" ]; then
echo "无新IP需要ban"
exit 0
fi
# 测试nginx配置
docker exec $NGINX_CONTAINER nginx -t
if [ $? -ne 0 ]; then
echo "nginx 配置测试失败"
exit 1
fi
# 重载nginx配置
docker exec $NGINX_CONTAINER nginx -s reload
if [ $? -eq 0 ]; then
RESTART_INFO="nginx重启成功"
else
RESTART_INFO="nginx重载失败"
fi
# 组织邮件内容
echo -e "新ban IP列表:\n$ADD_STR\n$RESTART_INFO" > "$MAIL_BODY"
# 发送邮件(使用swaks简易SMTP命令行工具)
swaks --server "$SMTP_SERVER" --port "$SMTP_PORT" --tls-optional \
--from "$FROM_EMAIL" --to "$TO_EMAIL" \
--header "Subject: $SUBJECT" --body "$MAIL_BODY"
# 清理临时文件
rm -f "$MAIL_BODY"
我的 SMTP 服务器是用了 smtp to telegram,实际上并没有发信,而是一个 tg 通知。
另外,1000次可能也比较高了,一个正常人类,一个小时能有500次都很不错了。
如果今后服务器还是被压迫的不行,就继续调低这个数值。

