通過OpenResty實現Nginx動態拉黑IP
前面提到過,nginx在項目中的作用。其實還有很多高級模塊功能,例如今天我們利用OpenResty來防止一些IP惡意攻擊。
OpenResty® 是一個基于 Nginx 與 Lua 的高性能 Web 平臺,其內部集成了大量精良的 Lua 庫、第三方模塊以及大多數的依賴項。用于方便地搭建能夠處理超高并發、擴展性極高的動態 Web 應用、Web 服務和動態網關。
官方地址:http://openresty.org/cn/
環境搭建
本文使用centos 7進行操作,安裝nginx,本處安裝nginx并非是openresty前提,只是為了演示openresty安裝后,訪問地址會將nginx變成openresty
wget下載
- wget http://nginx.org/download/nginx-1.19.5.tar.gz
解壓并執行安裝命令
- tar -zxvf nginx-1.19.5.tar.gz #解壓
- cd nginx-1.19.5 #進入目錄
- ./configure #配置
- make #編譯
- make install #安裝
- cd /usr/local/nginx/sbin #切換到nginx命令目錄
- ./nginx #啟動nginx
訪問地址

安裝openresty,先下載openresty,
- wget https://openresty.org/download/openresty-1.19.3.1.tar.gz
- (此版本最終一直無法加載一些lua腳本,最終使用openresty-1.15.8.3版本成功)
(此版本最終一直無法加載一些lua腳本,最終使用openresty-1.15.8.3版本成功)

解壓&安裝
- tar -zxvf openresty-1.19.3.1.tar.gz
- cd openresty-1.19.3.1
- yum install pcre-devel openssl-devel gcc curl
- ./configure
- make
- make install
執行完后,我們啟動openresty中得nginx,注意,切換到openresty安裝得路徑
- /usr/local/openresty/nginx/sbin
啟動后,訪問,發現nginx變成了openresty

配置nginx.conf
測試lua功能


可以看到已經可以使用lua腳本,下面我們將redis sdk引用進來

配置請求路徑訪問lua腳本(本處只是做一個demo,如果對所有路徑進行訪問限制,可以攔截/,然后lua驗證通過后,進行請求轉發)

lua腳本
- # Lua
- local function close_redis(redcli)
- if not redcli then
- return
- end
- --釋放連接(連接池實現)
- local pool_max_idle_time = 10000 --毫秒
- local pool_size = 100 --連接池大小
- local ok, err = redcli:set_keepalive(pool_max_idle_time, pool_size)
- if not ok then
- ngx_log(ngx_ERR, "set redis keepalive error : ", err)
- end
- end
- -- 連接redis
- local redis = require('resty.redis')
- local redcli = redis.new()
- redcli:set_timeout(1000)
- local ip = "127.0.0.1" ---修改變量
- local port = "6379" ---修改變量
- local ok, err = redcli:connect(ip,port)
- if not ok then
- return close_redis(redcli)
- end
- local clientIP = ngx.var.remote_addr
- -- increKey為請求頻率,blackKey黑名單key
- local incrKey = "user:"..clientIP..":request:frequency"
- local blackKey = "user:"..clientIP..":black:list"
- local is_black,err = redcli:get(blackKey)
- if tonumber(is_black) == 1 then
- ngx.exit(403)
- close_redis(redcli)
- end
- inc = redcli:incr(incrKey)
- ngx.say(inc)
- if inc < 2 then
- inc = redcli:expire(incrKey,1)
- end
- if inc > 2 then --每秒2次以上訪問即視為非法,會阻止30s的訪問
- redcli:set(blackKey,1)
- redcli:expire(blackKey,30)
- end
- close_redis(redcli)
啟動nginx后,請求一直報錯

- 2020/12/01 19:13:53 [error] 2101#0: *2 lua entry thread aborted: runtime error: /usr/local/openresty/nginx/lua/access_by_redis.lua:29: attempt to call field 'get_headers' (a nil value)
- stack traceback:
- coroutine 0:
- /usr/local/openresty/nginx/lua/access_by_redis.lua: in main chunk, client: 192.168.49.1, server: localhost, request: "GET /test1 HTTP/1.1", host: "192.168.49.131"
這個問題困擾了我很久(凡是不要一上來就最新版本,吐血說明)
windows版本的openresty并沒有出現此問題,liunux一直都有問題,最終降低了openresty版本,實驗成功,openresty-1.15.8.3版本
正常請求

異常請求

最后openresty的運行周期圖如下,可以從整體上了解openresty
