openresty自動攔截高頻IP

有次公司的一些接口被人爬數(shù)據(jù),導致web端異常緩慢。以前就知道openresty有這個功能,認識人往往就是這樣,問題發(fā)生了,才去被動解決,反思!
調(diào)研解決方案如下
1.把nginx換成openresty
2.openresy + redis 去統(tǒng)計訪問者訪問次數(shù),設置閾值,高于閾值直接返回403,一段時間后放開
調(diào)研結果如下
nginx location段配置


location  /redis_forbid {
        default_type 'text/html';
        access_by_lua_file lua/intercept.lua;
        content_by_lua_block {
        ngx.say("access")
        }
    }

intercept.lua

local redis = require("resty.redis")
local conn = redis:new()
conn:set_timeout(10000)

local redis_ip = "192.168.138.129"
local redis_port = 6379

local ok , err = conn:connect(redis_ip,redis_port)
if not ok then
    ngx.say("connect to redis fatal error: " ,err)
    return redis_close(conn)
end

-- ngx.exit(ngx.ERR) 客戶端無法返回

local ttl = 60 -- key過期時間
local top_times = 10
local forbit_ttl = 100 --60內(nèi)無法再次訪問
local ip = ngx.var.remote_addr
local ip_total_times = conn:get(ip)

print("debug...................................." , conn:ttl(ip))


if ip_total_times ~= ngx.null then
    if (ip_total_times == "-1") then
        return ngx.exit(403)
    else
        this_ttl = conn:ttl(ip)
        
        if (this_ttl == -1) then --沒有設置超時時間
            conn:set(ip,0)
            conn:expire(ip,ttl)
            return ngx.exit(ngx.OK)
        end
        v_times = tonumber(conn:get(ip)) + 1
        
        if (v_times > top_times) then
            
            conn:set(ip,-1)
            conn:expire(ip,forbit_ttl)
            return ngx.exit(ngx.OK)
        else
            print("debug 03")
            conn:set(ip,v_times)
            
            conn:expire(ip,this_ttl) -- 不要重新計時 
            return ngx.exit(ngx.OK)

        end     

        
    end
else
    print("key is not exists")
    conn:set(ip,1)
    conn:expire(ip,ttl)
    return ngx.exit(ngx.OK) --step done,如access_by_lua_file模塊此處后,進入到content_by_lua_file模塊處理
end

再寫段測試程序

package main

import (
    "net/http"
    "fmt"
    "io/ioutil"
    "os"
)

func main()  {

    for i := 1 ; i<= 20 ;i++  {
        resp,err := http.Get("http://192.168.138.128/redis_forbid")
        defer resp.Body.Close()
        if err != nil {
            os.Exit(-1)
        }
        //time.Sleep(1*time.Second)
        body, _ := ioutil.ReadAll(resp.Body)
        fmt.Println("i is", i)
        fmt.Println(string(body))
    }

}

結果訪問如下:

i is 12
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>openresty/1.13.6.2</center>
</body>
</html>
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容