《緩存利器》四、利用共享內存配置動態IP地址認證

在8.3節中曾提到過動態添加黑白名單地方案,下面對該內容做一個補充,代碼如下:

lua_shared_dict white_list_ip 1m;   #聲明存放白名單的共享內存
server {
    listen       80;
    server_name  testnginx.com;
    location / {
        access_by_lua_block {
            local ngx = require "ngx";
            local white_list_ip = ngx.shared.white_list_ip
            --獲取請求者的IP地址,如果Nginx的前端還有其他代理或CDN,需配置real_ip來獲取真實的用戶IP地址
            local ip  = ngx.var.remote_addr
            --在共享內存中查找請求的IP地址是否存在
            local value, flags = white_list_ip:get(ip)
            –如果查到的IP地址在白名單中,就退出access_by_lua_block,繼續執行下一個階段
            if value then
                ngx.exit(ngx.OK)
            else
                ngx.exit(ngx.HTTP_FORBIDDEN)–如果不在白名單中,就返回403錯誤
            end
        }
        echo 'ok';
    }

  --提供HTTP接口,可以修改共享內存中的數據
     location = /white_list_ip_op {
         default_type 'text/plain';
         content_by_lua_block {
              local ngx = require "ngx"
              local white_list_ip = ngx.shared.white_list_ip
              local op = ngx.var.arg_op
              local ip = ngx.var.arg_ip
              --增加白名單
              if op == 'add' then
                  white_list_ip:set(ip,'1')
              --刪除白名單
              elseif op == 'del' then
                  white_list_ip:delete(ip)
              end
              --執行完操作後,讀取當前白名單的配置
              local ds = white_list_ip:get_keys()
              if type(ds) == 'table' then
                  for _, k in ipairs(ds) do
                      ngx.say("白名單ip :  ",k)
                  end
              end
            }
      }

}

執行操作,添加1條白名單:
# curl 'http://testnginx.com/white_list_ip_op?op=add&ip=10.19.64.210'
白名單ip : 10.19.64.210
使用白名單中的IP地址 10.19.64.210訪問testnginx.com,返回結果如下:

#  curl -i http://testnginx.com/
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Tue, 29 May 2018 09:43:30 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive

ok

刪除白名單:

#  curl -i 'http://testnginx.com/white_list_ip_op?op=del&ip=10.19.64.210'
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Tue, 29 May 2018 09:44:11 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

使用白名單中的IP地址 10.19.64.210再次訪問testnginx.com,會返回異常,並提示禁止訪問,如下所示:

#  curl -i http://testnginx.com/
HTTP/1.1 403 Forbidden
Server: nginx/1.12.2
Date: Tue, 29 May 2018 09:45:21 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>

此方案存在一個隱患,即當Nginx的master進程重啓後,共享內存中的數據會丟失,會導致黑白名單的防禦失效。爲了防止數據丟失,下面提供兩種常見的解決方案。
A方案,將IP地址存放在MySQL上,再提供1個讀/寫MySQL的Lua函數,每次新增或刪除共享內存中的數據時,都將修改後的數據存放到MySQL中。當Nginx的master進程重啓後,在init_worker_by_lua階段將數據從MySQL中讀取出來插入共享內存即可。(本方案的使用方式在後續章節中會有示例。)
B方案,每次操作共享內存後,都將共享內存中的數據寫入硬盤文件。當Nginx的master進程重啓後,在init_by_lua_block階段讀取硬盤中的文件,將文件的IP地址重新插入共享內存即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章