kernel: possible SYN flooding on port 80. Sending cookies.

以上是系统日志中的信息,可能是遭到SYN洪水攻击(SYN Flood)。

那什么是SYN Flood呢?

SYN Flood攻击是一种典型的拒绝服务型(Denial of Service)攻击。所谓拒绝服务型攻击就是通过进行攻击,使受害主机或网络不能够良好的提供服务(就是使服务器不能响应其他的访问请求),从而间接达到攻击的目的。

SYN  Flood攻击利用的是IPv4中TCP协议的三次握手(Three-Way   Handshake)过程进行的攻击。大家知道协议规定,如果一端想向另一端发起TCP连接,它需要首先发送TCP SYN   包到对方,对方收到后发送一个TCP SYN+ACK包回来,发起方再发送TCP   ACK包回去,这样三次握手就结束了。我们把TCP连接的发起方叫作"TCP客户机(TCP   Client)",TCP连接的接收方叫作"TCP服务器(TCP Server)"。值得注意的是在TCP服务器收到TCP SYN   request包时,在发送TCP   SYN+ACK包回TCP客户机前,TCP服务器要先分配好一个数据区专门服务于这个即将形成的TCP连接。一般把收到SYN包而还未收到ACK包时的连  接状态成为半开连接(Half-open Connection)。

在 最常见的SYN Flood攻击中,攻击者在短时间内发送大量的TCP   SYN包给受害者,这时攻击者是TCP客户机,受害者是TCP服务器。根据上面的描述,受害者会为每个TCP   SYN包分配一个特定的数据区,只要这些SYN包具有不同的源地址(这一点对于攻击者来说是很容易伪造的)。这将给TCP服务器系统造成很大的系统负担,  最终导致系统不能正常工作。

那又为什么发送cookie呢?这个cookie是什么呢?

这 个cookie是指SYN  Cookie。在目前以IPv4为支撑的网络协议上搭建的网络环境中,SYN   Flood是一种非常危险而常见的DoS攻击方式。到目前为止,能够有效防范SYN Flood攻击的手段并不多,而SYN   Cookie就是其中最著名的一种。SYN Cookie原理由D. J. Bernstain和 Eric   Schenk发明。在很多操作系统上都有各种各样的实现。其中包括Linux。

SYN Cookie原理

SYN  Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN  Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP  SYN包并返回TCP  SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP   ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。

从上面的介绍可以看出,SYN Cookie的原理比较简单。到实际的应用中,它有多种不同的实现方式。

打 开或关闭SYN   Cookie功能,可以设置/proc/sys/net/ipv4/tcp_syncookies的值(或在/etc/sysctl.conf中  net.ipv4.tcp_syncookies的值),值为0关闭SYN Cookie功能,值为1打开SYN Cookie功能。

如果系统资源还没问题的话,应该多数不是受到SYN Flood攻击,而是并发连接过多。如果日志里有很多这样的警告信息,并且是因为服务器负载过高而产生的,应该调整以下几个参数,直到这个警告消失:

tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow,这三个文件都是基于/proc/sys/net/ipv4目录下

tcp_max_syn_backlog变量告诉你在内存中可以缓存多少个SYN请求。该变量需要打开tcp_syncookies才有效。如果服务器负载很高,可以尝试提高该变量的值。

tcp_synack_retries变   量用于TCP三次握手机制中第二次握手,当收到客户端发来的SYN连接请求后,服务端将回复SYN+ACK包,这时服务端处于SYN_RCVD状态,并等  待客户端发来的回复ACK包。如果服务端没有收到客户端的ACK包,会重新发送SYN+ACK包,直到收到客户端的ACK包。该变量设置发送  SYN+ACK包的次数,超过这个次数,服务端将放弃连接。默认值是5。

tcp_abort_on_overflow变   量的值是个布尔值,默认值为0(FALSE关闭)。如果开启,当服务端接收新连接的速度变慢时,服务端会发送RST包(reset包)给客户端,令客户端  重新连接。这意味着如果突然发生溢出,将重获连接。仅当你真的确定不能通过调整监听进程使接收连接的速度变快,可以启用该选项。该选项会影响到客户的连  接。

一般情况下,只增加tcp_max_syn_backlog的值就可以解决问题。例如执行命令:

# echo 2048 > /proc/sys/net/ipv4/tcp_max_syn_backlog

顺便说一下SYN Cookie防火墙

SYN Cookie Firewall

从 上面的介绍可以看到,Linux内核中的SYN Cookie机制主要的功能是防止本机遭受SYN   Flood攻击的,但是在很多情况下,仅仅实现这样的SYN   Cookie机制是不够的。如果我们要考虑的是一个网关模式的防火墙,它不仅要保护本机免受各种网络攻击,还要保护它后面的所有对外有开放TCP端口的主  机免受这些攻击。比如一个局域网中有个服务器开放了FTP服务给外界,这个服务器主机就有可能遭受到来自互联网上的SYN   Flood攻击。而这时的防火墙会将所有的攻击SYN包转发给受害主机。

一种杜绝这种情况的方法是SYN Cookie Firewall。它是SYN Cookie的一种扩展形式。总的来说,它是利用原来SYN Cookie的原理在内网和外网之间实现TCP三次握手过程的代理(proxy)的机制。

为了方便描述,我们假定一个外在的TCP客户机C希望通过防火墙F连接到局域网中的一个TCP服务器S。

在 防火墙收到来自外网的SYN包时,它并不直接进行转发,而是缓存在本地,再按照原来SYN   Cookie的机制制作好一个针对这个SYN包的SYN+ACK包,注意,这个SYN+ACK包中的ack顺序号为特制的cookie值c,更重要的是这  个包的的源地址被伪造成了S的地址(为了描述方便,我们这里暂时不考虑NAT等其他因素)。这样C会接收到这个SYN+ACK包,并认为是从S反馈回来  的。于是C再响应一个ACK包,并认为与S的TCP连接已经建立起来。这时防火墙F收到这个ACK包,按照前面的描述的SYN   Cookie原理来检查这个ACK中的ack顺序号。如果认为合法,F将本地缓存的来自C的SYN包发送给S,这时S会响应一个SYN+ACK包到C,其  中也携带一个seq号,   我们设为c`。当然这个包不会到达C,而是由防火墙F截取,F根据这个包中的序列号等信息,造一个ACK包响应到S。这时的情况是:C认为自己已经与S建  立了TCP连接;S认为自己与C建立了TCP连接。以后的TCP数据内容可以直接穿过防火墙F,在S和C之间交互。

根 据SYN Cookie Firewall的工作原理,它相当于在TCP Server与TCP   Client之间实现了对三次握手协议的代理。第一次"三次握手"在TCP Client与防火墙之间进行,第二次"三次握手"在防火墙与TCP   Server之间。在第一次"三次握手"时使用前面介绍的SYN   Cookie流程。有一个问题在进行两次"三次握手"时出现了:如图所示,进行第一次"三次握手"后,TCP   Client认为后续数据包的seq值从c+1开始,而进行第二次"三次握手"后,TCP Server认为后续发来的数据包的seq值从c`+1开始,   c是cookie,c`是TCP   Server随机产生的。c和c`几乎不可能相等,也就是说在完成上面的两个"三次握手"后,如果不进行其他操作,后续从TCP Client到TCP   Server的数据包都将被认为顺序号不对而被丢掉。一种补救方法就是在防火墙本地保存一个值δ

δ = |c - c`|

利用这个差值,在每个数据包经过防火墙时,将其seq值修改一下,这样,后续的数据流量可以完美地在TCP Server和TCP Client之间传输了。


转自:http://hi.baidu.com/lizhijiemvpmvp/item/68361e2a4b0fb8d5a517b6b8

#dmesg
possible SYN flooding on port 80. Sending cookies.
possible SYN flooding on port 80. Sending cookies.
possible SYN flooding on port 80. Sending cookies.
possible SYN flooding on port 80. Sending cookies.
… …
possible SYN flooding on port 80. Sending cookies

开了syncookie之后经常会看到这个报警信息“possible SYN flooding on port 80. Sending cookies”

如果看系统资源还没问题的话,应该多数不是受到syn flood,而是并发连接过多,不过这个还是要看自己的应用。

文档建议我们修改
tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow.

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 20480
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.core.netdev_max_backlog = 1000


net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。很关键的一个参数
net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range = 1024 65000 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000  表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改 为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参 数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。