openresty 고주파 IP 자동 차단

2656 단어
한 번 은 회사 의 일부 인터페이스 가 데이터 에 기어 올 라 웹 엔 드 가 매우 느리다.예전 에 openresty 가 이런 기능 을 가지 고 있다 는 것 을 알 았 습 니 다. 사람 을 알 게 되 는 것 이 바로 이 렇 습 니 다. 문제 가 발생 해서 수 동적 으로 해결 하고 반성 합 니 다!조사 연구 솔 루 션 은 다음 과 같다.

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       
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

403 Forbidden

403 Forbidden


openresty/1.13.6.2

좋은 웹페이지 즐겨찾기