以下内容纯属虚构,切勿轻易相信!
syn/ack/fin
三个标志位报文决定,但是这三个标志位报文,并不是说在构建连接的时候只发送一次的,因为协议不知道网络状况. 故而就存在了以下参数,可以调节发送次数syn+ack
标志位报文的重试次数,什么时候发送syn+ack
标志位呢?三次握手中,响应端为了应答请求端的syn
标志位报文,同时请求构建的时候,默认是5次,和上面一样,网络环境好,就来个2.syn+ack
报文的攻击,也就是说,如果有疯子一直大量发送syn标志位,但是服务器需要发送syn+ack
来响应,但是那个疯子却不回复ack
标志位,导致服务器需要一直重试到次数结束.syn
等待队列是有上限的,因为大量疯子的syn
报文占用了,那么服务器就接收不到正常的syn报文请求了.这里还有一个响应端syn
等待队列的参数SYN_RCVD
状态队列,默认是1024,根据服务器性能和负载情况,可以调高此数值,比如8192syn
等待队列也溢出了,该怎么搞?可以启用net.ipv4.tcp_syncookies
SYN_RCVD
的状态还是128或者512(内核小于2.6.20),其原因如下:
listen
函数会在调用的时候读取内核参数net.core.somaxconn
的值,它的默认值是128,来确定backlog
的大小listen
函数有一个固定值TCP_SYNQ_HSIZE
这个单向链表数组,它的默认值是512,你可以修改这个值,确保这个值*16 <= net.ipv4.tcp_max_syn_backlog,这个链表的位置在$KERNEL/include/net/tcp.h
listen
的显性参数backlog
,那么服务依然会限制listen 80 default backlog = 8192
listen.backlog = 8192
tcp_max_syn_backlog
是针对syn
半开连接的话,这个参数就是针对一个整体的,意思就是说当内核处理不过来的时候,多余的就先扔到队列中syn
等待队列溢出的时候,就给请求端发送syncookies
,直接绕过三次握手,构建连接.但这违反了tcp/ip
协议,可能会影响其他服务,所以如果不确定是攻击,而是正常负载,则不要开启OK,假设我们内核是大于2.6.20的,那么我们如果想要实现以下场景:
- 一个服务器,加载的是nginx服务,他正在接收请求,请求越来越多,他处理不过来了,所以将多余的请求扔到了一个队列中(队列上限8192);
- net.core.netdev_max_backlog = 8192
- 但是这时候又来了一大批奇怪的请求,服务器怎么回应,这些请求源都不响应,且这些请求量也很大,故而服务器将其扔到了另一个队列(队列上限8192);
- net.core.somaxconn = 8192
- net.ipv4.tcp_max_syn_backlog = 8192
- listen 80 default backlog = 8192
- 为了防止这些垃圾请求过于占用资源,服务器规定回应报文(ack+syn)的次数为2
- net.ipv4.tcp_synack_retries = 2
到目前为止,三次握手已经走了一半,继续路程~
内核参数优化之2-1 tcp/ip 标志位报文解析,布布扣,bubuko.com
原文:http://www.cnblogs.com/aaa103439/p/3863848.html