切換語言為:簡體
Nginx想實現動態封禁IP?詳細教程來了

Nginx想實現動態封禁IP?詳細教程來了

  • 爱糖宝
  • 2024-10-27
  • 2044
  • 0
  • 0

需求

爲了封禁某些爬蟲或者惡意使用者對伺服器的請求,我們需要建立一個動態的 IP 黑名單。對於黑名單中的 IP ,我們將拒絕提供服務。並且可以設定封禁失效時間

環境準備

linux version: centos7  / ubuntu 等
redis version: 5.0.5
nginx version: nginx-openresty

設計方案

實現 IP 黑名單的功能有很多途徑:
1、在作業系統層面,配置 iptables,來攔截指定 IP 的網路請求。

  • 優點:簡單直接,在伺服器物理層面上進行攔截

  • 缺點:每次需要手動上伺服器修改配置檔案,操作繁瑣且不靈活

2、在 Web 伺服器層面,透過 Nginx 自身的 deny 選項或者 lua 外掛配置 IP 黑名單。

  • 優點:可動態實現封禁 ip,透過設定封禁時間可以做到分散式封禁

  • 缺點:需要了解 Lua 指令碼和 Nginx 配置,有一定的學習成本

3、在應用層面,在處理請求之前檢查客戶端的 IP 地址是否在黑名單中。

  • 優點:透過編寫程式碼來實現,相對簡單且易於維護。

  • 缺點:程式碼可能會變得冗長,而且在高併發情況下可能影響效能。

爲了方便管理和共享黑名單,透過 nginx + lua + redis 的架構實現 IP 黑名單的功能 

Nginx想實現動態封禁IP?詳細教程來了

配置 nginx.conf

在需要進行限制的 server 的 location 中新增如下配置:

location / {
    # 如果該location 下存在靜態資原始檔可以做一個判斷      
    #if ($request_uri ~ .*\.(html|htm|jpg|js|css)) {
    # access_by_lua_file /usr/local/lua/access_limit.lua;   
    #}
    
    access_by_lua_file /usr/local/lua/access_limit.lua; # 加上了這條配置,則會根據 access_limit.lua 的規則進行限流
    alias /usr/local/web/;
    index  index.html index.htm;
}

配置 lua 指令碼

/usr/local/lua/access_limit.lua

-- 可以實現自動將訪問頻次過高的IP地址加入黑名單封禁一段時間

--連線池超時回收毫秒
local pool_max_idle_time = 10000
--連線池大小
local pool_size = 100
--redis 連線超時時間
local redis_connection_timeout = 100
--redis host
local redis_host = "your redis host ip"
--redis port
local redis_port = "your redis port"
--redis auth
local redis_auth = "your redis authpassword";
--封禁IP時間(秒)
local ip_block_time= 120
--指定ip訪問頻率時間段(秒)
local ip_time_out = 1
--指定ip訪問頻率計數最大值(次)
local ip_max_count = 3


--  錯誤日誌記錄
local function errlog(msg, ex)
    ngx.log(ngx.ERR, msg, ex)
end

-- 釋放連線池
local function close_redis(red)
    if not red then
        return
    end
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
    if not ok then
        ngx.say("redis connct err:",err)
        return red:close()
    end
end


--連線redis
local redis = require "resty.redis"
local client = redis:new()
local ok, err = client:connect(redis_host, redis_port)
-- 連線失敗返回伺服器錯誤
if not ok then
    close_redis(client)
    ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
--設定超時時間
client:set_timeout(redis_connection_timeout)

-- 最佳化驗證密碼操作 代表連線在連線池使用的次數,如果為0代表未使用,不為0代表複用 在只有為0時才進行密碼校驗
local connCount, err = client:get_reused_times()
-- 新建連線,需要認證密碼
if  0 == connCount then
    local ok, err = client:auth(redis_auth)
    if not ok then
        errlog("failed to auth: ", err)
        return
    end
    --從連線池中獲取連線,無需再次認證密碼
elseif err then
    errlog("failed to get reused times: ", err)
    return
end

-- 獲取請求ip
local function getIp()
    local clientIP = ngx.req.get_headers()["X-Real-IP"]
    if clientIP == nil then
        clientIP = ngx.req.get_headers()["x_forwarded_for"]
    end
    if clientIP == nil then
        clientIP = ngx.var.remote_addr
    end
    return clientIP
end

local cliendIp = getIp();

local incrKey = "limit:count:"..cliendIp
local blockKey = "limit:block:"..cliendIp

--查詢ip是否被禁止訪問,如果存在則返回403錯誤程式碼
local is_block,err = client:get(blockKey)
if tonumber(is_block) == 1 then
    ngx.exit(ngx.HTTP_FORBIDDEN)
    close_redis(client)
end

local ip_count, err = client:incr(incrKey)
if tonumber(ip_count) == 1 then
    client:expire(incrKey,ip_time_out)
end
--如果超過單位時間限制的訪問次數,則新增限制訪問標識,限制時間為ip_block_time
if tonumber(ip_count) > tonumber(ip_max_count) then
    client:set(blockKey,1)
    client:expire(blockKey,ip_block_time)
end

close_redis(client)

總結

以上,便是 Nginx+Lua+Redis 實現的 IP 黑名單功能,具有如下優點:

  1. 配置簡單輕量,對伺服器效能影響小。

  2. 多臺伺服器可以透過共享 Redis 例項共享黑名單。

  3. 動態配置,可以手工或者透過某種自動化的方式設定 Redis 中的黑名單

擴充套件

1、IP 黑名單的應用場景

IP 黑名單在實際應用中具有廣泛的應用場景,主要用於保護伺服器和應用免受惡意攻擊、爬蟲或濫用行為的影響。下面列舉幾個常見的應用場景:

  • 防止惡意訪問:黑名單可以阻止那些試圖透過暴力破解密碼、SQL 注入、XSS 攻擊等方式進行非法訪問的 IP 地址。

  • 防止爬蟲和資料濫用:黑名單可以限制那些頻繁訪問網站並抓取大量資料的爬蟲,以減輕伺服器負載和保護資料安全。

  • 防止 DDOS 攻擊:黑名單可以封禁那些發起大規模DDoS攻擊的IP地址,保護伺服器的穩定性和安全性。

  • 限制訪問頻率:黑名單可以限制某個IP在特定時間段內的訪問次數,防止惡意使用者進行暴力破解、刷票等行為。

2、高階功能和改進

除了基本的 IP 黑名單功能外,還可以進行一些高階功能和改進,以提升安全性和使用者體驗:

  • 異常檢測和自動封禁:透過分析訪問日誌和行為模式,可以實現異常檢測功能,並自動將異常行為的 IP 地址封禁,提高安全性。

  • 白名單機制:除了黑名單,還可以引入白名單機制,允許某些 IP 地址繞過黑名單限制,確保合法使用者的正常訪問。

  • 驗證碼驗證:對於頻繁訪問或異常行為的 IP,可以要求其進行驗證碼驗證,以進一步防止惡意行為。

  • 資料統計和分析:將黑名單相關的資料進行統計和分析,例如記錄封禁 IP 的次數、持續時間等資訊,以便後續最佳化和調整策略。

透過不斷改進和最佳化 IP 黑名單功能,可以更好地保護伺服器和應用的安全。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.