TCP面试:SYN报文在什么情况下会被丢弃

概括来说有两个方面的原因

1.TCP两个队列满了(半链接和全链接队列),造成SYN报文被丢弃

2.开启了tcp_tw_recylce调优参数,并且在NAT环境下,造成了SYN报文丢弃

原因一分析

回忆一下三次握手:

1.服务端收到客户端发起的SYN请求后,内核会把该链接存储到半链接队列,并向客户端响应SYN+ACK。

2.接着客户端返回ACK, 服务端收到第三次握手的ACK后,内核会把链接从半链接队列移除

3.然后创建新的完全的链接,并将其添加到aceept队列(全链接队列),等待进程调用accept 函数时把链接取出来。

如果大量的syn数据包同时到达服务端,导致半连接队列瞬间被打满,多余的SYN就丢弃了(DDOS攻击),怎么解决?

(1)增大半链接队列

         tcp_max_syn_backlog和backlog somaxconn,同时增大全链接队列

(2)开启tcp_syncookies

         服务器更具当前状态计算出一个值, 放在服务端发送给客户端的SYN+ACK中发出,当客户端返回ACK报文时,取出该值验证,如果合法,认为该链接建立成功

0:关闭该功能;1:SYN半链接装不下开启;2:无脑开启

(3)减少SYN+ACK重传次数

        当服务端收到SYN攻击时候,会有大量处于SYN_RECV状态的TCP链接,处于这个状态的TCP会重传SYN+ACK,当重传次数达到上限后,就会断开链接,那么针对SYN攻击的场景,我们可以减少SYN+ACK的重传次数,以加快SYN_RECV状态的TCP断开,默认为5,可以减少到1

在服务端并发处理大量请求时候,如果TCP accept队列太小,或者应用程序调用accept 不及时,就会造成accept队列满了,这时候或许的链接就会被丢弃,这样就会挤占半链接队列,这样就会丢弃syn包,如何解决?

(1)调大backlog以及somaxconn参数

(2)检查系统或者代码是不是调用accept不及时

原因二分析 

为什么会有tcp_tw_recycle参数

1.TCP 第四次挥手中,主动断开方会有一个TIME_WAIT状态,这个状态会持续2MSL后才会转变为CLOSED状态

2.主断开链接方= 客户端 + 大量主动断开链接,导致大后面客户端没有端口可以用

tcp要解决,当真的没有端口使用的时候,客户端还要想建立连接该怎么办,所以诞生了tcp_tw_recycle

3.tcp_tw_recycle,如果开启,允许time_wait状态被快速回收;tcp_tw_refuse,如果开启,客户端在调用connect,如果内核选择的端口已经被相同四元组的连接占用的时候,会判断该连接是否处于time_wait状态,如果处于Time_wait并且持续时间超过1s,那么就会重用这个连接,然后就可以正常使用这个端口了

上述两个参数使用前提,必须打开时间戳即net.ipv4.tcp_timestamp = 1

4.开启了recycle和timestamps选项,就开启了PAWS机制(防止了TCP包中的序列号发生绕回)

什么是PAWS机制?

之前说过,开启了 recycle 和 timestamps 选项,就会开启一种叫 per-host 的 PAWS 机制。per-host 是对「对端 IP 做 PAWS 检查」,而非对「IP + 端口」四元组做 PAWS 检查

正常来说每个 TCP 包都会有自己唯一的 SEQ,出现 TCP 数据包重传的时候会复用 SEQ 号,这样接收方能通过 SEQ 号来判断数据包的唯一性,也能在重复收到某个数据包的时候判断数据是不是重传的。但是 TCP 这个 SEQ 号是有限的,一共 32 bit,SEQ 开始是递增,溢出之后从 0 开始再次依次递增

所以当 SEQ 号出现溢出后单纯通过 SEQ 号无法标识数据包的唯一性,某个数据包延迟或因重发而延迟时可能导致连接传递的数据被破坏,比如

上图 A 数据包出现了重传,并在 SEQ 号耗尽再次从 A 递增时,第一次发的 A 数据包延迟到达了 Server,这种情况下如果没有别的机制来保证,Server 会认为延迟到达的 A 数据包是正确的而接收,反而是将正常的第三次发的 SEQ 为 A 的数据包丢弃,造成数据传输错误。

PAWS 就是为了避免这个问题而产生的,在开启 tcp_timestamps 选项情况下,一台机器发的所有 TCP 包都会带上发送时的时间戳,PAWS 要求连接双方维护最近一次收到的数据包的时间戳(Recent TSval),每收到一个新数据包都会读取数据包中的时间戳值跟 Recent TSval 值做比较,如果发现收到的数据包中时间戳不是递增的,则表示该数据包是过期的,就会直接丢弃这个数据包

对于上面图中的例子有了 PAWS 机制就能做到在收到 Delay 到达的 A 号数据包时,识别出它是个过期的数据包而将其丢掉。

最终原因 tcp_tw_recycle 在使用了 NAT 的网络下是不安全的!

 

1.经过同一个 NAT转换后的来自不同真实client数据流,在服务端看起来是和同一个Host打交道

a.客户端网络环境是用了NAT网关,那么客户端的每一台机器经过NAT网关之后,都会是相同的IP地址,服务器无法区别出来

2.虽然经过同一NAT转化,但不同的client会携带各自的timestamp值,因此无法保证经过NAT转化后的数据包携带的timestamp值严格递增

3.当服务器的per-host PAWS机制被触发后,会丢弃timestamp值不符合递增条件的数据包  

举例:当客户端 A 通过 NAT 网关和服务器建立 TCP 连接,然后服务器主动关闭并且快速回收 TIME-WAIT 状态的连接后,客户端 B 也通过 NAT 网关和服务器建立 TCP 连接,注意客户端 A 和 客户端 B 因为经过相同的 NAT 网关,所以是用相同的 IP 地址与服务端建立 TCP 连接,如果客户端 B 的 timestamp 比 客户端 A 的 timestamp 小,那么由于服务端的 per-host 的 PAWS 机制的作用,服务端就会丢弃客户端主机 B 发来的 SYN 包

因此,tcp_tw_recycle 在使用了 NAT 的网络下是存在问题的,如果它是对 TCP 四元组做 PAWS 检查,而不是对「相同的 IP 做 PAWS 检查」,那么就不会存在这个问题了。

 

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值