我们有一个 Ubuntu 12.04 服务器,端口 80 上带有 httpd,我们想要限制:
- 每个 IP 地址到 httpd 的最大连接数为 10
- 每秒到 httpd 的最大新连接数为 150
我们如何使用 iptables 做到这一点?
答案1
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 --connlimit-mask 32 -j REJECT --reject-with tcp-reset
这将拒绝来自一个源 IP 的超过 15 个连接。
iptables -A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit 150/second --limit-burst 160 -j ACCEPT
在应用每秒 150 个新连接(数据包)的限制之前,允许 160 个新连接(实际上是数据包)。
答案2
您希望 iptables 中的以下规则能够满足您问题中的两个要求:
iptables -t filter -I INPUT -p tcp --dport 80 -j ACCEPT
iptables -t filter -I INPUT -p tcp --dport 80 -m state \
--state RELATED,ESTABLISHED -j ACCEPT
# Adjust "--connlimit-above NN" to limit the maximum connections per IP
# that you need.
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit \
--connlimit-above 10 --connlimit-mask 32 -j DROP
# Adjust "--connlimit-above NNN" to the maximum total connections you
# want your web server to support
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit \
--connlimit-above 150 -j DROP
因为我们使用 -I (根据 OP 请求),所以我们必须以相反的顺序执行它们,以便从下往上“读取”它们。
我还建议考虑将 --connlimit-mask NN 从 32 更改为 24。这会将完整的 C 类网络(同一范围内最多 256 个 IP 地址)限制为 10 个连接。您还可以使用任何其他无类别号码,例如 22 或 30,具体取决于您认为服务的使用方式。
另外,根据您希望客户的行为方式,您可能想要在上面的两个规则中使用“-j REJECT --reject-with tcp-reset”而不是“-j DROP”,甚至只在 150 个连接最大规则中使用。
如果您拒绝连接,使用端口 80 的浏览器或软件将立即显示“不可用”状态,但 DROP 选项将导致客户端在报告站点不可用之前等待并重试几次。我自己倾向于使用 DROP,因为它的行为更像是连接不良而不是离线服务器。
此外,如果在重试期间连接限制回落到 150(或 10)以下,那么它将最终到达您的服务器。
然而,REJECT 选项将导致您站点的流量减少一小部分,因为 DROP 会导致它在重试时发送额外的数据包。可能并不是那么相关。
另一方面,如果您的端口 80 流量是集群的一部分,那么 REJECT 将告诉集群控制器它已关闭,并在重试超时期间停止向其发送流量。
RELATED,ESTABLISHED 规则是在假设您的默认规则是阻止所有流量(iptables -t filter -P INPUT DROP)的情况下存在的。这仅接受属于已接受连接的更多数据包。
另外 --syn 还告诉它注意(或计算)建立 TCP 连接的数据包。
答案3
您需要使用connlimit
允许您限制每个客户端 IP 地址(或地址块)到服务器的并行 TCP 连接数量的模块。
/sbin/iptables -I INPUT -p tcp --syn --dport 80 -m connlimit \
--connlimit-above 10 -j DROP