c4rt1y

使用 openresty 实现访问控制

0x01 背景

公司国外站点发生漏洞,有人恶意刷短信,目前采取了一个方案就是减少使用量,通过限制IP的形式进行处理。

0x02 安装openresty

# 下载repo文件
wget https://openresty.org/package/centos/openresty.repo -P /etc/yum.repos.d/

# update the yum index:
sudo yum check-update

# anzhuang 
sudo yum install -y openresty openresty-resty

0x03 配置环境

3.1、修改配置文件,加入限制条件 cat /etc/openresty/nginx.conf
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

	lua_shared_dict store 10m;

	init_by_lua_block {
	        require "resty.core" 	# resty.limit.count 在这个核心库
	    }

	server {
	    listen      80;
	    server_name blog.010sec.cn;  # 假设为blog地址被攻击

	    location ^~ / {
	        access_by_lua_block {
	            local limit_count = require "resty.limit.count"

	            -- rate: 3 requests per 3600s
	            local lim, err = limit_count.new("store", 3, 60)   # 存在一个缓存,记录访问次数,设置为1分钟3次
	            if not lim then
	                ngx.log(ngx.ERR, "failed to instantiate a resty.limit.count object: ", err)
	                return ngx.exit(500)
	            end

	            -- use the Authorization header as the limiting key

	            local key = ngx.req.get_headers()["X-REAL-IP"]

	            ngx.header["key"] = key

	            local delay, err = lim:incoming(key, true)

	            ngx.header["delay"] = delay
	            ngx.header["err"] = err

	            if not delay then
	                if err == "rejected" then
	                    ngx.header["X-RateLimit-Limit"] = "6"
	                    ngx.header["X-RateLimit-Remaining"] = 0
	                    return ngx.exit(503)
	                end
	                ngx.log(ngx.ERR, "failed to limit count: ", err)
	                return ngx.exit(500)
	            end

	            local remaining = err

	            ngx.header["X-RateLimit-Limit"] = "6"
	            ngx.header["X-RateLimit-Remaining"] = remaining
	        }
	        proxy_set_header Host $host;
	        proxy_set_header X-Real-IP  $remote_addr;
	        proxy_set_header X-Forwarded-For $remote_addr;
	        proxy_pass http://10.10.10.8; 	# 若能正常则访问
	    }
	}

}

3.2、重启openresty
systemctl restart openresty

3.3、开启一个新的终端访问
for i in `seq 5`;do curl blog.010sec.cn;done

3.4、查看访问日志
tail -f /etc/openresty/logs/access.log 
10.10.10.1 - - [17/May/2022:10:57:45 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.77.0"
10.10.10.1 - - [17/May/2022:10:57:46 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.77.0"
10.10.10.1 - - [17/May/2022:10:57:47 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.77.0"
10.10.10.1 - - [17/May/2022:10:57:48 +0000] "HEAD / HTTP/1.1" 503 0 "-" "curl/7.77.0"
10.10.10.1 - - [17/May/2022:10:57:49 +0000] "HEAD / HTTP/1.1" 503 0 "-" "curl/7.77.0"

# 达到了目标,在一定时间实现一定数量的访问

0x03 资料来源

https://github.com/unixhot/waf
http://openresty.org/cn/linux-packages.html
https://www.cnblogs.com/jimodetiantang/p/9408734.html
https://github.com/openresty/lua-resty-limit-traffic/blob/master/lib/resty/limit/count.md
https://hub.docker.com/r/openresty/openresty
GoTop