这是一台运行 Apache 2.4 的繁忙 Web 服务器。最近我们注意到几次短暂的中断,服务器在短时间内(不到一分钟)处理传入请求时超时。查看 Apache 错误日志,每次中断都与多次此类错误相关:
[Thu Dec 19 12:37:21.104416 2019] [http2:info] [pid 10827:tid 46937350948608] [client <ip address>:62355] h2_stream(209-285,HALF_CLOSED_REMOTE): redo, added to q
哪里总是同一个地址,不在我们的组织内。具体来说,我们会立即在日志中收到这一系列错误后一系列请求超时。
因此,不知何故,该 IP 向我们的服务器发送了大量请求,从而触发了此错误,并且这在某种程度上阻止了服务器响应来自其他 IP 的其他不相关请求。这包括从服务器向自身发出的 curl 请求,这些请求失败就是我们注意到这种情况的原因。(这些是我们当前在同一台服务器上运行的独立网站之间进行的 API 调用。)
例如,最近,我们在 UTC 时间 20:36:35 至 20:37:16 之间遇到了多个 API 请求超时的情况。(这些请求的超时时间为 10 秒,因为它们通常会立即返回,因此第一个超时请求始于 20:36:25。)然后我们在 20:37:06 的错误日志中收到了 2 份上述错误的副本,然后收到了 76 份时间戳从 20:37:16 到 20:37:29 的副本。
76 个请求根本不足以耗尽我所知道的任何资源,例如 Apache 线程或 TCP 连接。而且显然该错误似乎与 http2 有关 - 可能是某种通常使用时间很短的 SSL 协商资源,因此少数实例通常可以处理我们的流量水平?但显然,如果单个 IP 可以在流量如此之少的情况下有效地对我们的服务器实施 DOS 攻击,这将暴露我们设置中的漏洞。
所以我的问题是,这个错误是什么意思,是否有一个配置设置我可以增加来缓解看似相对较低的限制,以及我们如何防止 IP 通过此类请求有效地对我们的服务器进行 DOS 攻击?
答案1
事实证明,这是由于 PHP-FPM 的动态进程创建造成的。在服务器流量快速激增时,需要启动额外的 PHP-FPM 进程,但启动新进程时会陷入停滞,并丢弃请求。将 PHP-FPM 的池配置从动态更改为静态解决了这个问题(但代价是空闲内存使用率略高,因为每个空闲的 PHP-FPM 进程使用大约 500kB)。或者,我们可以通过大幅增加最小备用服务器设置来解决这个问题,但我们认为,为了节省少量内存,这样做并不值得。