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
修改方法:/ proc/sys/net/ipv4/tcp_max_syn_backlog
对于那些依然还未获得客户端确认的连接请求,需要保存在队列中最大数目。对于超过 128Mb 内存的系统,默认值是 1024,低于 128Mb 的则为 128。如果服务器经常出现过载,可以尝试增加这个数字。警告!假如您将此值设为大于1024,最好修改 include/net/tcp.h 里面的 TCP_SYNQ_HSIZE,以保持TCP_SYNQ_HSIZE*16 0)或者bytes-bytes/2^(-tcp_adv_win_scale)(如果tcp_adv_win_scale 128Mb 32768-610000)则系统将忽略所有发送给自己的ICMP ECHO请求或那些广播地址的请求。