尽管 SYN_RECV 连接数很少,但日志中仍存在“可能的 SYN 泛洪”

Ale*_*bes 31 linux kernel tcp flooding

最近我们有一个 apache 服务器,由于 SYN 泛滥,它的响应非常缓慢。解决方法是启用 tcp_syncookies ( net.ipv4.tcp_syncookies=1 in /etc/sysctl.conf)。

如果您想要更多背景知识,我在这里发布了一个关于此的问题。

启用 syncookies 后,我们开始大约每 60 秒在 /var/log/messages 中看到以下消息:

[84440.731929] possible SYN flooding on port 80. Sending cookies.

Vinko Vrsalovic 告诉我,这意味着 syn backlog 已满,所以我将 tcp_max_syn_backlog 提高到 4096。在某些时候,我还通过发出sysctl -w net.ipv4.tcp_synack_retries=3. 这样做之后,频率似乎下降了,消息的间隔在大约 60 到 180 秒之间变化。

接下来我发出了sysctl -w net.ipv4.tcp_max_syn_backlog=65536,但仍然在日志中收到消息。

在所有这一切中,我一直在观察处于 SYN_RECV 状态的连接数(通过运行watch --interval=5 'netstat -tuna |grep "SYN_RECV"|wc -l'),它永远不会高于大约 240,远低于积压的大小。但是我有一个 Red Hat 服务器,它在 512 左右徘徊(此服务器的限制是默认值 1024)。

是否有任何其他 tcp 设置会限制积压的大小,或者我是否在咆哮错误的树?SYN_RECV 连接的数量是否应该netstat -tuna与积压的大小相关?


更新

尽我所能,我正在处理这里的合法连接,netstat -tuna|wc -l徘徊在 5000 左右。我今天一直在研究这个,并发现了来自 last.fm 员工的这篇文章,它非常有用。

我还发现启用 syncookies 时 tcp_max_syn_backlog 不起作用(根据此链接

因此,作为下一步,我在 sysctl.conf 中设置了以下内容:

net.ipv4.tcp_syn_retries = 3
        # default=5
net.ipv4.tcp_synack_retries = 3
        # default=5
net.ipv4.tcp_max_syn_backlog = 65536
        # default=1024
net.core.wmem_max = 8388608
        # default=124928
net.core.rmem_max = 8388608
        # default=131071
net.core.somaxconn = 512
        # default = 128
net.core.optmem_max = 81920
        # default = 20480
Run Code Online (Sandbox Code Playgroud)

然后我设置了我的响应时间测试,sysctl -p通过sysctl -w net.ipv4.tcp_syncookies=0.

执行此操作后,处于 SYN_RECV 状态的连接数仍保持在 220-250 左右,但连接再次开始延迟。一旦我注意到这些延迟,我就重新启用了 syncookies 并且延迟停止了。

我相信我所看到的仍然是初始状态的改进,但是一些请求仍然被延迟,这比启用 syncookies 更糟糕。所以看起来我一直坚持启用它们,直到我们可以让更多的服务器联机以应对负载。即便如此,我也不确定是否有正当理由再次禁用它们,因为它们仅在(显然)服务器缓冲区已满时才发送。

但是 SYN_RECV 状态下只有约 250 个连接,syn 积压似乎并不完整!SYN 泛滥消息是否有可能是一条红鲱鱼,而不是正在填满的 syn_backlog?

如果有人有我还没有尝试过的任何其他调整选项,我很乐意尝试一下,但我开始怀疑是否由于某种原因没有正确应用 syn_backlog 设置。

Sla*_*ast 28

所以,这是一个很好的问题。

最初,我很惊讶您在启用 SYN cookie 的情况下看到任何处于 SYN_RECV 状态的连接。SYN cookie 的美妙之处在于,您可以使用加密技术作为服务器无状态地参与 TCP 3 次握手,因此我希望服务器根本不会表示半开连接,因为那将是完全相同的状态不被保留。

事实上,快速浏览源代码 (tcp_ipv4.c) 会显示有关内核如何实现 SYN cookie 的有趣信息。本质上,尽管打开了它们,内核仍会正常运行,直到其挂起的连接队列已满。这解释了您现有的 SYN_RECV 状态连接列表。

只有当挂起的连接队列已满,并且收到另一个 SYN 数据包(连接尝试),并且距离上次警告消息已经超过一分钟时,内核才会发送您看到的警告消息(“发送 cookie”) )。即使没有警告消息,也会发送 SYN cookie;警告消息只是为了提醒您问题尚未消失。

换句话说,如果您关闭 SYN cookie,消息就会消失。如果您不再被 SYN 淹没,那只会对您有用。

要解决您所做的其他一些事情:

  • net.ipv4.tcp_synack_retries
    • 增加此设置不会对那些被欺骗的传入连接产生任何积极影响,也不会对任何接收 SYN cookie 而不是服务器端状态的连接产生任何积极影响(它们也不会重试)。
    • 对于传入的欺骗连接,增加此值会增加您发送到假地址的数据包数量,并且可能会增加该欺骗地址在您的连接表中保留的时间(这可能是一个显着的负面影响)。
    • 在正常负载/传入连接数下,该值越高,您就越有可能通过丢弃数据包的链接快速/成功地完成连接。增加这一点的回报是递减的。
  • net.ipv4.tcp_syn_retries: 改变这个对入站连接没有任何影响(它只影响出站连接)

你提到的其他变量我还没有研究过,但我怀疑你的问题的答案就在这里。

如果您没有被 SYN 淹没并且机器响应非 HTTP 连接(例如 SSH),我认为可能存在网络问题,您应该让网络工程师帮助您查看。如果即使您没有被 SYN 淹没,机器通常也没有响应,如果它影响 TCP 连接的创建(非常低级别和资源非密集型),这听起来像是一个严重的负载问题


Jef*_*eff 16

我在全新安装的 Ubuntu Oneiric 11.10 上遇到了完全相同的问题,该 Ubuntu Oneiric 11.10 运行带有重载网站的网络服务器 (apache2)。在 Ubuntu Oneiric 11.10 上,默认启用了 syncookies。

我有相同的内核消息,说明可能对网络服务器端口进行 SYN 洪水攻击:

内核:[739408.882650] TCP:端口 80 上可能发生 SYN 泛洪。正在发送 cookie。

同时,我很确定,没有发生攻击。我有此消息以 5 分钟的间隔返回。这看起来就像是负载窥视,因为攻击者会一直保持高负载,同时试图让服务器停止响应请求。

调整net.ipv4.tcp_max_syn_backlog参数没有带来任何改进 - 消息以相同的速度继续。SYN_RECV 连接的数量总是非常低(在我的情况下低于 250)这一事实表明,必须有其他一些参数负责此消息。

我在红帽网站上发现了这个错误消息https://bugzilla.redhat.com/show_bug.cgi?id=734991指出内核消息可能是应用程序端的错误(或配置错误)的结果. 当然,日志消息非常具有误导性!因为在这种情况下,这不是负责的内核参数,而是您的应用程序的参数,bee 传递给内核。

所以我们还应该看看我们的网络服务器应用程序的配置参数。获取 apache 文档并转到http://httpd.apache.org/docs/2.0/mod/mpm_common.html#listenbacklog

ListenBacklog参数的默认值为511。(这与您在 red hat 服务器上观察到的连接数相对应。您的另一台服务器可能配置了较低的数字。)

Apache 有一个自己的配置参数,用于传入连接的积压队列。如果您有很多传入连接,并且在任何时候(就像随机的事情一样)它们几乎同时到达,这样网络服务器就无法以适当的方式为它们提供足够快的服务,您的积压将充满 511 个连接,内核将触发上述消息,说明可能存在 SYN 洪水攻击。

为了解决这个问题,我/etc/apache2/ports.conf将以下行添加到其他 .conf 文件之一,该文件将由 apache 加载(/etc/apache2/apache2.conf应该也可以):

ListenBackLog 5000

您还应该将 设置net.ipv4.tcp_max_syn_backlog为一个合理的值。据我了解,内核最大值将限制您可以在 apache 配置中配置的值。所以运行:

sudo sysctl -w net.ipv4.tcp_max_syn_backlog=5000
Run Code Online (Sandbox Code Playgroud)

调整配置后,不要忘记重新启动 apache:

sudo service apache2 restart ( or sudo /etc/init.d/apache2 restart )
Run Code Online (Sandbox Code Playgroud)

就我而言,此配置更改立即停止了内核警告。我可以通过在 apache 配置中设置较低的 ListenBackLog 值来重现消息。

  • 很好的答案。假设您说的是正确的,我会将其标记为已接受的答案,但我无法真正对其进行测试 - 减少负载解决了问题,并且我的政策是在没有正当理由的情况下不修补生产服务器:) (2认同)

uso*_*oft 5

在对内核 3.4.9 进行一些测试后,netstat 中的 SYN_RECV 连接数取决于

  • /proc/sys/net/core/somaxconn 四舍五入到 2 的下一个幂(例如 128 -> 256)
  • /proc/sys/net/ipv4/tcp_max_syn_backlogif 的75%/proc/sys/net/ipv4/tcp_syncookies设置为0或 100% if/proc/sys/net/ipv4/tcp_syncookies设置为1
  • ListenBackLog 在 apache 配置中四舍五入到 2 的下一个幂(例如 128 -> 256)

使用每个参数中的最小值。更改 somaxconn 或 ListenBackLog 后,必须重新启动 apache。

在增加 tcp_max_syn_backlog 之后,apache 也必须重新启动。

没有 tcp_syncookies apache 是阻塞的,为什么在这种情况下只有 75% 的 tcp_max_syn_backlog 是限制是奇怪的。并增加此参数将 SYN_RECV 连接增加到旧值的 100%,而无需重新启动 apache。