amy_888 发表于 2018-11-15 07:30:26

nginx + lua 限制访问

  local redis = require 'resty.redis'
  local cache = redis.new()
  local ok ,err = cache.connect(cache,'127.0.0.1','6379')
  cache:set_timeout(60000)
  -- 如果连接失败,跳转到label处
  if not ok then
  goto label
  end
  -- 白名单
  is_white ,err = cache:sismember('whitelist',ngx.var.remote_addr)
  if is_white == 1 then
  goto label
  end
  -- 黑名单
  is_black ,err = cache:sismember('blacklist',ngx.var.remote_addr)
  if is_black == 1 then
  ngx.exit(ngx.HTTP_FORBIDDEN)
  goto label
  end
  ip_forum_edittopic, err = cache:get('ip_forum_edittopic:' .. ngx.var.remote_addr)
  if ip_forum_edittopic == ngx.null then
  res , err = cache:set('ip_forum_edittopic:' .. ngx.var.remote_addr, 1)
  res , err = cache:expire('ip_forum_edittopic:' .. ngx.var.remote_addr, 43200) -- 12h重置
  end
  is_forum_ban , err = cache:get('ip_forum_edittopic:' .. ngx.var.remote_addr)
  if tonumber(is_forum_ban) > 80 then
  local source = ngx.encode_base64(ngx.var.scheme .. '://' ..
  ngx.var.host .. ':' .. ngx.var.server_port .. ngx.var.request_uri)
  local dest = 'http://127.0.0.1:5000/' .. '?continue=' .. source
  ngx.redirect(dest,302)
  goto label
  else
  res , err = cache:incr('ip_forum_edittopic:' .. ngx.var.remote_addr)
  end
  -- ip访问频率时间段
  ip_time_out = 60
  -- ip访问频率计数最大值
  connect_count = 45
  -- 60s内达到45次就ban
  -- 封禁ip时间(加入突曲线增长算法)
  ip_ban_time, err = cache:get('ip_ban_time:' .. ngx.var.remote_addr)
  if ip_ban_time == ngx.null then
  ip_ban_time = 300
  res , err = cache:set('ip_ban_time:' .. ngx.var.remote_addr, ip_ban_time)
  res , err = cache:expire('ip_ban_time:' .. ngx.var.remote_addr, 43200) -- 12h重置
  end
  -- 查询ip是否在封禁时间段内,若在则跳转到验证码页面
  is_ban , err = cache:get('ban:' .. ngx.var.remote_addr)
  if tonumber(is_ban) == 1 then
  -- source携带了之前用户请求的地址信息,方便验证成功后返回原用户请求地址
  local source = ngx.encode_base64(ngx.var.scheme .. '://' ..
  ngx.var.host .. ':' .. ngx.var.server_port .. ngx.var.request_uri)
  local dest = 'http://127.0.0.1:5000/' .. '?continue=' .. source
  ngx.redirect(dest,302)
  goto label
  end
  -- ip记录时间key
  start_time , err = cache:get('time:' .. ngx.var.remote_addr)
  -- ip计数key
  ip_count , err = cache:get('count:' .. ngx.var.remote_addr)
  -- 如果ip记录时间的key不存在或者当前时间减去ip记录时间大于指定时间间隔,则重置时间key和计数key
  -- 如果当前时间减去ip记录时间小于指定时间间隔,则ip计数+1,
  -- 并且ip计数大于指定ip访问频率,则设置ip的封禁key为1,同时设置封禁key的过期时间为封禁ip时间
  if start_time == ngx.null or os.time() - tonumber(start_time) > ip_time_out then
  res , err = cache:set('time:' .. ngx.var.remote_addr , os.time())
  res , err = cache:set('count:' .. ngx.var.remote_addr , 1)
  else
  ip_count = ip_count + 1
  res , err = cache:incr('count:' .. ngx.var.remote_addr)
  -- 统计当日访问ip集合
  res , err = cache:sadd('statistic_total_ip:' .. os.date('%x'), ngx.var.remote_addr)
  if ip_count >= connect_count then
  res , err = cache:set('ban:' .. ngx.var.remote_addr , 1)
  res , err = cache:expire('ban:' .. ngx.var.remote_addr , ip_ban_time)
  res , err = cache:incrby('ip_ban_time:' .. ngx.var.remote_addr, ip_ban_time)
  -- 统计当日屏蔽ip总数
  res , err = cache:sadd('statistic_ban_ip:' .. os.date('%x'), ngx.var.remote_addr)
  end
  end
  ::label::
  local ok , err = cache:close()

页: [1]
查看完整版本: nginx + lua 限制访问