尽pipeSYN_RECV连接数很less,但日志中可能出现“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.在某些时候,我还通过发行sysctl -w net.ipv4.tcp_synack_retries=3将tcp_synack_retries降低到了3(从默认值5降低了) 。 这样做后,频率似乎下降,消息的间隔大约60和180秒之间变化。

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

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

有没有其他的tcp设置会限制积压的大小,还是我吠叫错误的树? netstat -tuna的SYN_RECV连接的数量是否与积压的大小相关?


更新

尽我所能告诉我在这里处理合法的连接, netstat -tuna|wc -l徘徊在5000左右。我今天一直在研究这个,并且从last.fm员工那里find了这个post , 这个post非常有用。

我还发现,当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 

然后我设置我的响应时间testing,通过sysctl -w net.ipv4.tcp_syncookies=0运行sysctl -p并禁用syncookies。

这样做后SYN_RECV状态中的连接数仍然保持在220-250左右,但连接又开始延迟。 一旦我注意到这些延迟,我重新启用syncookies和延迟停止。

我相信我所看到的仍然是从最初的状态改善,但是一些请求仍然延迟,这比启用了syncookies更糟糕。 所以看起来像我坚持让他们启用,直到我们可以得到更多的服务器在线应付负载。 即使如此,我不确定我看到一个有效的理由再次禁用它们,因为它们只是在服务器的缓冲区满了时才发送(显然)。

但syn backlog看起来并不完整,在SYN_RECV状态下只有〜250个连接! SYN flooding消息是否可能是一个红色的鲱鱼,而不是syn_backlog是填满?

如果任何人有任何其他调整选项,我还没有尝试过,我会高兴地尝试出来,但我开始怀疑是否syn_backlog设置由于某种原因没有正确应用。

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

    起初,我很惊讶你看到SYN_RECV状态下的任何连接都启用了SYN cookies。 SYN cookies的美妙之处在于你可以无状态地使用encryption技术作为服务器参与TCP三次握手,所以我希望服务器根本不代表半开放连接,因为这将是一个非常相同的状态,不被保留。

    实际上,快速浏览一下源代码(tcp_ipv4.c)可以看到有关内核如何实现SYN cookie的有趣信息。 本质上,尽pipe打开它们,但内核的行为与正常情况下一样,直到其挂起的连接队列已满。 这解释了您在SYN_RECV状态下的现有连接列表。

    只有等待连接的队列已满,并且接收到另一个SYN数据包(连接尝试),并且从最后一个警告消息开始已经超过了一分钟,内核是否发送了您所看到的警告消息(“正在发送cookie” )。 即使警告消息不是,也会发送SYN Cookie。 警告信息只是为了让你们知道这个问题并没有消失。

    换句话说,如果closuresSYN Cookie,邮件将会消失。 如果你不再被SYN淹没的话,那只是为了你。

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

    • net.ipv4.tcp_synack_retries
      • 对于那些被欺骗的传入连接,对于任何接收到SYN cookie而不是服务器端状态的任何连接,都不会有任何正面的影响。
      • 对于传入的欺骗性连接,增加这个数值可以增加发送给假地址的数据包的数量,也可能增加欺骗地址停留在连接表中的时间(这可能是一个重大的负面影响)。
      • 在正常的负载/传入连接数量下,这个值越高,您就越有可能通过丢弃数据包的链接快速/成功完成连接。 增加这个收益递减。
    • net.ipv4.tcp_syn_retries :更改此项对入站连接没有任何影响(只影响出站连接)

    你提到的其他variables我还没有研究,但我怀疑你的问题的答案是非常正确的。

    如果您没有被SYN泛滥,并且机器对非HTTP连接(例如SSH)有反应,我认为可能是networking问题,您应该让networking工程师帮助您查看。 如果机器通常没有响应,即使你没有被SYN淹没,这听起来像是一个严重的负载问题,如果它影响TCP连接的创build(相当低的水平和资源非密集型)

    我已经面对完全相同的问题上运行一个web服务器(apache2)与重载网站的全新安装的Ubuntu Oneiric 11.10。 在Ubuntu Oneiric 11.10上,syncookies是默认启用的。

    我有相同的内核消息,说明networking服务器端口上可能发生SYN泛洪攻击:

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

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

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

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

    所以我们也应该看看我们的web服务器应用程序的configuration参数。 抓住Apache文档,并转到http://httpd.apache.org/docs/2.0/mod/mpm_common.html#listenbacklog

    ListenBacklog参数的默认值是511.(这与您在红帽服务器上观察到的连接数量相对应,您的另一台服务器可能configuration的编号较小)。

    Apache对于传入连接的积压队列有一个自己的configuration参数。 如果你有很多传入的连接,并且在任何时候(就像一个随机的东西),它们几乎同时到达,这样Web服务器不能够以适当的方式足够快地服务它们,你的积压将会充满了511个连接,内核将触发上面的消息,指出可能的SYN洪水攻击。

    为了解决这个问题,我把下面一行加到/etc/apache2/ports.conf或者其他的.conf文件中,这个文件会被apache加载( /etc/apache2/apache2.conf也可以):

    ListenBackLog 5000

    您还应该将net.ipv4.tcp_max_syn_backlog设置为合理的值。 根据我的理解,内核最大值将会限制这个值,你可以在apacheconfiguration中进行configuration。 所以运行:

     sudo sysctl -w net.ipv4.tcp_max_syn_backlog=5000 

    调整configuration后,不要忘记重新启动你的apache:

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

    在我的情况下,这个configuration更改立即停止了内核警告。 我可以通过在apacheconfiguration中设置一个较低的ListenBackLog值来重现这些消息。

    在使用内核3.4.9进行一些testing之后,netstat中的SYN_RECV连接的数目依赖于

    • /proc/sys/net/core/somaxconn舍入到2的下一个幂(例如128 – > 256)
    • 如果/proc/sys/net/ipv4/tcp_syncookies设置为1/proc/sys/net/ipv4/tcp_syncookies设置为0或100%时, /proc/sys/net/ipv4/tcp_syncookies 1
    • ListenBackLog在apacheconfiguration中向上舍入到2的下一个幂(例如128-> 256)

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

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

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