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的状态扭转,掌握的却很稀松,因此特地学习了下。
以下几个方面展开
- 理解TCP
- 抓包工具
- TCP有限状态机
- CLOSE_WAIT复现
- TCP
- HTTP
一、理解TCP
1.1 抓包工具
常见抓包工具
工具 | 平台 | 适用场景 | 开源/免费 |
---|---|---|---|
Wireshark | Windows/MacOS | 全协议 | 是/是 |
FiddlerEverywhere | Windows/MacOS/Linux | HTTP/HTTPS | 否/否 |
Charles | Windows/MacOS/Linux | HTTP/HTTPS | 否/否 |
tcpdump | Windows/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默认两点配置,个人感觉不太友好。需要进行以下配置
- 抓包TCP时,序列号seq是相对于捕获点开始的,是相对序列号,通过配置将其改为绝对序列号。
- 步骤:
编辑-首选项-Protocols-TCP-Relative sequence numbers
- 步骤:
- 抓包时间点,也是相对于捕获点开始的,是相对时间点。通过配置可以改为实际时间点。
- 步骤:
视图-时间显示格式-日期和时间
- 步骤:
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 | # 安装tcpdump工具 |
官方手册
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标志位有如下类型
标志位 | 简写 | 说明 |
---|---|---|
SYN | S | Synchronize: 初始化连接 |
FIN | F | Finish: 终止连接 |
PSH | P | Push: 立即将数据推送给接收方 |
RST | R | Rest: 重置连接 |
URG | U | Urgent: 包中有紧急数据,优先处理 |
CWR | W | Congestion Window Reduced: 发送方已响应接收方的ECN标志,并较小拥塞窗口 |
ECE | E | ECN Echo: 发送方告知接收方,我拥塞了 |
AE | e | Advertisement Echo: 通常出现在使用 TCP-AO(TCP Authentication Option)协议的连接中 |
ACK | . | Acknowledgment: 确认收到数据包 |
1.2.2 TCP有限状态机
像教科书中的TCP有限状态机,是包含三部分的
- 客户端TCP状态正常变迁
- 服务端TCP状态正常变迁
- 异常变迁
但是,全部糅合在一起,就导致整体的链路特别不明晰,因此我比较喜欢将其分开来学习。不过还是放上一份相对来说比较明晰的TCP有限状态机的图片。