Maison  >  Article  >  base de données  >  Comment utiliser Lua pour le contrôle d'accès Nginx Redis

Comment utiliser Lua pour le contrôle d'accès Nginx Redis

王林
王林avant
2023-06-02 16:31:15865parcourir

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

1. Analyse des exigences

1. Nginx dispose de nombreuses façons de gérer le contrôle d'accès, et il existe de nombreux effets de mise en œuvre, tels que la plage IP d'accès, les restrictions de contenu d'accès, les restrictions de fréquence d'accès, etc.

2. L'utilisation de Nginx+Lua+Redis pour la restriction d'accès prend principalement en compte la nécessité d'un contrôle d'accès rapide dans les environnements à forte concurrence.

3. Le processus de traitement des requêtes Nginx est divisé en 11 étapes, qui sont :

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

Dans openresty, vous pouvez trouver :

set_by_lua,access_by_lua,content_by_lua,rewrite_by_lua等方法。

Ensuite, le contrôle d'accès devrait être l'étape d'accès.

Solution

Selon la pensée logique normale, la solution de contrôle d'accès à laquelle nous penserions est la suivante :

1. Détecter si c'est interdit ? =》Oui, si l'interdiction a expiré : Oui, effacer l'enregistrement, renvoyer 200, accès normal ; Non, renvoyer 403 =》Non, renvoyer 200, accès normal

2. 1 traitement

3. Vérifiez si la fréquence d'accès dépasse la limite. Si elle dépasse la limite, un enregistrement interdit sera ajouté et 403 sera renvoyé

C'est une solution simple. le temps d'interdiction d'accès est importé via l'algorithme et la courbe concave augmente à chaque fois.

Méthode d'implémentation

Ajoutez d'abord le fichier de configuration vhost pour nginx. La partie vhost.conf est la suivante :

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

Après avoir fait référence à l'implémentation de v2ex.com, nous avons constaté qu'en utilisant un simple La solution de stockage de chaînes est suffisante. C'était suffisant, c'est pourquoi Redis a été choisi comme méthode de stockage. Les clés sont :

Enregistrement de connexion utilisateur : utilisateur :127.0.0.1 :heure (horodatage unix)

Restrictions d'accès : bloc :127.0.0.1

Connectez-vous d'abord à Redis :

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

Selon notre plan logique, deuxièmement Le premier L'étape consiste à vérifier si c'est interdit. Ensuite, nous vérifierons le bloc : 127.0.0.1. Si les données sont recherchées, vérifiez si le délai n'a pas expiré, 403 sera renvoyé directement. :

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
}

Ensuite, nous vérifierons si la fréquence d'accès a été dépassée. Si elle est trop élevée, elle sera mise sur liste noire. La façon d'y parvenir est de détecter si la valeur de user:127.0.0.1:time dépasse. le 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

Enfin, pensez à prévoir un temps pour chaque visite Auto-augmentation, 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

Ensuite, testez, forcez le rafraîchissement du navigateur plusieurs fois, et constatez qu'au bout d'un moment, 403 est renvoyé, ok, c'est fait.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer