Home >Database >Redis >How to use lua for nginx redis access control

How to use lua for nginx redis access control

王林
王林forward
2023-06-02 16:31:15938browse

怎么使用lua进行nginx redis访问控制

1. Requirements analysis

\1. There are many ways for Nginx to handle access control, and there are also many implementation effects. Access IP segments, Access content restrictions, access frequency restrictions, etc.

\2. Using Nginx Lua Redis for access restriction mainly takes into account the need for fast access control in high concurrency environments.

\3. The process of Nginx processing requests is divided into 11 stages, which are:

post-read、server-rewrite、find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-files、content、log.

In openresty, you can find:

set_by_lua,access_by_lua,content_by_lua,rewrite_by_lua等方法。

Then the access control should be , access stage.

Solution

According to normal logical thinking, the access control solution we would think of is as follows:

1. Detect whether it is forbidden? =》Yes, whether forbidden has expired: Yes, clear the record, return 200, normal access; No, return 403; =》No, return 200, normal access

2. Each visit, visit the user's visit Frequency 1 processing

3. Check whether the access frequency exceeds the limit. If it exceeds the limit, add a forbidden record and return 403

This is a simple solution. You can also add branches and leaves, and the access prohibition time is passed The algorithm is imported, and each time the concave curve increases.

Implementation method

First add the vhost configuration file for nginx. The vhost.conf part is as follows:

lua_package_path "/usr/local/openresty/lualib/?.lua;;";#告诉openresty库地址lua_package_cpath "/usr/local/openresty/lualib/?.so;;";
error_log /usr/local/openresty/nginx/logs/openresty.debug.log debug;

server {
   listen 8080 default;
   server_name www.ttlsa.com;    
   root  /www/openresty;

   location /login {
       default_type 'text/html';
       access_by_lua_file "/usr/local/openresty/nginx/lua/access_by_redis.lua";#通过lua来处理访问控制   }
}

Access_by_redis.lua

After referring to the implementation of v2ex.com, we found that using a simple string storage solution is enough, so we chose redis as the storage method. The keys are:

User login record: user:127.0.0.1:time (unix timestamp)

Access restrictions: block:127.0.0.1

Connect to Redis first :

local red = redis:new()function M:redis()
red:set_timeout(1000)local ok, err = red:connect("127.0.0.1", 6379)if not ok then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
end

According to our logical plan, the second step is to detect whether it is forbidden. Next, we will detect block:127.0.0.1. If the data is searched, check whether the time has expired. If it has not expired, 403 will be returned. Otherwise, directly Return 200:

function M:check1()local time=os.time() --system timelocal res, err = red:get("block:"..ngx.var.remote_addr)if not res then -- redis error
 ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error  endif type(res) == "string" then --if red not null then type(red)==string
 if tonumber(res) >= tonumber(time) then  --check if forbidden expired
  ngx.exit(ngx.HTTP_FORBIDDEN)
  --ngx.say("forbidden")
 end
end
}

The next step will be to check whether the access frequency is too high. If it is too high, it will be blacklisted.

The implementation method is to detect user:127.0.0.1 Whether the value of :time exceeds the standard:

function M:check2()local time=os.time() --system timelocal res, err = red:get("user:"..ngx.var.remote_addr..":"..time)if not res then -- redis error
 ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error
endif type(res) == "string" then if tonumber(res) >= 10 then -- attack, 10 times request/s
  red:del("block:"..self.ip)
  red:set("block:"..self.ip, tonumber(time)+5*60 ) --set block time
  ngx.exit(ngx.HTTP_FORBIDDEN)
 end
end
end

Finally, remember to make an auto-increment in the time of each access, user:127.0.0.1:time:

function M:add()local time=os.time() --system time
ok, err = red:incr("user:"..ngx.var.remote_addr..":"..time)if not ok then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error
end
end

Then, test, I swiped the browser several times and found that after a while, 403 was returned. OK, done.

The above is the detailed content of How to use lua for nginx redis access control. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete