为了简单起见,假设我有一个运行 nginx 的 Web 服务器,通过 php5-fpm 提供一个 php 文件(带有“hello world”消息)。
假设服务器位于 cloudflare 后面,并且对我的服务器的所有请求都通过 cloudflare 传入。
在几乎默认的配置下,nginx 报告的所有 ip 都是 cloudflare ip,因此我们使用 realip_module 并按照此链接从 cloudflare 设置真实 ip。
我的下一步是将这个 php 文件的连接和请求都限制为每个用户 IP 每秒 1 个请求(但允许 cloudflare 本身发出无限制的请求)。
根据这个答案使用$binary_remote_addr
强制限制是安全的,因为在使用 realip_module 之后,nginx 会将 ip 重写为标头上提供的任何 ip CF-Connecting-IP
。
因此,我开始进行这样的配置:
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=1r/s;
limit_conn conn_limit_per_ip 1;
limit_req zone=req_limit_per_ip burst=1 nodelay;
这意味着我只允许 1 个 http 连接和 1 个请求/秒,并且在那一秒内允许 1 个额外请求(我在这里感觉很慷慨)。
我知道这$binary_remote_addr
包括 cloudflare 报告的用户 ip,但是连接和请求仍然全部通过 cloudflare 到达服务器(因此我不能为此使用 iptables)。
我的理解limit_conn
是limit_req
,它将向任何超出这些限制的用户显示 503 状态页面。
情况1:
为了简单起见,假设同一地区的 300 个用户使用相同的 cloudflare 边缘位置在同一秒内访问该站点。
由于 cloudflare 为每个人报告不同的 ip 地址,并且每个人都在发出单个请求,所以没有人会看到 503 状态页面,并且 cloudflare 允许 300 个请求。
案例 2:
假设在那一秒内有 3 个人访问我的页面。其中 2 个用户发出了 1 个请求,而第 3 个用户使用 ab(apache 基准)同时发出了 10 个请求。
由于 cloudflare 报告的每个人的 ip 地址都不同,我可以假设前 2 个用户将毫无问题地看到我的页面,而第 3 个用户将成功请求我的页面两次(因为我使用的是 burst + nodelay),然后在该秒内为其余请求获取 503 状态页面。下一秒它将重复相同的操作,有效地将他的请求限制为 2 个请求/秒。
关注点:
由于所有这些 503 个请求仍通过 cloudflare 提供服务,其他用户是否会开始看到 cloudflare 的消息,提示由于之前的请求失败,源不可用(单击此处重试实时版本按钮)?
我知道如果服务器宕机(没有网络),cloudflare 消息将显示给所有人,并且即使服务器重新启动,它也需要几秒钟才能消失。
当我的 nginx 开始向某个不良用户回复错误 503 时,cloudflare 的“服务器离线”消息会显示给用户吗?
答案1
HTML(PHP 的输出)是默认情况下不缓存,因此除非您在 nginx 上缓存,否则他们将看到对自己请求的响应。为了万无一失,请设置指定“标准缓存”的页面规则,或者如果您想谨慎行事,可以将其设置为无缓存 - 但您必须小心匹配模式,否则 CSS/JS 不会被缓存。
我不相信其他用户会看到 503。你可以询问他们的支持人员 - 即使是免费计划,他们的响应也相当迅速。