当前位置:首页 > 运维 > 正文内容

openresty中的高级限制请求

phpmianshi3周前 (09-24)运维50

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;
        ...
    }
}



版权声明:本文由PHP面试资料网发布,如需转载请注明出处。
分享给朋友:

相关文章

进程、线程和协程三者之间的区别和联系

一、进程、线程、协程1,进程    进程,直观点说,保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己独立的地址空间,有自己的堆,...

dnsmasq搭建DNS服务器详解

Dnsmasq 简介Dnsmasq 是一个轻量级的 DNS 缓存、DHCP、TFTP、PXE 服务器。作为域名解析服务器,dnsmasq 可以通过缓存 DNS 请求来提高对访问过域名的解析速度。作为...

linux中nf_conntrack table full dropping packet问题处理

概述:在日常的服务器运维过程中,发现某段时间 /var/log/messages日志报错nf_conntrack:table full,drop packet简介:nf_connt...

linux中tee显示输出结果并且保存内容到文件

介绍tee最基本的用法就是显示输出结果并且保存内容到文件中。例如显示当前目录内容,并保存到1.txt 文件中[root@dev tmp]# ls -alh |&...

linux中如何排查负载过高的问题

概况Linux的负载高,主要是由于CPU使用、内存使用、IO消耗三部分构成。任意一项使用过多,都将导致服务器负载的急剧攀升。如何判断系统是否已经Over Loadw、uptime、top 等命令都可以...

openresty中使用淘宝的concat进行css和js合并

背景我们在访问淘宝的时候,会看到代码中的js和css文件是通过一次请求获得的,我们知道浏览器一次请求只能并发访问数个资源,这样的处理错输在网络传输层面可以大大节省时间,这里使用的技术就是把css、js...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。