nginx 动态计算拦截非法访问ip

需求:在Nginx上实现一个动态拦截IP的方法,具体是当某个IP在1分钟内访问超过60次时,将其加入Redis并拦截,拦截时间默认1天。

技术选型:使用Nginx+Lua+Redis的方法。这种方案通过Lua脚本在Nginx处理请求时检查Redis中的黑名单,同时统计访问频率,超过阈值就封禁。这应该符合用户的需求。

需要结合Lua脚本和Redis的计数功能。安装OpenResty,配置Nginx的Lua模块,编写Lua脚本统计访问次数,使用Redis存储和过期键,以及设置拦截逻辑。连接池的使用,避免频繁连接Redis影响性能。

一、环境准备

  1. 安装OpenResty
    OpenResty集成了Nginx和Lua模块,支持直接运行Lua脚本:

    # Ubuntu/Debian
    sudo apt-get install openresty
    # CentOS
    yum install openresty
  2. 安装Redis服务

    sudo apt-get install redis-server  # Debian系
    sudo yum install redis             # RedHat系

二、Nginx配置

  1. 主配置文件(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脚本实现动态拦截

  1. 脚本路径
    创建Lua脚本:/usr/local/lua/ip_block.lua

  2. 脚本内容

    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 then
            ngx.log(ngx.ERR, "Redis连接失败: ", err)
            return nil
        end
        if redis_auth then
            local ok, err = red:auth(redis_auth)
            if not ok then ngx.log(ngx.ERR, "Redis认证失败: ", err) end
        end
        return 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 then
        ngx.exit(ngx.HTTP_FORBIDDEN)  -- 直接返回403
    end
    
    -- 统计请求次数
    connect_redis()
    local current_count = red:incr(counter_key)
    if current_count == 1 then
        red:expire(counter_key, time_window)  -- 首次设置过期时间
    end
    
    -- 触发封禁条件
    if current_count > max_requests then
        red:setex(block_key, block_time, 1)   -- 封禁并设置1天过期
        red:del(counter_key)                  -- 删除计数器
        ngx.exit(ngx.HTTP_FORBIDDEN)
    end
    
    -- 释放Redis连接
    red:set_keepalive(10000, 100)

四、性能优化

  1. Redis连接池
    通过set_keepalive复用连接,避免频繁建立TCP连接

  • 共享内存缓存
    使用lua_shared_dict缓存高频访问IP,减少Redis查询压力

  1. 异步日志记录
    封禁操作异步写入日志文件,避免阻塞请求处理:

    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)

五、验证与测试

  1. 手动触发封禁

    # 模拟高频请求
    ab -n 100 -c 10 http://your-domain.com/
    # 检查Redis
    redis-cli keys "limit:block:*"
  2. 自动解封验证
    等待24小时后检查封禁IP是否自动删除:

    redis-cli ttl "limit:block:1.2.3.4"  # 返回剩余秒数

六、扩展方案

  1. 分布式封禁
    在多台Nginx服务器间共享Redis黑名单,实现集群级拦截

  1. 可视化监控
    通过Grafana+Prometheus展示实时拦截数据:

    # 采集Redis指标
    prometheus-redis-exporter --redis.address=localhost:6379
  2. 动态调整阈值
    通过Redis Hash存储不同路径的拦截规则:

    local rule_key = "limit:rule:" .. ngx.var.uri
    local custom_rule = red:hget(rule_key, "max_requests")

引用说明

  • 核心拦截逻辑参考了Nginx+Lua+Redis的经典架构设计
  • Redis键过期机制确保自动解封
  • 性能优化方案借鉴了OpenResty最佳实践

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/978755.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RNN,LSTM,GRU三种循环网络的对比

1. 三种网络在准确率的对比 2. 三种网络在损失值的对比 3. 三种网络在计算时间的对比 4. RNN(传统循环神经网络) 主要特点: RNN 是最基础的循环神经网络,通过 递归 计算每个时间步的输出。在每个时间步,RNN 会将当前…

hackmyvm-hero

信息收集 ┌──(root㉿kali)-[/home/kali/Desktop/hackmyvm] └─# arp-scan -I eth1 192.168.56.0/24 Interface: eth1, type: EN10MB, MAC: 00:0c:29:34:da:f5, IPv4: 192.168.56.103 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192…

纷析云:赋能企业财务数字化转型的开源解决方案

在企业数字化转型的浪潮中,财务管理的高效与安全成为关键。纷析云凭借其开源、安全、灵活的财务软件解决方案,为企业提供了一条理想的转型路径。 一、开源的力量:自主、安全、高效 纷析云的核心优势在于其100%开源的财务软件源码。这意味着…

异常c/c++

目录 1.c语言传统处理错误方式 1、终止程序 2、返回错误码 2.c异常概念 3.异常的使用 3.1异常的抛出与捕获 3.2异常安全(还有一些异常重新抛出) 3.3异常规范 4.自定义异常体系 5.c标准库的异常体系 6.异常优缺点 1、优点 2、缺点 7、补充 1.…

SAP-ABAP:使用ST05(SQL Trace)追踪结构字段来源的步骤

ST05 是 SAP 提供的 SQL 跟踪工具,可以记录程序运行期间所有数据库操作(如 SELECT、UPDATE、INSERT)。通过分析跟踪结果,可以精准定位程序中结构字段对应的数据库表。 步骤1:激活ST05跟踪 事务码 ST05 → 点击 Activa…

sklearn中的决策树-分类树:剪枝参数

剪枝参数 在不加限制的情况下,一棵决策树会生长到衡量不纯度的指标最优,或者没有更多的特征可用为止。这样的决策树 往往会过拟合。为了让决策树有更好的泛化性,我们要对决策树进行剪枝。剪枝策略对决策树的影响巨大,正确的剪枝策…

安宝特科技 | Vuzix Z100智能眼镜+AugmentOS:重新定义AI可穿戴设备的未来——从操作系统到硬件生态,如何掀起无感智能革命?

一、AugmentOS:AI可穿戴的“操作系统革命” 2025年2月3日,Vuzix与AI人机交互团队Mentra联合推出的AugmentOS,被业内视为智能眼镜领域的“iOS时刻”。这款全球首个专为智能眼镜设计的通用操作系统,通过三大突破重新定义了AI可穿戴…

基于Rook的Ceph云原生存储部署与实践指南(上)

#作者:任少近 文章目录 1 Ceph环境准备2 rook部署ceph群集2.1 Rook 帮助地址2.2 安装ceph2.3 获取csi镜像2.4 Master参加到osd2.5 设置默认存储 3 Rook部署云原生RBD块存储3.1 部署storageclass资源3.2 部署WordPress使用RBD3.3 WordPress访问 4 Rook部署云原生RGW…

2月27(信息差)

🌍雷军超钟睒睒登顶中国首富 身家近4400亿元 🎄全球AI大混战升温!超越Sora的阿里万相大模型开源 家用显卡都能跑 ✨小米15 Ultra、小米SU7 Ultra定档2月27日 雷军宣布:向超高端进发 1.刚刚!DeepSeek硬核发布&#xff…

【Linux】文件系统深度解析:从基础到高级应用

🎬 个人主页:努力可抵万难 📖 个人专栏:《C语法》《Linux系列》《数据结构及算法》 ⛰️ 路虽远,行则将至 目录 📚一、引言:文件系统的核心作用与历史演进 📖1.文件系统的定义与功…

《Effective Objective-C》阅读笔记(中)

目录 接口与API设计 用前缀避免命名空间冲突 提供“全能初始化方法” 实现description方法 尽量使用不可变对象 使用清晰而协调的命名方式 方法命名 ​编辑类与协议命名 为私有方法名加前缀 理解OC错误模型 理解NSCopying协议 协议与分类 通过委托与数据源协议进行…

MongoDB—(一主、一从、一仲裁)副本集搭建

MongoDB集群介绍: MongoDB 副本集是由多个MongoDB实例组成的集群,其中包含一个主节点(Primary)和多个从节点(Secondary),用于提供数据冗余和高可用性。以下是搭建 MongoDB 副本集的详细步骤&am…

【实战 ES】实战 Elasticsearch:快速上手与深度实践-1.3.1单节点安装(Docker与手动部署)

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 10分钟快速部署Elasticsearch单节点环境1. 系统环境要求1.1 硬件配置推荐1.2 软件依赖 2. Docker部署方案2.1 部署流程2.2 参数说明2.3 性能优化建议 3. 手动部署方案3.1 安…

Rt-thread源码剖析(1)——内核对象

前言 该系列基于rtthread-nano的内核源码,来研究RTOS的底层逻辑,本文介绍RTT的内核对象,对于其他RTOS来说也可供参考,万变不离其宗,大家都是互相借鉴,实现不会差太多。 内核对象容器 首先要明确的一点是什…

html css js网页制作成品——HTML+CSS甜品店网页设计(5页)附源码

目录 一、👨‍🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨‍&#x1f…

Trae根据原型设计稿生成微信小程序密码输入框的踩坑记录

一、需求描述 最近经常使用Trae生成一些小组件和功能代码(对Trae赶兴趣的可以看之前的文章《TraeAi上手体验》),刚好在用uniapp开发微信小程序时需要开发一个输入密码的弹框组件,于是想用Trae来实现。原型设计稿如下:…

斩波放大器

目录 简介 自稳零斩波放大器 噪声 简介 双极性放大器的失调电压为25 μV,漂移为0.1 μV/C。斩波放大器尽管存在一些不利影 响,但可提供低于5 μV的失调电压,而且不会出现明显的失调漂移, 以下图1给出了基本的斩波放大器电路图。…

windows设置暂停更新时长

windows设置暂停更新时长 win11与win10修改注册表操作一致 ,系统界面不同 1.打开注册表 2.在以下路径 \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 右键新建 DWORD 32位值,名称为FlightSettingsMaxPauseDays 根据需求填写数…

DIALOGPT:大规模生成式预训练用于对话响应生成

摘要 我们提出了一个大规模、可调节的神经对话响应生成模型,DIALOGPT(对话生成预训练变换器)。该模型训练于从2005年至2017年间Reddit评论链中提取的1.47亿次类似对话的交流,DIALOGPT扩展了Hugging Face的PyTorch变换器&#xff…

Mac端不显示正常用户名,变成192的解决方法

今天打开终端,本应该显示机器名的,但是此时显示了192。 问题原因: 当路由器的DNS使用默认的 192.168.1.1 或 192.168.0.1 的时候 Terminal 里的计算机名 会变成 localhost。当路由器的DNS使用自定义的 例如 运营商的DNS 或者 公共DNS的时候 …