我运营一个网站,从技术上讲,该网站充当另一个网站的代理(我向其发出 HTTP 请求),并且我需要确保不会建立太多同时连接,因此我使用 iptables 将其同时连接限制为 29 个:
iptables -A OUTPUT -p tcp --dport 80 -m state --state NEW -m connlimit --connlimit-above 29 -j REJECT
INPUT ACCEPT
除了默认的//之外FORWARD ACCEPT
,这是我使用的唯一规则OUTPUT ACCEPT
。
我针对我的另一台服务器测试了该规则,并且我看到该另一台服务器上的 iptables 中最多只有 29 个连接。
然而,我代理的另一个网站向我报告说,他们在高峰期看到了 1499 个同时连接。哇。这让他们的网站变得不稳定,他们不得不禁止我的服务器的 IP,他们说这让他们的网站恢复了稳定。
注意:此站点的 DNS 指向两个 IP,但 1499 远大于 29 × 2。
我运行的是 Debian 稳定版、nginx 和 php,连接是通过 PHP 的 cURL 函数建立的。我不重复使用连接,因为 PHP 的 cURL 实现使这成为不可能。
问题:这怎么可能?这有可能吗?任何想法?
我所拥有的最好的理论(这对我来说似乎是不可能的,除非他们会做一些非常时髦的事情)是,不知何故请求在我的服务器上关闭了,但在他们的服务器上没有关闭。
答案1
我认为您的猜测是正确的。连接只有在收到来自另一端的 ACK 之前才会处于 NEW 状态。您说的是“一次只允许 29 个没有 ACK 的 SYN 从端口 80 发出。”因此,您的规则将 PENDING 连接的数量限制为 29 个,但一旦建立,就没有限制了。
如果另一端及时发回 ACK,那么已收到 ACK 的连接将不再处于“新”状态,因此不会计入限制。
删除 --state 过滤器并添加目标可能值得进行测试。这样,无论状态如何,您都可以限制与 $DESTINATION_SERVER:$DESTINATION_PORT 的所有连接的速率。这可以证实您的猜测。