队列及参数

 
tcp-sync-queue-and-accept-queue-small.jpg

server端的半连接队列(syn队列)

在三次握手协议中,服务器维护一个半连接队列,该队列为每个客户端的SYN包开设一个条目(服务端在接收到SYN包的时候,就已经创建了request_sock结构,存储在半连接队列中),该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包(会进行第二次握手发送SYN+ACK 的包加以确认)。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。
该队列为SYN 队列,长度为 max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog) ,在机器的tcp_max_syn_backlog值在/proc/sys/net/ipv4/tcp_max_syn_backlog下配置。

server端的完全连接队列(accpet队列)

当第三次握手时,当server接收到ACK 报之后, 会进入一个新的叫 accept 的队列,该队列的长度为 min(backlog, somaxconn),默认情况下,somaxconn 的值为 128,表示最多有 129 的 ESTAB 的连接等待 accept(),而 backlog 的值则应该是由 int listen(int sockfd, int backlog) 中的第二个参数指定,listen 里面的 backlog 可以有我们的应用程序去定义的。

当Client发送SYN包之后挂了(syn flood攻击)

Client发送SYN包给Server后挂了,Server回给Client的SYN-ACK一直没收到Client的ACK确认,这个时候这个连接既没建立起来,也不能算失败。这就需要一个超时时间让Server将这个连接断开,否则这个连接就会一直占用Server的SYN连接队列中的一个位置,大量这样的连接就会将Server的SYN连接队列耗尽,让正常的连接无法得到处理。

目前,Linux下默认会进行5次重发SYN-ACK包,重试的间隔时间从1s开始,下次的重试间隔时间是前一次的双倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s,TCP才会把断开这个连接。由于,SYN超时需要63秒,那么就给攻击者一个攻击服务器的机会,攻击者在短时间内发送大量的SYN包给Server(俗称 SYN flood 攻击),用于耗尽Server的SYN队列。对于应对SYN 过多的问题,linux提供了几个TCP参数:tcp_syncookies、tcp_synack_retries、tcp_max_syn_backlog、tcp_abort_on_overflow 来调整应对。

net.ipv4.tcp_synack_retries #内核放弃连接之前发送SYN+ACK包的数量
net.ipv4.tcp_syn_retries #内核放弃建立连接之前发送SYN包的数量

为了应对SYNflooding(即客户端只发送SYN包发起握手而不回应ACK完成连接建立,填满server端的半连接队列,让它无法处理正常的握手请求),Linux实现了一种称为SYNcookie的机制,通过net.ipv4.tcp_syncookies控制,设置为1表示开启。简单说SYNcookie就是将连接信息编码在ISN(initialsequencenumber)中返回给客户端,这时server不需要将半连接保存在队列中,而是利用客户端随后发来的ACK带回的ISN还原连接信息,以完成连接的建立,避免了半连接队列被攻击SYN包填满。

当syn队列满的情况(tcp_abort_on_overflow)

对于SYN半连接队列的大小是由(/proc/sys/net/ipv4/tcp_max_syn_backlog)这个内核参数控制的,有些内核似乎也受listen的backlog参数影响,取得是两个值的最小值。当这个队列满了,不开启syncookies的时候,Server会丢弃新来的SYN包,而Client端在多次重发SYN包得不到响应而返回(connection time out)错误。但是,当Server端开启了syncookies=1,那么SYN半连接队列就没有逻辑上的最大值了,并且/proc/sys/net/ipv4/tcp_max_syn_backlog设置的值也会被忽略。

Client端在多次重发SYN包得不到响应而返回connection time out错误

查看

netstat -s | grep LISTEN
4375 SYNs to LISTEN sockets dropped

当accept队列满的情况

当accept队列满了之后,即使client继续向server发送ACK的包,也会不被响应,此时ListenOverflows+1,同时server通过/proc/sys/net/ipv4/tcp_abort_on_overflow来决定如何返回,0表示直接丢弃该ACK,1表示发送RST通知client;相应的,client则会分别返回read timeout 或者 connection reset by peer

client则会分别返回read timeout 或者 connection reset by peer

查看

root@b5dbe93bcb04:/opt# netstat -s | grep listen
22438 times the listen queue of a socket overflowed

accept队列满了,对 syn队列也有影响,在代码 net/ipv4/tcp_ipv4.c :

int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
/*tcp_syncookies为2 进行syn cookie
tcp_syncookies为1 且request队列满了 进行syn cookie处理
tcp_syncookies为0 且request队列满了 将该syn报文drop掉
*/
if ((sysctl_tcp_syncookies == 2 ||
inet_csk_reqsk_queue_is_full(sk)) && !isn) {
want_cookie = tcp_syn_flood_action(sk, skb, "TCP");
if (!want_cookie)
goto drop;
} /* Accept backlog is full. If we have already queued enough
* of warm entries in syn queue, drop request.
*/
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
goto drop;
}

accept队列大多数情况下会比较小,所以会出现SYN 队列没有满,而ACCEPT 队列满了的情况,此时会按照tcp_aborton_overflow来决定直接丢弃,还是返回拒绝RST。 而如果启用了syncookies,那么syncookies会开启,限制SYN包进入的速度。

当系统丢弃最后的 ACK,而系统中还有一个 net.ipv4.tcp_synack_retries 设置时,Linux 会重新发送 SYN ACK 包。而客户端收到多个 SYN ACK 包,则会认为之前的 ACK 丢包了。于是促使客户端再次发送 ACK ,在 accept队列有空闲的时候最终完成连接。若 accept队列始终满员,则最终客户端收到 RST 包。

作者:go4it
链接:https://www.jianshu.com/p/ff26312e67a9
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

另外贴一个地址https://blog.csdn.net/ptonlix/article/details/76528206

(转)tcp的半连接与完全连接队列的更多相关文章

  1. tcp的半连接与完全连接队列

    队列及参数 https://segmentfault.com/a/1190000008224853 server端的半连接队列(syn队列) 在三次握手协议中,服务器维护一个半连接队列,该队列为每个客 ...

  2. tcp的半连接与完全连接队列(二)

    队列及参数 server端的半连接队列(syn队列) 在三次握手协议中,服务器维护一个半连接队列,该队列为每个客户端的SYN包开设一个条目(服务端在接收到SYN包的时候,就已经创建了request_s ...

  3. tcp的半连接与完全连接队列(三)源码分析

    TCP 协议中的 SYN queue 和 accept queue 处理 若要理解本文意图说明的问题,可能需要以下知识背景: listen 系统调用的 backlog 参数含义,以及与 net.cor ...

  4. 【转】关于TCP 半连接队列和全连接队列

    摘要: # 关于TCP 半连接队列和全连接队列 > 最近碰到一个client端连接异常问题,然后定位分析并查阅各种资料文章,对TCP连接队列有个深入的理解 > > 查资料过程中发现没 ...

  5. 关于TCP 半连接队列和全连接队列

    关于TCP 半连接队列和全连接队列 http://jm.taobao.org/2017/05/25/525-1/ 发表于 2017-05-25   |   作者   蛰剑     |   分类于 网络 ...

  6. TCP 半连接队列和全连接队列满了会发生什么?又该如何应对?

    前言 网上许多博客针对增大 TCP 半连接队列和全连接队列的方式如下: 增大 TCP 半连接队列的方式是增大 /proc/sys/net/ipv4/tcp_max_syn_backlog: 增大 TC ...

  7. TCP实战二(半连接队列、全连接队列)

    TCP实验一我们利用了tcpdump以及Wireshark对TCP三次握手.四次挥手.流量控制做了深入的分析,今天就让我们一同深入理解TCP三次握手中两个重要的结构:半连接队列.全连接队列. 参考文献 ...

  8. 三次握手 四次握手 原因分析 TCP 半连接队列 全连接队列

    小结 1. 三次握手的原因:保证双方收和发消息功能正常: [生活模型] "请问能听见吗""我能听见你的声音,你能听见我的声音吗" [原理]A先对B:你在么?我在 ...

  9. TCP全连接队列和半连接队列已满之后的连接建立过程抓包分析[转]

    最近项目需要做单机100万长连接与高并发的服务器,我们开发完服务器以后,通过自己搭的高速压测框架压测服务端的时候,发生了奇怪的现象,就是服务端莫名其妙的少接收了连接,造成了数据包的丢失,通过网上查资料 ...

随机推荐

  1. 关于JS闭包

    今天在敲代码的时候,发现很多JQ插件在写闭包的时候都会用到下面的写法: (function ($) { ... })(jQuery); 一时的好奇心驱使,我研究起了这一写法来.大家都知道,在 $ 没有 ...

  2. 【c++】类管理指针成员

    c++编程提倡使用标准库,一个原因是标准库大胆减少对指针的使用.但是许多程序是离不开指针的.包含指针的类需要特别注意复制控制,原因是复制指针时只复制指针中的地址,而不复制指针所指向的对象.这样当把一个 ...

  3. HDU 5700——区间交——————【线段树+枚举】

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  4. Android和kernel杂散点集合

    Android: 1.编译 普通的编译: 1). source build/envsetup.sh 2).lunch 3).make -jx make kernel:只重新编译kernel部分镜像,但 ...

  5. [转]让ASP.NET Web API支持$format参数的方法

    本文转自:http://www.cnblogs.com/liuzhendong/p/4228592.html 在不使用OData的情况下,也可以让ASP.NET Web API支持$format参数, ...

  6. 提交代码至coding.net

    1.首先在本地任意目录下创建项目 2.cmd切换至该目录下,然后依次输入: git init git add . git commit -m "version 3.9" git r ...

  7. hdu 4628 Pieces 状态压缩dp

    Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total S ...

  8. hdu 3466 Proud Merchants 01背包变形

    Proud Merchants Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) ...

  9. hdu 1561 树形背包 选k个最大价值

    http://blog.csdn.net/dellaserss/article/details/8799730 这题其实和上一题思路是一样的,一个0节点作为根节点,通过剩余量来遍历子树. #inclu ...

  10. 微信小程序,动态改变样式

    小程序目前没有修改样式api,但是可以利用数据绑定实现动态改变样式,可以用view标签模拟page然后改变view标签的样式,以下案例演示了如果改变page背景颜色: <view class=& ...