动图图解!收到RST,就一定会断开TCP连接吗?( 四 )


 
已连接状态下收到第一次握手包会怎么样?我们需要了解一个问题,比如服务端在已连接(ESTABLISHED)状态下,如果收到客户端发来的第一次握手包(SYN),会怎么样?
以前我以为服务单会认为客户端憨憨了,直接RST连接 。
但实际,并不是 。
static bool tcp_validate_incoming(){struct tcp_sock *tp = tcp_sk(sk);/* 判断seq是否在合法窗口内 */if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {if (!th->rst) {// 收到一个不在合法窗口内的SYN包if (th->syn)goto syn_challenge;}}/** RFC 5691 4.2 : 发送 challenge ack*/if (th->syn) {syn_challenge:tcp_send_challenge_ack(sk);}}当客户端发出一个不在合法窗口内的SYN包的时候,服务端会发一个带有正确的seq数据ACK包出来,这个ACK包叫 challenge ack 。

动图图解!收到RST,就一定会断开TCP连接吗?

文章插图
 
challenge ack抓包
上图是抓包的结果,用scapy随便伪造一个seq=5的包发到服务端(端口9090),服务端回复一个带有正确seq值的challenge ack包给客户端(端口8888) 。
 
利用challenge ack获取seq上面提到的这个challenge ack,仿佛为盲猜seq的老哥们打开了一个新世界 。
在获得这个challenge ack后,攻击程序就可以以ack值为基础,在一定范围内设置seq,这样造成RST攻击的几率就大大增加了 。
动图图解!收到RST,就一定会断开TCP连接吗?

文章插图
 
利用ChallengeACK的RST攻击
 
总结
  • RST其实是TCP包头里的一个标志位,目的是为了在异常情况下关闭连接 。
  • 内核收到RST后,应用层只能通过调用读/写操作来感知,此时会对应获得 Connection reset by peer 和Broken pipe 报错 。
  • 发出RST后不需要得到对方的ACK确认包,因此RST丢失后对方不能立刻感知,但是通过下一次重传数据或keepalive心跳包可以导致RST重传 。
  • 收到RST包,不一定会断开连接,seq不在合法窗口范围内的数据包会被默默丢弃 。通过构造合法窗口范围内seq,可以造成RST攻击,这一点大家了解就好,千万别学!
来源:
https://mp.weixin.qq.com/s/Fr6o6gRiIUIspV9-jR9snw




推荐阅读