Tcp三次握手内核流程图解

1.流程图解&流程描述

上图中不管是半连接队列还是全连接队列,都有最大长度限制,超过限制时,内核会直接丢弃,或返回 RST数据包.

2.相关的几个内核参数

开启tcp_syncookies参数逻辑:tcp_syncookies参数开启,就可以在不使用syn半连接队列的情况下建立连接

参数路径:

 cat /proc/sys/net/ipv4/tcp_syncookies 
服务端在接收到客户端的syn报文时,计算出一个值,放到syn+ack报文中发出返回给客户端。当客户端返回ack报文时携带该值,取出该值验证,成功则建立连接。

  通常见的半连接攻:

   就是大量发送syn让服务资源耗尽,从而不能提供服务,也叫DDos攻击.

   抵御大量半连接的方法如下:
1.增大半链接队列
    通过修改内核参数增大半链接队列tcp_max_syn_backlog,还需要一同增大somaconn和backlog(增大全连接队列)

   sysctl -a|grep 参数名 // 查看对应参数当前配置大小

  全连接队列长度: 其最大长度是 listen 时传入的 backlog 和 net.core.somaxconn 之间较小的那个值。如果需要加大全连接队列长度,那么就是调整 backlog 和 somaxconn。
  半链接队列长度: min(backlog,somaxconn,tcp_max_syn_backlog) + 1 向上取整到2的幂次。(最小不能小于16),另外线上遇到了半连接队列溢出的问题,想加大该队列长度,那么就需要同时考虑 somaxconn、backlog、和 tcp_max_syn_backlog 三个内核参数

2.减少服务端的syn+ack数据包的传递次数

  修改重传次数:/proc/sys/net/ipv4/tcp_synack_retries

  有个参数tcp_abort_on_overflow可以指定TCP全连接队列满了,使用什么策略来回应客户端
  参数路径: /proc/sys/net/ipv4/tcp_abort_on_over_flow

    0:如果全连接队列满了,那么服务端丢弃ack报文
    1:如果全连接队列满了,那么服务端会想客户端发送RST报文,终止这个握手连接

 注:半链接攻击跟全连接攻击,详情请见博主的“半链接攻击跟全连接攻击”介绍.

 3.三次握手出现的问题

connect时异常

客户端调用connect连接时,系统会给当前客户端分配一个端口号,端口号的分配过程内核根据参数ip_local_port_range分配一个尚未使用的端口.但是如果端口号如果使用完了,再来客户端分配度端口,是无法分配成功的。在内核中,分配端口时一个循环过程,并且内部使用了自旋锁以及哈希表搜索过程。如果端口用完了,每次来新的连接,就都会进行无用的循环+自旋锁的占用cpu时间+大量的哈希查找等时间开销,从而造成cpu的时间消耗大幅度飙升

处理方式:

可以根据实际情况,调整ip_local_port_range端口范围,避免出现端口使用完的情况发生.
尽量复用连接,使用长链接,避免过多频繁的短连接带来大量的握手从而造成cpu耗时.
    可以开启tcp_tw_reuse和tcp_tw_recycle参数,但是不建议开启。

    tcp_tw_reuse:开启该参数便可以重复利用处于 time_wait 状态的连接。实际场景中,客户端主动发起关闭连接,表示当前不再连接访问服务。如果有需要,重新连接即可。如果开启,处于状态为time_wait的连接仍旧能被使用,可能会出现未知的问题,所以不建议开启该参数。

    tcp_tw_recycle:该参数4.x 内核版本之后已经被废弃。因为这个参数功能是快速回收处于 time_wait 状态的连接,不用等2 MSL 就关闭连接。产生的影响是会拒绝所有当前客户端的时间戳更靠前的网络包,所以不要开启该参数。不然可能会发生大量服务拒绝数据包问题。


第一次握手丢包异常

       第一次握手,半连击队列满了,并且没有开启tcp_syncookies,那么服务端会直接将该握手包丢弃,此时客户端因有定时重传,会在超时后,重新发送一个握手包,同时设置下一次超时时间,如果服务端仍旧丢弃该包,那么客户端重传到一定次数后(重传的次数由于net.ipv4.tcp_syn_retries 影响,[由于重传判断逻辑比较复杂,不单单是比较次数,还有时间的比较判别,所以有时看到重传次数跟内核单数不太一致,也是正常的现象],就不再进行连接.同样全队列如果也是满了,并且有young_ack存在(尚未连接的半连接对象)也会丢弃当前的数据包。

   注:客户端在高版本的服务设置的超时时间是1s,比较老的系统设置是3s,当客户是用客户端连接服务端时,如果发生上述情况丢包,如果进行重传连接,那么此时的耗时严重影响客户使用体验.

第三次握手包丢失情况

    如果握手进行到该阶段,收到了服务端发的synack数据包,此时客户端认为连接好了,并且会将第一次发出握手包之后设置的定时重传器删除,再发出最有一次握手的ack数据包.此刻全队列满了,服务端将该ack数据包丢弃,服务端会发现定时时间内没收到ack包,则会重新发送一个synack数据包,如果全队列一直都是满的,那ack数据包会一直丢弃,一直持续到超多重传的次数才停止(重传次数由内核参数  net.ipv4.tcp_synack_retries控制)

处理方法:

    开启tcp_syncookies参数,即便半连接队列满了,仍旧可以连接。
    增大连接队列长度,调整时,根据实际需要,半连接跟全连接队列都适配的调整。可以大幅度避免发生握手异常问题.
    快速的accept,避免处理其他业务逻辑导致队列满了,通常都是连接完直接accept。
    结合实际场景,能使用长链接的使用长链接,避免因短连接过多的握手连接导致系统资源的消耗.(当然,一些非频繁的消息处理,使用短连接好,用完即释放,避免长时间占用资源)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值