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

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

最近,我们的 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。在某个时候,我还通过发出 降低 tcp_synack_retries 到 3(从默认值 5 降低)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

然后我设置了我的响应时间测试,运行sysctl -p并禁用了 syncookies sysctl -w net.ipv4.tcp_syncookies=0

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

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

但是 syn backlog 似乎还没满,SYN_RECV 状态的连接只有大约 250 个!SYN 泛洪消息是不是一个转移注意力的借口,是不是 syn_backlog 之外的东西在填满?

如果有人有其他我还没有尝试过的调整选项,我会非常乐意尝试它们,但我开始怀疑 syn_backlog 设置是否由于某种原因没有被正确应用。

答案1

所以,这是一个巧妙的问题。

一开始我很惊讶你看到了任何启用 SYN cookies 后处于 SYN_RECV 状态的连接。SYN cookies 的优点在于,您可以使用加密技术作为服务器无状态地参与 TCP 三次握手,因此我希望服务器根本不表示半开连接,因为那将是未保留的相同状态。

事实上,快速浏览一下源代码 (tcp_ipv4.c) 就会发现有关内核如何实现 SYN cookies 的有趣信息。本质上,尽管启用了它们,内核的行为仍然与正常行为一样,直到其待处理连接队列已满。这解释了您现有的处于 SYN_RECV 状态的连接列表。

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

换句话说,如果你关闭 SYN cookies,消息就会消失。只有当你不再受到 SYN 泛滥时,这才会奏效。

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

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

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

如果您没有受到 SYN 泛洪攻击,并且计算机对非 HTTP 连接(例如 SSH)有响应,我认为可能存在网络问题,您应该请网络工程师帮助您查看。如果即使没有受到 SYN 泛洪攻击,计算机通常也没有响应,如果它影响 TCP 连接的创建(相当低级别且不占用资源),这听起来像是严重的负载问题

答案2

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

我收到了相同的内核消息,指出 Web 服务器端口可能遭受 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在 Red Hat 网站上,指出内核消息可能是由于应用程序端的错误(或配置错误)导致的。当然,日志消息非常具有误导性!因为在这种情况下,这不是负责的内核参数,而是应用程序的参数,被传递给内核。

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

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

Apache 对传入连接的积压队列有自己的配置参数。如果您有大量传入连接,并且在任何时刻(只是随机的)它们几乎同时到达,使得 Web 服务器无法以适当的方式足够快地为它们提供服务,您的积压队列将充满 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

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

sudo service apache2 restart ( or sudo /etc/init.d/apache2 restart )

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

答案3

经过对内核 3.4.9 的一些测试,netstat 中的 SYN_RECV 连接数取决于

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

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

并且增加 tcp_max_syn_backlog 后,apache 也必须重新启动。

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

相关内容