言成言成啊 | Kit Chen's Blog

TCP有限状态机以及CLOSE_WAIT问题排查<未完成>

发布于2024-07-27 00:54:44,更新于2025-01-06 23:14:36,标签:java tcp  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

生产环境中有个网关,也就是HTTP反向代理,运行一段时间,在Linux服务器中就会出现大量CLOSE_WAIT连接一直不释放,直到把整个服务连接占满,导致程序假死——进程存在,但不能正常工作。

由于代码不是我写的,并且我也只负责生产环境运维。因此,从运维角度、不影响实际业务的情况下,最快解决该问题——实现了个程序保活脚本。

事后总结,我有点TCP常识,能独立发现问题根源,但是对于TCP的状态扭转,掌握的却很稀松,因此特地学习了下。

以下几个方面展开

  1. 理解TCP
    1. 抓包工具
    2. TCP有限状态机
  2. CLOSE_WAIT复现
    1. TCP
    2. HTTP

一、理解TCP

1.1 抓包工具

常见抓包工具

工具平台适用场景开源/免费
WiresharkWindows/MacOS全协议是/是
FiddlerEverywhereWindows/MacOS/LinuxHTTP/HTTPS否/否
CharlesWindows/MacOS/LinuxHTTP/HTTPS否/否
tcpdumpWindows/MacOS/Linux全协议是/是

从黑客角度,当我们需要逆向分析一些HTTPS流量时,使用Fiddler或者Charles即可,这两款软件,虽然是付费的,但功能特别强大,适合逆向。

话说,我当时上学时,安装根证书,逆向今日校园APP时,使用的就是IOS上的Charles,并且还买了正版。

当时一开始使用的是使用Android的HTTPCanary;还有Windows的Fiddler,可以监听Android的流量,进而实现Android抓包。

但是随着APP的升级,HTTPS的流量不再被捕获到了,这其实是证书问题,可以解决,但需要花费更多的精力。

但是Charles不同,开箱即用,主打一个无脑。

这是年轻时一件趣事,有兴趣可以查阅今日校园实现自动监测并提交最新表单 - 言成言成啊

从开发者角度,当我们需要正向分析一些TCP/UPD流量时,使用Wireshark或者tcpdump即可,比较通用,而且免费。

1.1.1 Wireshark

安装与使用

1.) 下载Wireshark,建议下载portable版本。

2.) Wireshark默认两点配置,个人感觉不太友好。需要进行以下配置

  1. 抓包TCP时,序列号seq是相对于捕获点开始的,是相对序列号,通过配置将其改为绝对序列号。
    • 步骤:编辑-首选项-Protocols-TCP-Relative sequence numbers
  2. 抓包时间点,也是相对于捕获点开始的,是相对时间点。通过配置可以改为实际时间点。
    • 步骤:视图-时间显示格式-日期和时间

3.) 打开Wireshark,会发现有多个网络适配器,也就是网卡。根据你的需求,监听对应的网卡即可。

4.) 新增过滤器,用于过滤网络请求。

比如我要监听与某个IP的SSL请求,那么过滤器表达式为ssl && ip.addr == 49.233.46.128

比如我要监听DNS域名解析请求,那么过滤器表达式为tcp.port == 53 || udp.port == 53

比如我要监听时钟服务同步请求,那么过滤器表达式为tcp.port == 123 || udp.port == 123

5.) 借助浏览器提供的会话密钥,抓HTTPS明文包。我们会发现如果是Chrome进行抓包的话,即便是HTTPS,也不会乱码。那么Wireshark是否可以像Chrome一样展示明文呢?当然也是可以的。

首先,管理员模式关闭掉所有chrome进程

1
taskkill /f /im "chrome.exe"

其次,设置Chrome启动时,生成sslkey日志

1
"C:\Program Files\Google\Chrome\Application\chrome.exe" --ssl-key-log-file=D:\Desktop\sslkey

之后,Wireshark打开编辑-首选项-Protocols-TLS,指定Master-Secret log filename为Chrome生成的日志文件。

再之后,重启Chrome和Wireshark,浏览器发起请求,Wireshark进行抓包,可以发现已经是明文了。

这个做法,只能解析通过Chrome发出的HTTPS请求。因为他依赖于Chrome生成的TLS会话密钥。

如果像Postman或者curl直接调用,是不行的。无法解析出明文。

参考致谢

我云了,原来wireshark可以抓HTTPS明文包 | MonkeyWie’s Blog

Wireshark抓包分析HTTPS协议_哔哩哔哩_bilibili

Chrome not Firefox are not dumping to SSLKEYLOGFILE variable - Stack Overflow

1.1.2 tcpdump

安装与使用

命令一把梭

1
2
3
4
5
6
7
8
# 安装tcpdump工具
yum -y install tcpdump
# 查看已有网卡
ip addr
# 监听ens33网卡的流量
tcpdump -i ens33
# 监听ens33网卡的8080端口的tcp流量
tcpdump -i ens33 tcp port 8080

官方手册

1.2 TCP

1.2.1 抓包日志说明

以tcpdump抓包日志为例。格式如下

更详细的内容,也可自行查阅tcpdump的官方文档

1
src > dst: Flags [tcpflags], seq data-seqno, ack ackno, win window, urg urgent, options [opts], length len

其中,具体的含义如下

  • src > dst: src表示源地址,dst表示目的地址。
  • Flags [tcpflags]: tcpflags为简写后的TCP标志位,通过该标志位可知该报文的作用。
  • seq data-seqno: data-seqno为序列号
  • ack ackno: ackno为确认号
  • win window: window表示窗口大小,指示接收方可以缓冲的剩余字节数。
  • urg urgent: urgent为1表示该报文包含紧急数据;为0表示报文不含紧急数据。
  • length len: len表示数据负载的长度,不包括头部。

TCP标志位有如下类型

标志位简写说明
SYNSSynchronize: 初始化连接
FINFFinish: 终止连接
PSHPPush: 立即将数据推送给接收方
RSTRRest: 重置连接
URGUUrgent: 包中有紧急数据,优先处理
CWRWCongestion Window Reduced: 发送方已响应接收方的ECN标志,并较小拥塞窗口
ECEEECN Echo: 发送方告知接收方,我拥塞了
AEeAdvertisement Echo: 通常出现在使用 TCP-AO(TCP Authentication Option)协议的连接中
ACK.Acknowledgment: 确认收到数据包

1.2.2 TCP有限状态机

像教科书中的TCP有限状态机,是包含三部分的

  1. 客户端TCP状态正常变迁
  2. 服务端TCP状态正常变迁
  3. 异常变迁

但是,全部糅合在一起,就导致整体的链路特别不明晰,因此我比较喜欢将其分开来学习。不过还是放上一份相对来说比较明晰的TCP有限状态机的图片。

1.3 抓包分析

二、复现CLOSE_WAIT

2.1 TCP

2.2 HTTP

发布:2024-07-27 00:54:44
修改:2025-01-06 23:14:36
链接:https://meethigher.top/blog/2024/tcp-state/
标签:java tcp 
付款码 打赏 分享
Shift+Ctrl+1 可控制工具栏