首页 > 运维 > openresty中的高级限制请求
2021
09-24

openresty中的高级限制请求

Nginx 有ngx_http_limit_req_module可用于限制请求处理速率,但大多数人似乎只使用其基本功能:通过远程地址限制请求率

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    ...
    server{
        ...
        location/search/{
            limit_req zone=one burst=5;
        }

这是从 Nginx 的官方文档中获取的示例配置,limit_req_zone 指令将变量 $binary_remote_addr 作为限制传入请求的键。密钥填充名为 one 的区域,该区域由 zone 参数定义,它可以使用最多 10m 的内存。而 rate 参数表示每个 $binary_remote_addr 的最大请求率是每秒 1。在搜索位置块中,我们可以使用 limit_req 指令来引用一个区域,突发不超过 5 个请求。

一切看起来都很棒,我们已经配置了 Nginx 来对抗流氓机器人/蜘蛛,对吧?

没有!该配置在现实生活中不起作用,它永远不应该在您的生产环境中使用!以下列情况为例:

  • 当用户在 NAT 后访问您的网站时,他们共享相同的公共 IP,因此 Nginx 将仅使用一个 $binary_remote_addr 来执行限制请求。总共有数百名用户每天只能访问您的网站 1 次!

  • 僵尸网络用于抓取您的网站,每次使用不同的 IP 地址。同样,在这种情况下,限制 $binary_remote_addr 是完全没用的。

那么我们应该使用什么配置呢?我们需要使用不同的变量作为键,或者甚至将多个变量组合在一起(从版本 1.7.6 开始,limit_req_zone 的键可以采用多个变量)。而不是远程地址,最好使用请求 HTTP 标头来区分用户,例如 User-Agent,Referer,Cookie 等。这些标头在 Nginx 中很容易访问,它们作为内置变量公开,如 $http_user_agent,$http_referer,$cookie_ name 等

例如,这是定义区域的更好方法:

http {
    limit_req_zone $binary_remote_addr$http_user_agent zone=two:10m rate=90r/m;
}

它将 $binary_remote_addr 和 $http_user_agent 组合在一起,因此可以区分 NATed 网络后面的不同用户代理。但它仍然不完美,多个用户可以使用相同的浏览器,相同的版本,因此他们发送相同的 User-Agent 标头!另一个问题是 $http_user_agent 变量的长度不固定(与 $binary_remote_addr 不同),长标头可能会使用该区域的大量内存,可能超过它。

为了解决第一个问题,我们可以在那里使用更多变量,cookie 会很棒,因为不同的用户发送他们独特的 cookie,比如 $cookie_ userid,但这仍然是我们的第二个问题。答案是使用变量哈希代替。

Thers 是一个名为set-misc-nginx-module的第三方模块,我们可以用它来从变量生成哈希值。如果您使用的是 Openresty,则已包含此 moule。所以配置是这样的:

http {
    ...
    limit_req_zone $binary_remote_addr$cookie_hash$ua_hash zone=3:10m rate=90r/m;
    ...
    server{
        ...
        set_md5 $cookie_hash $cookie_userid;
        set_md5 $ua_hash $http_user_agent;
        ...
    }
}

我们可以在 http 块中使用 $cookie_hash 和 $ua_hash,然后在 server 块中定义它们。这个配置现在很棒。

现在让我们继续解决分布式僵尸网络问题,我们需要从密钥中取出 $binary_remote_addr,因为这些机器人通常不会发送 Referer 标头(否则你可以自己找到它的独特之处),我们可以利用它。这个配置应该照顾它:

http {
    ...
    limit_req_zone $cookie_hash $referer_hash $ua_hash zone=3:10m rate=90r/m;
    ...
    server{
        ...
        set_md5 $cookie_hash$cookie_userid;
        set_md5 $referer_hash $http_referer;
        set_md5 $ua_hash $http_user_agent;
        ...
    }
}



本文》有 0 条评论

留下一个回复