1. SYN Flood攻击原理
SYN Flood是DDos攻击的其中一种形式,其原理是:在TCP连接初始化的时候需要进行三次握手(见图1和图2),攻击者在第一次握手的数据表里面,通过伪造”Source Address”(见图3),让服务器(接收端)在进行第二次握手的时候,将确认包发向一个伪造的IP地址,由于IP地址是伪造的,因此服务器端迟迟等不到第三次的确认包,导致服务器打开了大量的SYNC_RECV
半连接。
图1,引自:https://tools.ietf.org/html/rfc793#section-3.4
图2
图3
其中图3中的Flags标志位包含了SYN、ACK、RST、FIN等值,三次握手中数据包所标识的Syn和Ack等标识就是在这个位置进行标注的。
SYN Flood的攻击就是在图一的第一步中(即图中的1),因为TCP A发向TCP B的数据表的”Source Address”是伪造的,因为TCP B向伪造的IP发送了确认包(图中的2),但是由于IP是伪造的,因为TCP B一直等不到返回的确认包(图中的3),因为TCP B一直处于半打开状态,如果有大量的这样半连接,那么就会把TCP B的连接资源耗尽,最后导致TCP B无法对其他TCP连接进行响应。
2. 在虚拟环境中模拟SYN Flood攻击
我们在Vmware中安装了一台Ubuntu Server 17.10,然后我们在其中一台中安装了hping,该机器充当攻击者,另外一台充当陂攻击者。
攻击机IP:192.168.144.128
被攻击机IP:192.168.144.129
操作系统(攻击机和被攻击机):Ubuntu Server 17.10
攻击机:
被攻击机:
hping的github地址:https://github.com/antirez/hping
hping的安装方法:https://github.com/antirez/hping/blob/master/INSTALL
我们根据源码中INSTALL中的指导,成功安装hping后,在命令行中输入hping -v
,输出如下:
使用hping 192.168.144.129 –i u100000 –S –a 192.168.144.200
命令对被攻击机进行攻击。
-i
:interval,就是数据包发送的间隔,其中u表示单位是’微妙’,m表示单位是’毫秒’
-S
:使用SNY标记,表示发送的是SYN包
-a
:源地址欺骗,可以使用–rand-dest
表示随机目的地址模式,–rand-source
表示随机源目的地址模式
我们可以使用随机源地址来代替192.168.144.200
:
hping 192.168.144.129 –i u100000 –S –rand-source
我们在被攻击机(192.168.144.129)中用使用netstat -n | grep SYN_RECV | wc -l
,输出:
如果我们使用netstat -n | grep SYN_RECV
的话,会输出满屏的SYN_RECV
的半连接,如图:
3. 为什么是128个半连接
从上面的测试可以发现SYN半连接的数量最高是128,其实这是系统的tcp_max_syn_backlog
参数决定的,我们可以通过cat /proc/sys/net/ipv4/tcp_max_syn_backlog
命令查看系统的设定,默认值为128。我们为了发挥系统的性能,可以将该值设置为更大的值。
在/etc/sysctl.conf
文件中设置net.ipv4.tcp_max_syn_backlog
的值,同时,我们还需要设置net.core.somaxconn
的值,因为somaxconn
如果不调高的话,tcp_max_syn_backlog
的值是不生效的,somaxconn
的默认值也是128。最后,我们在/etc/sysctl.conf
文件中将这两个参数设置如下:
同时,我们还需要在nginx的配置文件中设置backlog的的值为2560,我们在这里使用的是nginx作为测试软件,在nginx源码中会调用listen()函数,其中的backlog参数会影响系统的socket连接性能发挥。
最后,我们再次进行攻击测试,结果如下:
此时,如果我们使用curl
命令对目标机进行正常的Http访问,此时将不会返回结果,连接一直挂起直到连接超时:
4. 如果避免SYN Flood攻击
tcp_syncookies (Boolean; since Linux 2.2)
Enable TCP syncookies. The kernel must be compiled with
CONFIG_SYN_COOKIES. Send out syncookies when the syn backlog
queue of a socket overflows. The syncookies feature attempts
to protect a socket from a SYN flood attack. This should be
used as a last resort, if at all. This is a violation of the
TCP protocol, and conflicts with other areas of TCP such as
TCP extensions. It can cause problems for clients and relays.
It is not recommended as a tuning mechanism for heavily loaded
servers to help with overloaded or misconfigured conditions.
For recommended alternatives see tcp_max_syn_backlog,
tcp_synack_retries, and tcp_abort_on_overflow.
摘自:http://man7.org/linux/man-pages/man2/listen.2.html
使用syncookie的基本原理是:在第二次TCP握手的时候,Server端不为连接分配资源,Server端返回了带syncookies的syn,ack包,在第三次握手的时候client端也要带上这个syncookie,此时Server端才正式分配系统资源。
但是Linux的man手册中并不推荐syncookie这种方式,认为这是违反TCP协议的,同时与TCP的其他部分产生冲突。man手册建议调整tcp_max_syn_backlog,也就是本文所讨论到的参数。同时可以调整tcp_synack_retries或tcp_abort_on_overflow参数。
tcp_synack_retries:表示SYN/ACK重试的次数,我们降低这个值可以在syn Flood的时候减少等待超时后的重试次数,从而减少系统资源的消耗。
tcp_abort_on_overflow:表示在系统无法接受更多的连接的时候,系统就会抛弃掉这些新的连接。man手册明确提到:这个参数只有在系统无法继续调优接收更多的连接时才使用,因为设置这个参数为true会对client端的连接造成负面的影响。
5. 一点题外话
5.1 backlog参数和/proc/sys/net/ipv4/tcp_max_syn_backlog参数的区别
The behavior of the backlog argument on TCP sockets changed with
Linux 2.2. Now it specifies the queue length for completely
established sockets waiting to be accepted, instead of the number of
incomplete connection requests. The maximum length of the queue for
incomplete sockets can be set using
/proc/sys/net/ipv4/tcp_max_syn_backlog. When syncookies are enabled
there is no logical maximum length and this setting is ignored. See
tcp(7) for more information.
If the backlog argument is greater than the value in
/proc/sys/net/core/somaxconn, then it is silently truncated to that
value; the default value in this file is 128. In kernels before
2.4.25, this limit was a hard coded value, SOMAXCONN, with the value
128.
摘自:http://man7.org/linux/man-pages/man7/tcp.7.html
从man手册中的上述这段话,我们可以看出backlog参数影响的是已经完成TCP三次握手的网络连接的队列长度,而/proc/sys/net/ipv4/tcp_max_syn_backlog影响的是尚未完成TCP三次握手的半连接的队列长度。
6. 参考文献
https://tools.ietf.org/html/rfc793#section-3.4
https://www.hi-linux.com/posts/57862.html
http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html