前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用NGINX和NGINX Plus速率限速

使用NGINX和NGINX Plus速率限速

作者头像
用户1263954
发布2018-01-30 15:33:27
1.2K0
发布2018-01-30 15:33:27
举报
文章被收录于专栏:IT技术精选文摘IT技术精选文摘

NGINX最有用但经常被误解和配置错误的特征之一就是速率限制。 它允许您限制用户在给定时间段内可以执行的HTTP请求数量。

速率限制可以用于安全目的,例如减慢暴力密码猜测攻击。 它可以通过将传入请求率限制为真实用户的典型值,并且(通过日志记录)来识别目标URL,可以帮助防止DDoS攻击。 更一般地说,它用于保护上游应用服务器免受同时因太多用户请求而被压跨。

在本文中,我们将介绍使用NGINX进行速率限制的基础知识以及更高级的配置。 速率限制在NGINX Plus中的工作方式相同。

NGINX速率限制的工作原理

NGINX速率限制使用泄漏桶算法,其在电信和分组交换计算机网络中被广泛使用,用于在带宽有限时处理突发性。 就好比它是一个桶,从顶部倒水,然后从底部漏水; 如果倒水速度超过其漏水速率,则桶会溢出。 在请求处理方面,水表示来自客户端的请求,桶表示根据先进先出(FIFO)调度算法请求等待处理的队列。 泄漏的水代表离开缓冲区的请求,由服务器进行处理,溢出表示被丢弃和不再服务的请求。

配置基本速率限制

速率限制配置有两个主要的指令:limit_req_zone和limit_req,如下例所示:

limit_req_zone指令定义了速率限制的参数,而limit_req可以在出现的上下文中启用速率限制(在该示例中,对于/ login /的所有请求)。

limit_req_zone指令通常在http块中定义,使其可在多个上下文中使用。它需要以下三个参数:

Key - 定义应用限制的请求特性。在该示例中,它是NGINX变量$ binary_remote_addr,它保存客户端IP地址的二进制表示形式。这意味着我们将每个唯一IP地址限制为由第三个参数定义的请求速率。 (我们使用这个变量是因为它比使用$ remote_addr表示的客户端ip地址更少的空间。)

Zone - 定义用于存储每个IP地址状态的共享内存区域以及访问请求限制URL的频率。将信息保存在共享内存中意味着可以在NGINX工作进程之间共享。定义有两个部分:zone = keyword标识的区域名称以及冒号后面的大小。16,000个IP地址的状态信息大概需要1M字节,所以我们的区域可以存储大约16万个地址。

如果NGINX需要添加新条目时而存储空间不足,则其会删除最旧的条目。如果释放的空间仍然不足以容纳新记录,则NGINX返回状态码503(服务暂时不可用)。另外,为了防止内存耗尽,每次NGINX创建一个新条目时,它最多删除两个在前60秒内未使用的条目。

Rate - 设置最大请求率。在该示例中,速率不能超过每秒10个请求。 NGINX实际上以毫秒的粒度跟踪请求,所以这个限制对应于每100毫秒1个请求。因为我们不允许突发(见下一部分),这意味着如果请求在前一个允许的请求后面的100毫秒内到达则会被拒绝。

limit_req_zone指令设置速率限制和共享内存区域的参数,但实际上并不限制请求速率。为此,您需要通过在那里添加一个limit_req指令来将限制应用于特定location或server块。在这个例子中,我们是对/ login /的速率限制请求。

所以现在每个唯一的IP地址限制在/ login /的每秒10个请求 - 或者更准确地说,在前一个IP地址的100毫秒内不能请求该URL。

处理突发事件

如果我们在100毫秒内得到2个请求怎么办? 对于第二个请求,NGINX向客户端返回状态码503。 这可能不是我们想要的,因为应用程序本质上是突发的。 相反,我们希望缓冲任何超额的请求并及时为他们提供服务。 这是我们使用burst参数来限制_req,就像这个更新的配置一样:

burst参数定义了客户端可以执行多少请求,超出区域指定的速率(使用我们的例子中的mylimit区域,速率限制为每秒10个请求,或每100毫秒1个请求)。 一个早于100毫秒之前到达的请求会被放入队列中,这里我们将队列大小设置为20。

这意味着如果21个请求同时从给定的IP地址到达,则NGINX会立即将第一个请求转发到上游服务器组,并将其余20个队列放入队列中。 然后它每100毫秒转发一个排队的请求,只有当一个传入的请求使队列请求的数量超过20时,才返回503。

无延时的排队

具有突发性的配置导致流量流畅,但是不太实用,因为它可能使您的站点看起来很慢。 在我们的示例中,队列中的第20个数据包等待2秒转发,此时对客户端的响应可能不再有用。 要解决这种情况,请添加nodelay参数以及burst参数:

使用nodelay参数,NGINX仍然根据burst参数分配队列中的插槽,并施加配置的速率限制,但不排除排队请求的转发。相反,当请求到达“太早”时,只要在队列中有可用的插槽,NGINX将立即转发。它将该插槽标记为“已占用”,并且不会将其释放以供另一个请求使用,直到适当的时间过去(在我们的示例中,在100毫秒之后)。

假设如前所述,20槽的队列是空的,21个请求从给定的IP地址同时到达。 NGINX立即转发所有21个请求,并标记队列中的20个插槽,然后每100毫秒释放1个插槽。 (如果有25个请求,NGINX将立即转发其中21个,标记20个插槽,并拒绝4个请求,状态为503)。

现在假设第一组请求后的101毫秒被转发,另外20个请求同时到达。队列中只有1个槽已被释放,所以NGINX转发1个请求,并拒绝其他19,状态为503。如果在20个新请求到达之前已经过去了501毫秒,则5个槽是空闲的,所以NGINX立即转发5个请求并拒绝15 。

效果相当于每秒10个请求的速率限制。 如果您想强制使用速率限制,而不限制请求之间的允许间距,则nodelay选项将非常有用。

注意:对于大多数部署,我们建议将burst和nodelay参数包含在limit_req指令中。

高级配置示例

通过将基本速率限制与其他NGINX功能相结合,您可以实现更细微的流量限制。

白名单

此示例显示如何对不在“白名单”的任何人的请求强制设置费率限制。

此示例使用geo和map指令。 geo块为白名单中的IP地址分配0到$ limit,对所有其他IP地址分配1。 然后,我们使用map将这些值转换为关键字,以便:

如果$ limit为0,则将$ limit_key设置为空字符串

如果$ limit为1,则将$ limit_key设置为客户端的二进制格式的IP地址

把两个对齐,$ limit_key设置为白名单IP地址的空字符串,否则设置为客户端的IP地址。 当limit_req_zone目录(Key)的第一个参数是空字符串时,不会应用限制,因此白名单IP地址(10.0.0.0/8和192.168.0.0/24子网)不受限制。 所有其他IP地址每秒限制为5个请求。

limit_req指令对/ location应用限制,允许在配置的限制内突发最多10个报文,转发时间不会有延时

在Location中包含多个limit_req指令

您可以在单个Location包含多个limit_req伪指令。 符合给定请求的所有限制都将被应用,这意味着使用最严格的限制。 例如,如果多个指令施加延迟,则使用最长的延迟。 类似地,如果这是任何指令的效果,即使其他指令允许它们通过,请求也被拒绝。

扩展前面的例子,我们可以对白名单上的IP地址应用速率限制:

白名单上的IP地址没有匹配到第一个速率限制(req_zone),但匹配第二个(req_zone_wl),因此每秒限制为15个请求。 不在白名单上的IP地址匹配两个速率限制,因此限制性更强:每秒5个请求。

配置相关功能

记录

默认情况下,NGINX记录由于速率限制而延迟或丢弃的请求,如本示例所示:

日志条目中的字段包括::

limiting requests - 指示日志条目记录速率限制

excess - 每毫秒超过此请求所表示的配置速率的请求数

zone - 定义施加速率限制的区域

client - 发出请求的客户端的IP地址

server - 服务器的IP地址或主机名

request - 客户端提供的实际HTTP请求

host - 主机HTTP头的值

默认情况下,NGINX在error级别记录拒绝请求,如上例中的[error]所示。 (它将延迟请求记录在一个级别以下,默认情况下为info。)要更改日志记录级别,请使用limit_req_log_level指令。 在这里我们设置拒绝请求登录在warn级别:

发送给客户端的错误代码

默认情况下,当客户端超过其速率限制时,NGINX响应状态码503(服务暂时不可用)。 使用limit_req_status指令设置不同的状态代码(在本示例中为444):

拒绝对特定Location的所有请求

如果您要拒绝所有针对特定网址的请求,而不仅仅是限制它们,请为其配置Location,并包含deny all指令:

结论

我们已经介绍了NGINX和NGINX Plus提供的许多速率限制功能,包括为HTTP请求设置不同location的请求率,以及配置其他功能来限制速率,例如突发和节点参数。 我们还涵盖了对白名单和黑名单客户端IP地址应用不同限制的高级配置,并解释了如何记录拒绝和延迟的请求。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-09-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT技术精选文摘 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档