在Nginx中实现动态封禁IP的三种主流方案

 更新时间:2025年11月11日 08:44:42   作者:程序员1970  
在运维和安全实践中,经常需要根据实时情况封禁某些恶意 IP,但传统的Nginx 配置是静态的,一旦写死deny 1.2.3.4;,就必须重启或重载服务才能生效,那么,有没有办法实现动态、实时、可编程的IP封禁呢,所以本文给大家介绍了在Nginx中实现动态封禁IP的三种主流方案

引言

在运维和安全实践中,经常需要根据实时情况封禁某些恶意 IP。但传统的Nginx 配置是静态的——一旦写死 deny 1.2.3.4;,就必须重启或重载服务才能生效。那么,有没有办法在不中断服务的前提下,实现动态、实时、可编程的 IP 封禁呢?

一、方案对比

方案是否需 reload实时性技术栈适用场景
geo + map + 文件是(nginx -s reload秒~分钟级原生 Nginx手动或定时脚本封禁
OpenResty + Lua毫秒级OpenResty(Nginx + Lua)自动化、高并发、API 化管理
fail2ban + 日志分析否(系统级封禁)秒级fail2ban + iptables安全防护、日志驱动型封禁

二、方案一:原生 Nginx + 外部文件(简单可靠)

适用于不需要极高实时性的场景,比如每天批量封禁一批扫描 IP。

1. 创建封禁 IP 列表文件

# /etc/nginx/conf.d/blockips.conf
192.168.1.100 1;
203.0.113.5    1;

格式为:IP 值;,值通常设为 1 表示“命中”。

2. 在 nginx.conf 中配置

http {
    # 从外部文件加载黑名单
    geo $block_ip {
        default 0;
        include /etc/nginx/conf.d/blockips.conf;
    }

    map $block_ip $deny_ip {
        1 "denied";
        0 "";
    }

    server {
        listen 80;

        if ($deny_ip = "denied") {
            return 403;
        }

        location / {
            # 正常业务
        }
    }
}

3. 动态更新方式

  • 修改 blockips.conf
  • 执行平滑重载:
nginx -s reload

✅ 优点:无需额外依赖,配置简单。
⚠️ 缺点:每次更新需 reload,不适合高频操作。

三、方案二:OpenResty + Lua(推荐用于自动化)

如果你需要通过 API 实时封禁 IP(例如 WAF、风控系统调用),OpenResty 是最佳选择。它基于 Nginx,嵌入 Lua 脚本引擎,支持共享内存,无需 reload 即可生效。

1. 安装 OpenResty

# Ubuntu 示例
wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
echo "deb http://openresty.org/package/debian $(lsb_release -sc) openresty" | sudo tee /etc/apt/sources.list.d/openresty.list
sudo apt update && sudo apt install openresty

2. 配置 nginx.conf

http {
    lua_shared_dict ip_blacklist 10m;  # 共享内存存储黑名单

    server {
        listen 80;

        # 【核心】访问前检查 IP
        access_by_lua_block {
            local ip = ngx.var.remote_addr
            if ngx.shared.ip_blacklist:get(ip) then
                ngx.log(ngx.WARN, "Blocked IP: ", ip)
                ngx.exit(403)
            end
        }

        # 动态封禁接口(建议加 IP 白名单保护)
        location = /ban {
            content_by_lua_block {
                local args = ngx.req.get_uri_args()
                local ip = args.ip
                local seconds = tonumber(args.seconds) or 3600

                if not ip or not ip:match("^%d+%.%d+%.%d+%.%d+$") then
                    ngx.status = 400
                    ngx.say("Invalid or missing 'ip'")
                    return
                end

                ngx.shared.ip_blacklist:set(ip, true, seconds)
                ngx.say("Banned ", ip, " for ", seconds, "s")
            }
        }

        # 解封 & 查询接口
        location / { echo "Hello! Your IP: $remote_addr"; }
    }
}

3. 使用示例

# 封禁 IP 5 分钟
curl "http://your-server/ban?ip=1.2.3.4&seconds=300"

# 测试是否被封
curl http://your-server/  # 返回 403

✅ 优点:毫秒级生效、支持 TTL 自动过期、可集成到自动化系统。
🔐 安全提示:务必限制 /ban 接口的访问来源!

四、方案三:fail2ban + Nginx 日志(自动防御)

适用于防御暴力 破解、高频 404 扫描等行为。fail2ban 会监控日志,自动封禁异常 IP。

1. 确保 Nginx 记录详细日志

log_format main '$remote_addr - $remote_user [$time_local] "$request" $status ...';
access_log /var/log/nginx/access.log main;

2. 创建过滤器 /etc/fail2ban/filter.d/nginx-bad-request.conf

[Definition]
failregex = ^<HOST> -.*"(GET|POST).*" 404 .*
ignoreregex =

3. 配置 jail(/etc/fail2ban/jail.local)

[nginx-bad-request]
enabled  = true
port     = http,https
filter   = nginx-bad-request
logpath  = /var/log/nginx/access.log
maxretry = 10      # 10 次失败
findtime = 600     # 在 10 分钟内
bantime  = 3600    # 封 1 小时
action   = iptables-multiport[name=nginx, port="http,https"]

4. 启动并查看状态

sudo systemctl start fail2ban
sudo fail2ban-client status nginx-bad-request

✅ 优点:全自动、成熟稳定、社区支持好。
⚠️ 注意:默认使用 iptables 封禁,影响整个服务器,非仅 Nginx。

五、如何选择?

  • 只想偶尔手动封几个 IP? → 用 方案一(原生 Nginx)。
  • 需要程序自动封禁、支持 API 调用? → 用 方案二(OpenResty)。
  • 想自动防御扫描、爆破? → 用 方案三(fail2ban)。

进阶技巧:可让 fail2ban 调用 OpenResty 的 /ban 接口,实现“仅封 Nginx + 自动过期”的完美组合。

以上就是在Nginx中实现动态封禁IP的三种主流方案的详细内容,更多关于Nginx动态封禁IP的资料请关注脚本之家其它相关文章!

相关文章

  • Nginx 403 forbidden错误的原因以及解决方法

    Nginx 403 forbidden错误的原因以及解决方法

    yum安装nginx,安装一切正常,但是访问时报403 forbidden,下面这篇文章主要给大家介绍了关于Nginx 403 forbidden错误的原因以及解决方法,需要的朋友可以参考下
    2022-08-08
  • nginx中proxy_set_header参数的实现

    nginx中proxy_set_header参数的实现

    本文详细介绍了Nginx中proxy_set_header指令的用法,通过设置不同的请求头信息,可以实现更灵活的反向代理功能,具有一定的参考价值,感兴趣的可以了解一下
    2024-12-12
  • Nginx中报错:Permission denied与Connection refused的解决

    Nginx中报错:Permission denied与Connection refused的解决

    这篇文章主要给大家介绍了在Nginx中报错:13: Permission denied与111: Connection refused的解决方法,文中介绍的非常详细,相信对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
    2017-04-04
  • nginx基础配置说明一则

    nginx基础配置说明一则

    nginx基础配置说明一则,有需要的朋友可以参考下
    2013-02-02
  • nginx中的日志切割详解

    nginx中的日志切割详解

    Nginx日志切割是定期将访问日志和错误日志分割成多个文件,以优化性能、便于管理和分析,常见的实现方法包括使用logrotate工具和编写自定义脚本,解决常见的问题如Nginx不再写入新日志和权限问题,需要确保正确的信号发送和权限设置
    2025-11-11
  • nginx对http请求处理的各个阶段详析

    nginx对http请求处理的各个阶段详析

    这篇文章主要给大家介绍了关于nginx对http请求处理的各个阶段分析的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Nginx环境下WordPress的多站点功能配置详解

    Nginx环境下WordPress的多站点功能配置详解

    WordPress的多站点功能允许安装一个WordPress程序的情况下,实现多个站点也就是一套程序,可以绑定多个域名或子域名,本文详细介绍了在Nginx环境下WordPress的多站点功能配置方法
    2018-10-10
  • nginx配置静态资源的访问的实现

    nginx配置静态资源的访问的实现

    本文主要介绍了nginx配置静态资源的访问的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-05-05
  • 利用nginx实现动静分离的负载均衡集群实战教程

    利用nginx实现动静分离的负载均衡集群实战教程

    这篇文章介绍了利用nginx实现动静分离的负载均衡集群实战,本次用到的操作系统及服务,本次实验一共需要3台服务器,一台nginx做为负载均衡分发器和动静分离的分发器,两台apache做为后端服务器,使用nginx实现两台apache服务器的负载均衡和动静分离,需要的朋友可以参考下
    2023-03-03
  • 基于域名、端口和IP搭建nginx虚拟主机

    基于域名、端口和IP搭建nginx虚拟主机

    本文给大家分享基于域名、端口和IP搭建nginx虚拟主机的内容,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2019-11-11

最新评论