资讯详情

资讯详情

iOS 网络抓包实战:从 TCP/UDP 到 HTTPS 解密与问题排查

经常有人在群里问iOS 端网络出问题能不能像服务端那样直接 tcpdump 一把梭问的人多了我发现大家真正想要的是——在整个 iOS App 的开发调试和线上问题排查里有一套能拿到 TCP、UDP 数据包、并能看懂数据的完整方法。说实话这件事在 iOS 上比在安卓和 Linux 上麻烦不少但它又是联调、定位弱网问题、排查服务端“甩锅”时最硬核的证据。这篇文章就把我这几年在 iOS App 上做数据包抓取的实操经验整理出来适合所有做 iOS 原生开发、又得和网络问题死磕的工程师。先泼一盆冷水iOS 不是 Linux你不能随手开个 root shell 在设备上跑 tcpdump也不能像安卓那样拿个抓包软件就能看到所有 UDP。但也不是完全没辙。通过 Mac 端的虚拟网卡、系统自带的网络诊断日志再配合 Wireshark 这一层的分析工具TCP 和 UDP 的包都能完整拿到。这篇文章不会只给你几条命令我会把“为什么这样抓”“抓到之后怎么看”“遇到 HTTPS 怎么办”“线上偶发超时怎么定位”这几个问题串起来尽量让你少走弯路。1. 先厘清需求iOS 抓 TCP/UDP 包到底在什么场景下才是必要动作1.1 哪些问题非抓包不可先说个常见的尴尬场景后端说“我这边日志显示请求根本没到”客户端同事说“我明明发了请求”两边都觉得自己没错。这种纠纷如果不看网络层的真实数据基本靠猜。而抓包的意义就在于把双方“认为发生了什么”替换成“网络里实际发生了什么”。比如 TCP 三次握手是否完成、SYN 发出后有没有回 ACK、请求体是在哪个分片丢的、UDP 包是不是发出去就石沉大海——这些信息业务日志里不会写SDK 的报错回调也不一定准。我归纳了一下真正值得抓包的场景大概有三类联调排错接口通了但结果不对或者时通时不通需要区分是客户端没发出去、中间链路丢了、还是服务端没回。这类问题抓 TCP 最有效。弱网和音视频体验问题直播、语音、实时数据同步这类场景UDP 是主力。用户反馈“卡顿”“断字”“不同步”的时候业务层很难说清楚是丢包、乱序还是抖动。只有抓到原始报文用应用层序号和时间戳推算才能定位。安全和隐私自查App 里到底有没有偷偷发明文证书校验到底有没有生效哪些域名走了 IPv6这类问题不抓包光看代码容易漏。新手容易犯的错是一拿到工具就开抓然后被成百上千条包淹没。所以动手之前先想清楚你是要确认“连不连得上”还是要分析“报文内容对不对”还是要判断“网络质量差在哪”。目标不同抓包的位置、过滤条件和分析方式完全不一样。1.2 TCP 和 UDP 在排查思路上是两码事这一点我每次带人的时候都会反复强调TCP 和 UDP 的抓包分析思维方式根本不同。TCP 是面向连接的可靠流协议。它自带序号Sequence Number、确认号Acknowledgment Number、状态标志SYN/ACK/FIN/RST。所以你看 TCP 包本质上是在看一台状态机三次握手建立连接、数据传输、四次挥手关闭连接每一步都有明确的报文。包丢了会有重传包序错了会有乱序提示对端没收到会有重复 ACK。你可以非常清晰地得到结论这次连接到底建没建成卡在哪个阶段谁先发的 RST。UDP 就不一样了。它没有连接概念没有确认机制也不保证顺序。你抓到的就是一个个独立的数据报网络层能告诉你的只有源地址、目的地址、源端口、目的端口、包长度和时间戳。丢没丢包、乱没乱序协议层一概不知。这时候就得借助应用层的信息很多 UDP 协议会在 payload 里放递增序号、时间戳、帧标记你要靠这些字段推算丢包率和抖动。还有个容易被忽略的点TCP 的抓包分析可以精确到“字节的可靠性”UDP 只能精确到“报文的存在性”。所以用 UDP 做核心业务的时候应用层必须自己设计序号和确认机制否则出了问题连从哪查起都不知道。1.3 iOS 平台的特殊约束在 iOS 上抓包你还要先接受三件事。第一设备侧权限有限。非越狱环境拿不到 root不能在 iPhone 本机直接监听所有网卡流量。最实用的办法是把流量引导到 Mac 上再抓后面会详细讲。第二系统层 TLS 保护越来越严。从 iOS 10.3 开始安装的根证书默认不被完全信任必须到“设置 → 通用 → 关于本机 → 证书信任设置”里手动开启。如果 App 再做证书固定SSL Pinning中间人解密这条路基本就断了只能靠代码层日志。第三现在的网络是 IPv4/IPv6 双栈。你可能只关注了域名和端口但实际流量可能走了 IPv6过滤条件没写对就会漏掉一半包。我见过不少同事在 Wireshark 里只写tcp.port 443结果 IPv6 的流量一条都显示不出来白白折腾半天。2. 工具选型的真实边界从 Wireshark 到 Xcode 自带诊断怎么组合不折腾2.1 三层抓包方案设备侧、链路侧、协议侧我习惯把 iOS 抓包方案分成三层按需选择链路侧在 Mac 上用 Wireshark/tcpdump 捕获网卡流量。覆盖面最广能看到设备离开 App 之后的所有真实网络行为。适合定位 TCP 连接问题、MTU 问题、DNS 解析问题。设备侧通过 Xcode 的 Network 调试能力或 Charles 这类工具在 App 进程附近做流量中转与解密。适合看 HTTP/HTTPS 请求内容、请求头、Cookie、接口响应。协议侧在 App 代码里用 URLSession 的 taskMetrics、Network.framework 的 NWConnection 状态回调把自己关心的网络指标打点输出。适合线上问题、难以复现的问题、以及加了证书固定的 App。实际项目中这三层要配合用。比如你要定位一个 HTTPS 接口偶发超时先用设备侧确认请求内容没问题再用链路侧确认 TCP 握手、TLS 协商、数据传输在哪一步断了。单靠一层经常会得出片面的结论。2.2 可视化工具擅长与不擅长的部分很多人一上来就问Wireshark 和 Charles 到底选哪个这其实是在问两个不同维度的问题。Wireshark是协议分析工具它的主场是 TCP/IP 协议栈。它能把一条 TCP 流从头到尾重组出来标出重传、乱序、重复 ACK、零窗口还能分析 TLS 握手细节和 DNS 响应时间。但不擅长做 HTTPS 内容的“人话”展示解密需要额外配置证书而且配置失败率其实挺高。Charles是英文开发调试工具它的主场是 HTTP/HTTPS 的请求响应。装好证书后你能直接看到某个接口的 URL、Header、Body、响应码还能断点修改请求。但它的底子是 TCP 之上的 HTTP 解析UDP 流量基本看不见底层 TCP 重传、丢包这类信息也完全无能为力。所以我的习惯是看业务内容用 Charles看网络行为用 Wireshark。如果你只对“接口返回了什么”感兴趣Charles 就够了如果你要解决“网络为什么慢、为什么断”请打开 Wireshark。顺便说一句服务端老同事最爱的 tcpdump 在 iOS 开发里也不是没用只是跑在 Mac 上。它轻量、无界面、适合在终端里快速抓一小段 pcap 文件再丢给 Wireshark 分析。后面讲 RVIT 的时候会用到。2.3 用 USB 虚拟网卡捕获完整 iOS 流量RVIT这是我这几年用下来最顺手的方案也是 iOS 官方支持的做法——通过 USB 让 Mac 生成一个虚拟网卡把 iPhone 的流量在 Mac 上完整镜像出来。苹果自带工具叫 Remote Virtual Interface命令行工具是rvictl。具体步骤很简单准备好 iPhone 和 Mac用数据线连接。在 Mac 上打开终端确认设备已被识别用xcrun xctrace list devices查看设备 UDID。执行sudo rvictl -s UDID这时候系统会创建一个名为rvi0或rvi1等的虚拟网卡。打开 Wireshark选择rvi0接口开始抓包或者用sudo tcpdump -i rvi0 -s 0 -w ios.pcap先存文件。用完执行sudo rvictl -x UDID删除虚拟接口。这个方案的优点非常明显第一不需要手机越狱不需要装任何插件第二抓到的流量是设备真实的网络栈输出包含 TCP、UDP、ICMP、DNS 等所有报文而不仅仅是 HTTP 层第三手机走的 Wi-Fi 或蜂窝流量都会经过这个虚拟网卡观察面很全。要注意的是抓包期间设备要保持 USB 连接并且信任这台 Mac。另外rvi0上抓到的流量并不包含所有系统内部通信但对 App 自身发起的网络请求来说完整度已经足够日常排查了。3. 实操演示从零抓住第一条 TCP 流和 UDP 包3.1 配好过滤条件避免被噪声淹没拿到rvi0接口之后第一件事不是点开始而是先把过滤条件想清楚。我见过太多人打开 Wireshark 就抓三秒钟抓了几万条包然后完全不知道从哪里看起。我的习惯是这样先确定要分析的目标 App 的服务端域名或端口然后在抓包工具里只保留和它相关的流量。Wireshark 的过滤语法很简单比如ip.addr 192.168.1.100 tcp——只看该 IP 的 TCP 包。tcp.port 443——只看 443 端口。udp.port 8000——只看某 UDP 端口的包。也可以用域名过滤dns.qry.name contains example.com先找到实际解析出的 IP再切回 IP 过滤。不要一上来就用tcp或者直接不填过滤条件。Wi-Fi 环境下会混入大量局域网广播、其他设备的流量过滤得当能让你少看 90% 的噪声。另外抓包文件的命名也建议规范。我一般按“日期-场景-方向”来命名比如20250112_upload_timeout.pcapng。排查线上问题时一般要抓好几轮命名不清后面根本对不上号。3.2 TCP 连接过程怎么看三次握手、重传、乱序现在假设你已经抓到了一条完整的 TCP 流。打开 Wireshark找到第一条SYN包看整个连接的过程。正常情况下你会看到192.168.1.5 - 203.0.113.10 TCP SYN 203.0.113.10 - 192.168.1.5 TCP SYNACK 192.168.1.5 - 203.0.113.10 TCP ACK三次握手完成。接下来就是数据传输阶段。这一步不要逐条看 payload先看 Wireshark 给你标的异常指示TCP Retransmission、TCP Dup ACK、TCP Out-Of-Order、TCP ZeroWindow。重传Retransmission说明有包丢了或对端没确认网络质量差或者服务端处理不过来。重复 ACKDup ACK对端反复要求重发同一个序号说明中间丢了包。乱序Out-Of-Order包到达顺序和发送顺序不一致常见于多路径、Wi-Fi 切换等场景。零窗口ZeroWindow对端缓冲区满了TCP 层在“喊停”这不是网络问题是应用层消费速度跟不上。我一般会先用“统计 → 流量图”或者右键“追踪流 → TCP 流”把整条流可视化再点开异常包看具体是哪个序号段的。判断根因的时候第一步永远是看异常集中在哪个阶段握手阶段、TLS 协商阶段、还是数据传输阶段。阶段不同排查方向完全不同。新手最容易犯的错是看到一条重传就觉得是“网络丢包”其实可能是服务端设置了很小的接收窗口、客户端一次发太大、或者 MTU 过大导致分片被中间设备丢弃。这些都要结合包长和窗口大小一起看。3.3 UDP 只看端口和时间戳如何推断丢包与抖动UDP 抓包比 TCP 看起来“清爽”很多没有握手也没有重传但看的人往往更懵——看起来一切正常但用户就是卡。我自己的分析套路是四步建基线先用 Wireshark 的“统计 → 会话”看这个 UDP 对端的包数量、字节数建立一个正常量级。看序号连续性大部分真实业务 UDP 协议会在 payload 里带序号。筛选出协议字段按顺序拉出来看。如果出现 1、2、3、5、6 这种跳跃掉的那一个序号大概率就是丢了。有时候序号是连续的但时间戳间隔突然变大那就是抖动。看时间戳间隔在 Wireshark 里把frame.time_delta字段显示出来如果相邻包的间隔从正常的 20ms 突然变成 500ms再结合序号没有丢失说明是网络延迟增大不是丢包。比对客户端和服务端两个方向双向都看一下确认丢包是“上行丢”还是“下行丢”。这决定是让用户换网络、改 App 发送策略还是服务端加大缓冲区。UDP 抓包有个天然局限你只能看到“发出的包”和“收到的包”没法知道中间丢了多少。所以最终结论往往用“推测交叉验证”的方式给出序号跳跃说明某处丢了包时间戳间隔异常说明网络抖动接收端的应用层日志里如果正好有“等待超时”的记录证据链就闭合了。4. HTTPS 流量怎么开证书安装、信任与双向认证的坑4.1 让抓包工具能解开 HTTPS 的标准步骤绝大多数业务现在都是 HTTPS如果你只能在 Wireshark 里看到一堆 TLS 加密数据那对排查业务问题基本没用。所以我需要单独讲一下怎么让数据“看得懂”。最常用的方法是用 Charles 这类工具做中间人解密的 TLS 转发。大致流程是在 Mac 上启动 Charles开启 HTTPS 解密功能并安装并信任 Charles 的根证书。iPhone 连上 Mac 所在的局域网Wi-Fi 设置里把 HTTP 流量转发指向 Mac 的监听端口。用 iOS 的 Safari 访问chls.pro/ssl下载并安装根证书。到“设置 → 通用 → 关于本机 → 证书信任设置”把 Charles 根证书的“完全信任”打开。这一步 iOS 10.3 以上必做漏了这一步会提示证书无效。在 Charles 里为需要解密的域名勾选 SSL Proxying重新发起请求就能看到明文了。这里要特别提醒不要为了图方便全局开启 SSL Proxying。一是性能影响很大二是很多 App 会检测到中间人并直接异常退出或发送假数据。我通常只在需要排查的域名上开排查完立刻关掉。4.2 遇到证书固定与双向认证时怎么办很多金融、出行类 App 会做证书固定也就是在客户端内置服务端证书指纹校验不匹配就断开连接。这种情况下Charles 就算装了根证书也解不开因为 App 根本不认它。遇到证书固定我一般会放弃中间人解密改用三层方案里的“设备侧 协议侧”关闭 HTTPS 解密只在 Wireshark 里看 TLS 握手是否成功、用了哪个密码套件。在代码里用 URLSession 的taskMetrics把连接建立耗时、TLS 握手耗时、请求发送耗时打点输出。遇到双向认证客户端证书的场景抓包工具里就算导入了客户端 p12 也常常不好使因为客户端证书的私钥保护和使用时机都由系统安全模块管理。这种时候老老实实加日志比折腾抓包工具更高效。一句话总结抓包工具在 HTTPS 场景下能解的是“信任该证书”的流量解不开的是“不信任任何额外证书”的流量。区分清楚这个边界能少浪费很多时间。5. 一次线上偶发超时问题的完整排查链路5.1 从一条超时日志开始的证据链第 3 章讲的都是“怎么抓到”这一章用一个真实复盘把整个过程串起来。当时的情况是某项目组反馈iOS 端用户在上传文件时偶发报错提示“请求超时”Android 端同样网络环境下却基本正常。一开始大家怀疑是服务端问题因为同一个接口客户端日志显示“请求已发送”。我接手之后没有直接上 Wireshark而是先做了一件事让项目组把超时发生时刻的客户端日志、设备网络状态、服务端访问日志全部拉出来对齐。结果发现服务端在那个时间窗口里根本没有收到任何请求记录说明问题大概率出在“客户端发出请求”到“请求到达服务端”这一段链路。这时候才决定上抓包。由于超时是偶发的直接在用户设备上抓包不现实我们采用了可复现方案在测试机上跑同样的上传流程用 RVIT 把 iOS 虚拟网卡挂到 Mac 上持续抓包等待问题出现。大概跑了半个多小时终于在一次弱网模拟下复现了超时。5.2 抓包验证与条件收窄抓到包后我先把过滤条件设为目标服务端 IP 和tcp然后看 TCP 流的整体形态。结果发现三次握手都是成功的TLS 协商也完成了问题出在数据传输阶段出现了大面积的TCP Retransmission集中在几个比较大的 segment 上。很多包标注了TCP Dup ACK但连接没有立即断开。我们用的测试网络环境是 Wi-Fi此时丢包率明显升高。把这些异常和包长度放一起看发现上传请求的数据段普遍超过了一个阈值部分分片在弱网环境下容易被丢弃。于是结论逐渐清晰问题不是服务端不响应而是客户端一次性发送的数据量过大在弱网 Wi-Fi 上分片后被丢弃触发重传和超时。随后我们又对比了蜂窝网络下的抓包结果同样条件下问题复现概率大幅下降。这进一步支持了“大包在弱网丢包”的判断——因为蜂窝网络的分片和调度策略与 Wi-Fi 不同。5.3 根因、代码改动与二次验证定位到根因之后改动其实不大在上传逻辑里把大文件切成分片单次请求的数据量降到底部。增加应用层重试机制失败后指数退避重试。在弱网环境下主动降低并发数避免多条流同时重传加剧拥塞。改动上线后我们在模拟弱网环境里再用 RVIT 抓包验证确认重传率明显下降超时问题不再复现。整个排查链路也就闭环了。这个案例最值得记住的并不是某一条命令或某个过滤条件而是排查的顺序先由日志和数据确认问题发生的环节再用抓包验证网络层的真实行为最后让代码改动去回应网络行为。没有第一步直接抓包很容易被海量数据淹没没有第二步改动就是在猜。6. 把抓包能力沉淀成日常工程实践6.1 在 URLSession 层建立可观测指标抓包厉害但你不能每次都靠抓包解决所有问题。尤其线上用户环境千奇百怪你不可能一个个去抓。我这几年的心得是把抓包思维下沉到代码里在 URLSession 层建立一套“准抓包”的可观测指标。具体做法很简单。iOS 的 URLSession 提供了taskMetrics回调里面包含了完整的请求生命周期DNS 解析开始/结束时间、TCP 连接开始时间、TLS 握手开始/结束时间、首字节时间、总耗时。把这些时间点打点上报线上问题即使不抓包也能很清楚地看到瓶颈在哪。我通常会把以下指标沉淀成一条网络日志DNS 解析耗时判断本地 DNS 是否异常TCP 连接建立耗时判断网络连通性TLS 握手耗时判断证书校验和协商速度请求发送耗时、响应首字节耗时判断服务端处理速度是否发生连接复用、是否走了 IPv6网络类型Wi-Fi / 蜂窝 / 运营商日志里要脱敏token、手机号、请求体一律不写。只记录时间点和状态码这些“网络证据”。这套东西做好之后很多线上问题根本不用抓包看指标就能定位到八九不离十。6.2 自动化回归与日志脱敏如果你所在的团队有自动化测试可以更进一步在回归环境里跑关键业务流程时用 RVIT 抓固定时长的包自动分析这几个指标有没有非预期的RST包。HTTP 请求有没有走明文。TCP 重传率是否超过阈值。UDP 包是否存在大量乱序。我在实际操作中会写一个简单的脚本用tshark读取 pcap 文件统计上述指标输出成一份简短报告。这个报告不是给人逐条看的而是用来“报警”连续几条指标异常就说明最近一次的改动可能影响了网络层行为需要人工介入。日志脱敏这事再强调一遍。抓包里经常能看到完整的 token、session、甚至是用户头像的 URL。把这些数据落到本地文件或者上传到日志系统都是有隐私风险的。我自己的原则是能不打日志就不打必须打就只留脱敏后的信息比如只保留 URL path不保留 query 参数。6.3 什么情况下不该依赖抓包最后得说点反直觉的东西不是所有问题都该用抓包解决。抓包解决的是“网络协议层的行为”也就是“包发没发出去、发到哪了、对端怎么回的”。但如果你遇到的是“UI 卡顿”“内存上涨”“数据库读写慢”“业务逻辑条件分支错误”这类问题抓包根本帮不上忙硬抓只会浪费时间。我见过的最典型低效场景是一个按钮点了没反应开发同学不去看业务日志先去抓包抓到发现根本没有网络请求——然后呢还是要回头查代码。所以我的习惯是先问自己“这个问题是否涉及跨设备的信息传递”如果不涉及就别抓包如果涉及再确定是 TCP 连接问题还是 UDP 内容问题然后选择对应的抓包方案。6.4 一个我现在仍在用的检查习惯项目上线前我会固定跑一轮“流量巡检”在测试机上走一遍冷启动、登录、核心业务、退出登录的流程同时在 Mac 上用tcpdump -i rvi0 -w pre_release.pcap把全程包抓下来。然后快速扫一眼有没有域名解析失败。有没有多次 TLS 重协商。有没有明显超过基线水平的重传。有没有意外发出的明文 UDP 流量。这套巡检我已经坚持了挺长时间确实提前拦下过不少问题。抓包本身不难难的是把它变成一种下意识的工作习惯。工具是放大器真正值钱的是你对 TCP 状态机、对 UDP 语义、对 App 自身网络模型的判断力。把那套判断力练起来以后再遇到“我也不知道为什么就超时了”的问题心里会稳稳地有数。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →