tcp_syncookies是一个开关,是否打开SYN Cookie功能,该功能可以防止部分SYN攻击。tcp_synack_retries和tcp_syn_retries定义SYN的重试次数。
----------------------------------------参数说明------------------------------------------------------------------
$ /proc/sys/net/core/wmem_max
最大socket写buffer,可参考的优化值:873200
$ /proc/sys/net/core/rmem_max
最大socket读buffer,可参考的优化值:873200
$ /proc/sys/net/ipv4/tcp_wmem
TCP写buffer,可参考的优化值: 8192 436600 873200
$ /proc/sys/net/ipv4/tcp_rmem
TCP读buffer,可参考的优化值: 32768 436600 873200
$ /proc/sys/net/ipv4/tcp_mem
同样有3个值,意思是:
net.ipv4.tcp_mem[0]:低于此值,TCP没有内存压力.
net.ipv4.tcp_mem[1]:在此值下,进入内存压力阶段.
net.ipv4.tcp_mem[2]:高于此值,TCP拒绝分配socket.
上述内存单位是页,而不是字节.可参考的优化值是:786432 1048576 1572864
$ /proc/sys/net/core/netdev_max_backlog
进入包的最大设备队列.默认是300,对重负载服务器而言,该值太低,可调整到1000.
$ /proc/sys/net/core/somaxconn
listen()的默认参数,挂起请求的最大数量.默认是128.对繁忙的服务器,增加该值有助于网络性能.可调整到256.
$ /proc/sys/net/core/optmem_max
socket buffer的最大初始化值,默认10K.
$ /proc/sys/net/ipv4/tcp_max_syn_backlog
进入SYN包的最大请求队列.默认1024.对重负载服务器,增加该值显然有好处.可调整到2048.
$ /proc/sys/net/ipv4/tcp_retries2
TCP失败重传次数,默认值15,意味着重传15次才彻底放弃.可减少到5,以尽早释放内核资源.
$ /proc/sys/net/ipv4/tcp_keepalive_time
$ /proc/sys/net/ipv4/tcp_keepalive_intvl
$ /proc/sys/net/ipv4/tcp_keepalive_probes
这3个参数与TCP KeepAlive有关.默认值是:
tcp_keepalive_time = 7200 seconds (2 hours)
tcp_keepalive_probes = 9
tcp_keepalive_intvl = 75 seconds
意思是如果某个TCP连接在idle 2个小时后,内核才发起probe.如果probe 9次(每次75秒)不成功,内核才彻底放弃,认为该连接已失效.对服务器而言,显然上述值太大. 可调整到:
/proc/sys/net/ipv4/tcp_keepalive_time 1800
/proc/sys/net/ipv4/tcp_keepalive_intvl 30
/proc/sys/net/ipv4/tcp_keepalive_probes 3
$ proc/sys/net/ipv4/ip_local_port_range
指定端口范围的一个配置,默认是32768 61000,已够大.
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套接字拖死
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服务器系统造成很大的系统负担,最终导致系统不能正常工作。
Syn Flood 基本都是以 DDOS 模式展开攻击。
目前处理Syn Flood的问题由几个方式:
Syn Cookie:
SYN Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。
Syn Cookie Firewall ( TCP 六次握手 ):
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://www.ibm.com/developerworks/cn/linux/l-syncookie/?ca=dwcn-newsletter-linux )
对于Syn Cookie的本地防护,在Linux系统的本地已经可以通过Linux内置的Syn Cookie机制来完成。
Syn Cookie Firewall技术又被广泛的称为 TCP六次握手、TCP Syn Proxy。在上面的那张图我们看到Firewall首先跟ClientSide进行三次握手,然后再跟ServerSide进行三次握手,因此被形象地称之为 TCP六次握手。同时我们看到这就是像是一个 Proxy,接受ClientSide的请求,然后转递给ServerSide,因此在OpenBSD平台我们看到已经成功实现的此种技术被称为 TCP SYN PROXY ( http://www.openbsd.org/faq/pf/filter.html )
但是对于Linux平台,好像还没有实现Syn Cookies Firewall,不过在Linux 2.2平台出现过一个ip_scfw的东西。