nginx 动态计算拦截非法访问ip
需求:在Nginx上实现一个动态拦截IP的方法,具体是当某个IP在1分钟内访问超过60次时,将其加入Redis并拦截,拦截时间默认1天。
技术选型:使用Nginx+Lua+Redis的方法。这种方案通过Lua脚本在Nginx处理请求时检查Redis中的黑名单,同时统计访问频率,超过阈值就封禁。这应该符合用户的需求。
需要结合Lua脚本和Redis的计数功能。安装OpenResty,配置Nginx的Lua模块,编写Lua脚本统计访问次数,使用Redis存储和过期键,以及设置拦截逻辑。连接池的使用,避免频繁连接Redis影响性能。
一、环境准备
-
安装OpenResty
OpenResty集成了Nginx和Lua模块,支持直接运行Lua脚本:# Ubuntu/Debian sudo apt-get install openresty # CentOS yum install openresty -
安装Redis服务
sudo apt-get install redis-server # Debian系 sudo yum install redis # RedHat系
二、Nginx配置
- 主配置文件(nginx.conf)
在http块中添加共享内存和Lua脚本路径:http {lua_package_path "/usr/local/openresty/lualib/?.lua;;";lua_shared_dict ip_limit 10m; # 共享内存区server {listen 80;server_name _;location / {access_by_lua_file /usr/local/lua/ip_block.lua; # 核心拦截脚本root /var/www/html;}} }
三、Lua脚本实现动态拦截
-
脚本路径
创建Lua脚本:/usr/local/lua/ip_block.lua -
脚本内容
local redis = require "resty.redis" local red = redis:new()-- Redis连接参数 local redis_host = "127.0.0.1" local redis_port = 6379 local redis_timeout = 1000 -- 毫秒 local redis_auth = nil -- 无密码留空-- 拦截参数 local block_time = 86400 -- 封禁时间(1天) local time_window = 60 -- 统计窗口(1分钟) local max_requests = 60 -- 最大请求数-- 获取客户端IP local function get_client_ip()local headers = ngx.req.get_headers()return headers["X-Real-IP"] or headers["x_forwarded_for"] or ngx.var.remote_addr end-- 连接Redis local function connect_redis()red:set_timeout(redis_timeout)local ok, err = red:connect(redis_host, redis_port)if not ok thenngx.log(ngx.ERR, "Redis连接失败: ", err)return nilendif redis_auth thenlocal ok, err = red:auth(redis_auth)if not ok then ngx.log(ngx.ERR, "Redis认证失败: ", err) endendreturn ok end-- 主逻辑 local client_ip = get_client_ip() local counter_key = "limit:count:" .. client_ip local block_key = "limit:block:" .. client_ip-- 检查是否已封禁 local is_blocked, err = red:get(block_key) if tonumber(is_blocked) == 1 thenngx.exit(ngx.HTTP_FORBIDDEN) -- 直接返回403 end-- 统计请求次数 connect_redis() local current_count = red:incr(counter_key) if current_count == 1 thenred:expire(counter_key, time_window) -- 首次设置过期时间 end-- 触发封禁条件 if current_count > max_requests thenred:setex(block_key, block_time, 1) -- 封禁并设置1天过期red:del(counter_key) -- 删除计数器ngx.exit(ngx.HTTP_FORBIDDEN) end-- 释放Redis连接 red:set_keepalive(10000, 100)
四、性能优化
-
Redis连接池
通过set_keepalive复用连接,避免频繁建立TCP连接
-
共享内存缓存
使用lua_shared_dict缓存高频访问IP,减少Redis查询压力
-
异步日志记录
封禁操作异步写入日志文件,避免阻塞请求处理:ngx.timer.at(0, function()local log_msg = string.format("%s - IP %s blocked at %s", ngx.var.host, client_ip, ngx.localtime())local log_file = io.open("/var/log/nginx/blocked_ips.log", "a")log_file:write(log_msg, "\n")log_file:close() end)
五、验证与测试
-
手动触发封禁
# 模拟高频请求 ab -n 100 -c 10 http://your-domain.com/ # 检查Redis redis-cli keys "limit:block:*" -
自动解封验证
等待24小时后检查封禁IP是否自动删除:redis-cli ttl "limit:block:1.2.3.4" # 返回剩余秒数
六、扩展方案
-
分布式封禁
在多台Nginx服务器间共享Redis黑名单,实现集群级拦截
-
可视化监控
通过Grafana+Prometheus展示实时拦截数据:# 采集Redis指标 prometheus-redis-exporter --redis.address=localhost:6379 -
动态调整阈值
通过Redis Hash存储不同路径的拦截规则:local rule_key = "limit:rule:" .. ngx.var.uri local custom_rule = red:hget(rule_key, "max_requests")
引用说明
- 核心拦截逻辑参考了Nginx+Lua+Redis的经典架构设计
- Redis键过期机制确保自动解封
- 性能优化方案借鉴了OpenResty最佳实践
相关文章:
nginx 动态计算拦截非法访问ip
需求:在Nginx上实现一个动态拦截IP的方法,具体是当某个IP在1分钟内访问超过60次时,将其加入Redis并拦截,拦截时间默认1天。 技术选型:使用NginxLuaRedis的方法。这种方案通过Lua脚本在Nginx处理请求时检查Redis中的黑…...
商业秘密维权有哪些成本开支?
企业商业秘密百问百答之六十三:商业秘密维权费用项目有哪些? 在商业秘密维权过程中,原告可能需要支付多种费用,一般费用项目包括: 1、诉讼费。诉讼费是向法院支付的费用,包括起诉费、案件受理费等。这些费…...
使用UA-SPEECH和TORGO数据库验证自动构音障碍语音分类方法
使用UA-SPEECH和TORGO数据库验证自动构音障碍语音分类方法 引言 原文:On using the UA-Speech and TORGO databases to validate automatic dysarthric speech classification approaches 构音障碍简介 构音障碍是一种由于脑损伤或神经疾病(如脑瘫、肌萎缩侧索硬化症、帕金森…...
WebSocketHandler 是 Spring Framework 中用于处理 WebSocket 通信的接口
WebSocketHandler 是 Spring Framework 中用于处理 WebSocket 通信的接口,其主要作用是定义了如何处理 WebSocket 的各种事件和消息。以下是 WebSocketHandler 的主要作用和功能: ### 1. 处理 WebSocket 生命周期事件 WebSocketHandler 定义了多个方法来…...
Pikachu
一、网站搭建 同样的,先下载安装好phpstudy 然后启动Apache和Mysql 然后下载pikachu,解压到phpstudy文件夹下的www文件 然后用vscode打开pikachu中www文件夹下inc中的config.inc.php 将账户和密码改为和phpstudy中的一致(默认都是root&…...
如何使用 Jenkins 实现 CI/CD 流水线:从零开始搭建自动化部署流程
如何使用 Jenkins 实现 CI/CD 流水线:从零开始搭建自动化部署流程 在软件开发过程中,持续集成(CI)和持续交付(CD)已经成为现代开发和运维的标准实践。随着代码的迭代越来越频繁,传统的手动部署方式不仅低效,而且容易出错。为了提高开发效率和代码质量,Jenkins作为一款…...
Vue.js 学习笔记
文章目录 前言一、Vue.js 基础概念1.1 Vue.js 简介1.2 Vue.js 的特点1.3 Vue.js 基础示例 二、Vue.js 常用指令2.1 双向数据绑定(v-model)2.2 条件渲染(v-if 和 v-show)2.3 列表渲染(v-for)2.4 事件处理&am…...
数据存储:一文掌握RabbitMQ的详细使用
文章目录 一、RabbitMQ简介二、RabbitMQ的概述2.1 基本概念2.2 实际应用场景三、RabbitMQ的安装与配置3.1 安装RabbitMQ3.2 启用管理插件四、使用Python操作RabbitMQ4.1 安装Pika库4.2 生产者示例4.3 消费者示例4.4 发布/订阅模式示例五、RabbitMQ的高级特性5.1 消息持久化5.2 …...
辛格迪客户案例 | 祐儿医药科技GMP培训管理(TMS)项目
01 项目背景:顺应行业趋势,弥补管理短板 随着医药科技行业的快速发展,相关法规和标准不断更新,对企业的质量管理和人员培训提出了更高要求。祐儿医药科技有限公司(以下简称“祐儿医药”)作为一家专注于创新…...
FreeRtos实时系统: 十六.tickless低功耗模式
FreeRtos实时系统: 十六.tickless低功耗模式 一.tickless低功耗模式简介二.tickless模式详解三.tickless模式相关配置项四.tickless低功耗模式实验五.课堂总结 一.tickless低功耗模式简介 STM32低功耗模式: 二.tickless模式详解 为了可以降低功耗,又不…...
CSDN博客:Markdown编辑语法教程总结教程(上)
❤个人主页:折枝寄北的博客 Markdown编辑语法教程总结 前言1. CSDN Markdown编辑器功能简介1.1 基础操作界面1.2 创作助手和语法说明 2. Markdown编辑器语法2.1 目录2.2 标题2.2.1 标题级别设置2.2.2 标题居中 3. 文本样式3.1 强调文本(斜体)…...
多个pdf合并成一个pdf的方法
将多个PDF文件合并优点: 能更容易地对其进行归档和备份.打印时可以选择双面打印,减少纸张的浪费。比如把住宿发票以及滴滴发票、行程单等生成一个pdf,双面打印或者无纸化办公情况下直接发送给财务进行存档。 方法: 利用PDF24 Tools网站 …...
Spark基础篇 RDD、DataFrame与DataSet的关系、适用场景与演进趋势
一、核心概念与演进背景 1.1 RDD(弹性分布式数据集) 定义:RDD 是 Spark 最早的核心抽象(1.0版本引入),代表不可变、分区的分布式对象集合,支持函数式编程和容错机制。特点: 无结构化信息:仅存储对象本身,无法自动感知数据内部结构(如字段名、类型)。编译时类型安全…...
odoo初始化数据库
在 Odoo 中,初始化数据库的命令会因使用的环境和启动方式而有所不同,下面为你详细介绍几种常见的初始化数据库的方式。 1. 使用命令行工具初始化 在命令行中,你可以使用 Odoo 的启动脚本并结合相关参数来初始化数据库。以下是基本的命令格式…...
大模型WebUI:Gradio全解12——LangChain原理、架构和组件(2)
大模型WebUI:Gradio全解12——LangChain原理、架构和组件(2) 前言12. LangChain原理及agents构建Gradio UI12.2 学习资料12.2.1 学习文档12.2.2 用途示例12.2.3 OpenAI和DeepSeek例程1. OpenAI示例2. DeepSeek例程参考文献前言 本系列文章主要介绍WEB界面工具Gradio。Gradi…...
1. 搭建前端+后端开发框架
1. 说明 本篇博客主要介绍网页开发中,搭建前端和后端开发框架的具体步骤,框架中所使用的技术栈如下: 前端:VUE Javascript 后端:Python Flask Mysql 其中MySQL主要用来存储需要的数据,在本文中搭建基本…...
初会学习记录
目录 务实: 第一章 (1)会计概念,职能和目标: (2)会计假设: (3)会计核算基础: (4)会计信息质量要求: (5)会计人员职业道德规范 (6)会计准则制度体系概述: (7)会计要素与会计等式&#x…...
DeepSeek 使用窍门与提示词写法指南
一、通用提示词技巧 窍门分类技巧说明示例提示词明确需求用“角色任务要求”明确目标作为健身教练,为30岁上班族设计一周减脂计划,需包含饮食和15分钟居家训练结构化提问分步骤、分模块提问第一步:列出Python爬虫必备的5个库;第二…...
【大模型】DeepSeek核心技术之MLA (Multi-head Latent Attention)
文章目录 1. Multi-Head Attention (MHA)2. Multi-head Latent Attention (MLA)2.1 低秩压缩2.2 应用RoPE2.3 矩阵融合 参考资料 在讲解MLA之前,需要大家对几个基础的概念(KV Cache, Grouped-Query Attention (GQA), Multi-Query Attention (…...
七、JOIN 语法详解与实战示例
一、JOIN 的作用与分类 JOIN 操作用于合并两个或多个表的行,基于表之间的关联字段。以下是常见的 JOIN 类型: JOIN 类型描述INNER JOIN返回两个表匹配的记录LEFT JOIN返回左表所有记录 右表匹配记录(右表无匹配则为NULL)RIGHT …...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
