我有一些简单的规则来阻止黑客/垃圾邮件发送者经常使用的某些 IP 块,例如:
iptables -A INPUT -s 173.208.250.0/24 -j DROP
但是,我注意到 apache 在几天后挂起了,并且在 netstat 的输出中显示了许多 CLOSE_WAIT,并且永远不会消失:
# netstat -atlpn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 1 0 ::ffff:10.0.0.107:80 ::ffff:173.208.250.123.50813 CLOSE_WAIT 29125/httpd
这可能是由于在规则中指定了 DROP 目标导致的吗?我应该改用 REJECT 吗?
答案1
这可能是由于在规则中指定 DROP 目标造成的吗?
不。
我应该使用 REJECT 吗?
不。
INPUT 链上该规则上的 DROP 目标意味着 Apache 永远不会看到第一个 SYN 数据包或任何具有该源地址的数据包。如果不建立连接,它永远不会处于 CLOSE_WAIT 状态。参见状态图来自维基百科以下:
如您所见,CLOSE_WAIT 仅在建立会话后发生,并且仅在客户端发起关闭会话时才会在服务器上发生。使用 KeepAlive,会话保持打开状态,直到客户端或服务器之一达到超时并主动关闭会话。
服务器通常会达到此超时并关闭会话,从而导致服务器最终有大量处于 TIME_WAIT 状态的连接。默认情况下,它们将保持此状态两分钟,但这很少会导致问题。TIME_WAIT 连接(在 Linux 上)会占用 IP/端口组合,但除非您有大约 30,000 个处于 TIME_WAIT 状态的连接,否则您不会用完这些连接。
规则中的源地址范围与示例中 CLOSE_WAIT 状态的 IP 地址不匹配。
对于礼貌的人来说,如果由于某种原因您无法接受他们的连接,则 REJECT 是一种礼貌,因为它允许他们立即关闭连接,但对于黑客/垃圾邮件发送者来说,没有必要礼貌。让他们等待他们配置的任何超时时间。
所以呢能导致连接处于 CLOSE_WAIT 状态?客户端发送 FIN,服务器响应 FIN/ACK,然后等待最终 ACK。如果服务器从未收到最终 ACK,则它会一直停留在那里,直到发生其他事情(例如重新启动 Apache)。
其他代码(如硬件防火墙)中的不良连接状态跟踪可能会导致这种情况,客户端的问题也可能导致这种情况。我不确定是什么导致了您的具体问题。