Nginx + Lua + Redis 动态封IP黑名单

在现代 web 应用中,保护系统免受恶意攻击是一项至关重要的任务。随着网络安全威胁的不断增加,利用一些技术手段来动态维护 IP 黑名单显得尤为重要。本文将介绍如何通过 Nginx、Lua 和 Redis 实现动态封禁 IP 的功能。

1. 什么是 IP 黑名单?

IP 黑名单是一个包含了被禁止访问某个网站的 IP 地址的列表。当一个 IP 地址在黑名单中时,服务器会拒绝这个 IP 的请求,从而保护网站免受攻击。

2. 技术栈介绍

  • Nginx:一种高性能的 HTTP 服务器和反向代理服务器。
  • Lua:一种轻量级的脚本语言,可以嵌入到 Nginx 中,提供更多的灵活性。
  • Redis:一个开源的内存数据存储系统,用于快速存取数据。

3. 系统架构

我们的系统架构如下所示:

stateDiagram
    [*] --> Nginx
    Nginx --> Lua
    Lua --> Redis
    Redis --> Nginx
    Nginx --> [*]

如上图所示,请求先经过 Nginx,Nginx 调用 Lua 脚本,然后 Lua 从 Redis 获取 IP 黑名单信息,最后决定是否允许请求通过。

4. 环境搭建

在开始之前,请确保环境中安装了 Nginx,Lua 和 Redis。你可以通过以下步骤在 Ubuntu 上安装这些组件:

sudo apt update
sudo apt install nginx lua5.3 liblua5.3-dev redis-server

接下来,确保你已安装了 Nginx 的 Lua 模块。你可以通过编译 Nginx 或者使用诸如 OpenResty 这样的发行版。

5. Lua 脚本

Lua 脚本负责检查请求的 IP 是否在 Redis 的黑名单中。以下是一个简单的 Lua 脚本示例:

local red = require "resty.redis"
local redis = red:new()
redis:set_timeout(1000) -- 设置连接超时为1秒

-- 连接到 Redis
local ok, err = redis:connect("127.0.0.1", 6379)
if not ok then
    ngx.log(ngx.ERR, "failed to connect to Redis: " .. err)
    return ngx.exit(500)
end

-- 获取请求的 IP
local ip = ngx.var.remote_addr

-- 检查 IP 是否在黑名单中
local blacklisted, err = redis:sismember("ip_blacklist", ip)
if err then
    ngx.log(ngx.ERR, "failed to check blacklist: " .. err)
    return ngx.exit(500)
end

if blacklisted == 1 then
    -- 返回403 Forbidden
    return ngx.exit(ngx.HTTP_FORBIDDEN)
end

-- 如果没有被封禁,继续进行请求

上述脚本中,我们使用了 Redis 的 sismember 命令来检查请求的 IP 是否在黑名单中。如果是,则返回 403 Forbidden 状态。

6. Nginx 配置

我们需要在 Nginx 配置文件中调用 Lua 脚本。以下是一个基本的配置示例:

http {
    lua_shared_dict ip_blacklist_shared 10m;

    server {
        listen 80;
        server_name example.com;

        location / {
            access_by_lua_file /path/to/check_ip.lua;
            # 其他处理
        }
    }
}

记得将 /path/to/check_ip.lua 替换成你实际的 Lua 脚本路径。

7. 向 Redis 添加 IP

我们可以使用 Redis CLI 或其他工具来动态更新黑名单。以下是一个示例命令,用于添加一个 IP 地址到黑名单中:

redis-cli SADD ip_blacklist 192.168.1.1

使用 SADD 命令,我们可以将新的 IP 地址添加到名为 ip_blacklist 的集合中。

8. 清理黑名单

通常,IP 黑名单需要定期清理。我们可以编写一个简单的 Lua 脚本或使用定时任务来移除过期的 IP。

9. 总结

在本篇文章中,我们介绍了如何使用 Nginx、Lua 和 Redis 来实现动态封禁 IP 黑名单的功能。通过灵活的脚本和高效的存储方式,我们可以提高系统的安全性,保护我们的应用免受恶意攻击。希望这篇文章能帮助你更好地理解并实现 IP 黑名单的管理机制。保护你的应用,从动态封禁 IP 黑名单开始!