Wireshark困境:为何TLS通信以RST结束?
杨胜辉

你好,我是胜辉。今天谈谈 RST 的问题。
正常来说,一个 TCP 连接,无论是通过 TLS 间接地承载 HTTP,还是直接承载 HTTP,其连接关闭的过程都应该遵照 TCP 协议,以四次挥手为结束。也就是下图这样:

不过,如果你抓取过 TLS 相关的报文,会发现有时候 TCP 连接的关闭不是以图上的 FIN,而是以 RST 报文结束的。RST 一般意味着 TCP 关闭过程有错误。然而,当你真的去检查应用层事务的具体情况时,又可能会发现其实这些事务都正常完成了。但是,应用程序日志里却记录了连接异常中断之类的报错。
那这种 RST 引起的错误,到底应该是报啊,还是报啊,还是报啊?(郭德纲附体)
有一次我们也遇到类似的情况。应用开发团队说,他们的应用经常会遇到 connection was closed prematurely 这样的报错:
HTTPTransportException: Transport outbound I/O exception in xxxServiceV1: java.util.concurrent.ExecutionException: java.io.IOException:connection was closed prematurely, at service location:xxx
公开
同步至部落
取消
完成
0/2000
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结

1. TLS通信中出现RST报文可能导致应用程序记录异常中断报错,但实际应用层事务可能正常完成。 2. Wireshark抓包分析发现TCP连接关闭时出现RST报文和Encrypted Alert(18号报文),需要进一步分析TLS通信。 3. 解密后发现Encrypted Alert其实是TLS close_notify消息,根据RFC5246定义,TLS通信结束需要显式发送close_notify,但实际情况中存在多种不规范的关闭形式。 4. 不规范的TLS通信关闭形式可能导致TCP挥手过程异常,如服务端连续发送TLS close_notify和TCP FIN报文,导致客户端无法完成双向的TLS关闭。 5. Wireshark分析在发现不合理行为时可能无法进一步推导原因,这种困境称为"Wireshark困境",需要从应用程序和内核逻辑角度进行分析。 6. 应用程序无法直接操纵TCP报文的元信息,包括TCP报文的flag、确认号、序列号等在内的TCP元信息,都是由内核管控的。 7. 在Linux内核中,产生RST报文的逻辑涉及两个函数:tcp_send_active_reset()和tcp_v4_send_reset(),分别用于主动发送RST和被动式发送RST。 8. 内核通过异常报文或特定状态组合来触发RST报文,而不是由应用程序直接操控。 9. 数据没有被读取的并不是应用层HTTP的数据,而只是表示层的TLS close_notify消息,所以对应用事务的完整性并没有产生任何影响。 10. 在分析网络问题时,形成猜想然后去证实这个猜想会更加高效。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络排查案例课》,新⼈⾸单¥59
《网络排查案例课》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
精选留言
由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论

