Nginx 实现动态封禁IP
Nginx 是一个高性能的 HTTP 和反向代理服务器,通过配置模块可以实现很多强大的功能,包括动态封禁 IP 地址。实现动态封禁 IP 通常涉及以下几步:
-
使用 Nginx 第三方模块:Nginx 本身并不直接支持动态封禁 IP,但可以通过第三方模块如
ngx_http_access_module
或者ngx_http_auth_request_module
来实现。此外,还可以结合外部脚本和 Redis 等工具来实现动态封禁。 -
配置 Nginx 和 Lua 脚本:通过 Nginx 的
ngx_lua
模块,可以编写 Lua 脚本来动态地处理封禁逻辑。Lua 脚本可以查询 Redis 或其他存储系统,来决定是否封禁某个 IP。 -
使用第三方工具:比如 Fail2ban,它可以与 Nginx 日志结合,动态封禁多次失败的请求 IP。
下面是一个使用 ngx_lua
和 Redis 实现动态封禁 IP 的示例:
环境准备
-
安装 Nginx 和 LuaJIT:确保 Nginx 支持 Lua 模块,通常需要安装
openresty
,它包含了 Nginx 和 ngx_lua 模块。 -
安装 Redis:用于存储封禁 IP 列表。
配置示例
-
安装 OpenResty 和 LuaRocks(假设在 Linux 系统上):
sudo apt-get update sudo apt-get install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring curl -fsSL https://openresty.org/package/pubkey.gpg | sudo tee /usr/share/keyrings/openresty-archive-keyring.gpg > /dev/null echo "deb [signed-by=/usr/share/keyrings/openresty-archive-keyring.gpg] http://openresty.org/package/debian $(lsb_release -cs) openresty" | sudo tee /etc/apt/sources.list.d/openresty.list sudo apt-get update sudo apt-get install -y openresty sudo apt-get install -y luarocks
-
安装 Lua 依赖库:
sudo luarocks install lua-resty-redis sudo luarocks install lua-resty-http
-
配置 Nginx:
编辑 Nginx 配置文件(例如
/etc/openresty/nginx.conf
),添加以下配置:http { lua_shared_dict my_cache 10m; server { listen 80; location / { access_by_lua_block { local redis = require "resty.redis" local red = redis:new() red:set_timeout(1000) -- 1 sec local ok, err = red:connect("127.0.0.1", 6379) if not ok then ngx.say("failed to connect: ", err) return ngx.exit(500) end local client_ip = ngx.var.remote_addr local blocked, err = red:sismember("blocked_ips", client_ip) if not blocked then -- Proceed with the request else ngx.say("Access forbidden") return ngx.exit(403) end -- Close the redis connection local ok, err = red:close() if not ok then ngx.log(ngx.ERR, "failed to close: ", err) end } # Your other configuration directives proxy_pass http://your_backend; } # Add a location for blocking/unblocking IPs via HTTP (for admin use) location /block_ip { content_by_lua_block { local redis = require "resty.redis" local red = redis:new() red:set_timeout(1000) -- 1 sec local ok, err = red:connect("127.0.0.1", 6379) if not ok then ngx.say("failed to connect: ", err) return ngx.exit(500) end local ip = ngx.req.get_uri_args()["ip"] if not ip then ngx.say("IP not provided") return ngx.exit(400) end local ok, err = red:sadd("blocked_ips", ip) if not ok then ngx.say("failed to block IP: ", err) return ngx.exit(500) end ngx.say("IP blocked successfully") -- Close the redis connection local ok, err = red:close() if not ok then ngx.log(ngx.ERR, "failed to close: ", err) end } } location /unblock_ip { content_by_lua_block { local redis = require "resty.redis" local red = redis:new() red:set_timeout(1000) -- 1 sec local ok, err = red:connect("127.0.0.1", 6379) if not ok then ngx.say("failed to connect: ", err) return ngx.exit(500) end local ip = ngx.req.get_uri_args()["ip"] if not ip then ngx.say("IP not provided") return ngx.exit(400) end local ok, err = red:srem("blocked_ips", ip) if not ok then ngx.say("failed to unblock IP: ", err) return ngx.exit(500) end ngx.say("IP unblocked successfully") -- Close the redis connection local ok, err = red:close() if not ok then ngx.log(ngx.ERR, "failed to close: ", err) end } } } }
运行和测试
-
启动 Redis:
sudo systemctl start redis
-
启动 Nginx:
sudo systemctl start openresty
-
测试封禁功能:
- 访问
http://your_server_ip/block_ip?ip=192.168.1.100
来封禁某个 IP。 - 访问
http://your_server_ip/unblock_ip?ip=192.168.1.100
来解封某个 IP。 - 使用被封禁的 IP 访问你的 Nginx 服务器,应该会收到
Access forbidden
的响应。
- 访问
这样,你就实现了一个简单的动态封禁 IP 的系统。根据需求,你可以进一步优化和扩展这个系统,比如添加更多的日志记录、更复杂的封禁规则等。
- 点赞
- 收藏
- 关注作者
评论(0)