一 MGS常用抓包方案介绍
1.背景
在基于mPaaS框架的移动App项目开发过程中,经常会遇到各种个样的错误。特别是当问题涉及到客户端与服务器或网关之间的交互行为时,抓取HTTP或者TCP报文是帮助理解和排查这类错误的重要手段。例如,当观察到存在请求报错时,可以通过分析请求报文和响应报文,查看请求的信息是否存在错误、服务器是否正常返回以及查看返回值是否符合预期等,帮助判断问题的根本原因。
2.HTTP报文抓包
1)抓包原理
常用的HTTP抓包工具有两个:Fiddler和Charles。两者的基本原理几乎一样:在本地架设一个的HTTP Proxy,所有通过该Proxy的HTTP报文均可以被截获和解析,如图1-1所示。需要注意的是,对于HTTPS协议报文的解析需要提前在客户端配置好Charles/Fiddler的CA Root证书,保证“中间人”转发的信息被客户端信任,从而实现报文的解密。
图1‑1 抓包原理
其中需要注意的是Charles/Fiddler只能对HTTPS报文本身进行解密展示。在是实践中,开发者可能会数据先做一次离线加密操作(如MGS的数据加密功能),再经过HTTPS进行通讯。这部分的原始内容是无法被Charles/Fiddler解密的,只能展示离线加密后的内容。
2)抓包工具
如图1-2所示,本节以Charles 4.5.5版本为例说明。
图1‑2 抓包工具
(1)安装与基本界面
从 Charles 官网https://www.charlesproxy.com/,下载 Charles 4.5.5 的 dmg 安装包。运行安装包并安装到系统中。首次启动 Charles 时,会请求给予设置系统代理的权限,设置允许。启动后,当有HTTP请求经过Charles时,应该可以在Charles主界面中见到这些请求,如图1-3所示。
图1‑3 抓包页面
(2)客户端配置
在本机上运行的模拟器所产生的HTTP请求默认地会走系统Proxy,因此无需手动配置Proxy信息。对于物理移动设备(iPhone/Android手机)则需要手动配置Proxy,保证其所产生的网络请求均经过Charles Proxy转发。同时需要保证移动设备可以通过IP直接访问到安装Charles的Mac机器,建议移动设备和安装Charles的机器处于同一网络下。然后配置过程如下:
首先查看Charles的Proxy配置,记住Proxy端口号:点击Proxy -> Proxy Settings,打开Proxy配置页面,如图1-4所示,默认端口号为8888。
图1‑4 抓包设置
然后打开系统网络设置,查看本机IP地址,如图1-5所示。
图1‑5 抓包ip地址
配置移动端Proxy设置,已iOS设备为例,设置->无线网络->对应WIFI设置,添加Proxy(Charles机器)的IP地址和端口号,如图1-6所示。
图1‑6 iOS设置代理
移动端配置成功后,移动端首次请求到达Charles时会有如下提示,如图1-7所示,点击Allow按钮。
图1‑7 设置代理提示框
这样可以在Charles中见到移动设备产生的HTTP请求。例如,通过手机浏览器访问http://www.antfin.com/,可以在Charles中见到该请求,如图1-8所示。
图1‑8 网络代理示意图
3)抓包客户端配置
在默认情况下,Charles不会对HTTPS报文进行解密,如果需要分析HTTPS的报文内容,需要配置好SSL Proxying功能。主要有两部分,包括设备端(模拟器和真机都要安装)安装并信任Charles Root CA;Charles上配置好需要解密的HTTPS站点。
(1)iOS App设置
在Charles开启的状态下,移动端通过浏览器(iOS请使用Safari)访问 chls.pro/ssl ,浏览器会自动下载charles-proxy-ssl-proxying-certificate.pem并提示安装Charles Proxy Customer Root Certificate,如图1-9所示。iOS 10以上系统,需要进入设置 -> 通用 -> 关于本机 -> 证书信任设置,对上一步安装的Charles证书启用完全信任。
图1‑9 iOS代理示意图
iOS 10以上系统,需要进入设置 -> 通用 -> 关于本机 -> 证书信任设置,对上一步安装的Charles证书启用完全信任。如图1-10所示。
图1‑10 iOS10设置示意图
(2)Android App设置
Android会需要对证书命名,并安装在用户信任凭据(Customer Certificate)中。如图1-11所示。
图1‑11 Android代理示意图
需要注意的是,对于Android App,需要通过增加配置网络安全选项的方式来信任用户信任凭据。在Portal工程中增加一个Network Security Configuration XML资源放到 res/xml/network_security_config.xml,其中XML的内容如下:
同时更新AndroidManifest.xml文件,配置使用上面的network security configuration:
android:networkSecurityConfig="@xml/network_security_config"
... >
...
(2)Charles设置
如果本机(Mac)需要信任Charles证书,请通过Help -> SSL Proxying -> Install Charles Root Certificate。
图1‑12 Charles示意图
同时在Charles菜单栏选择Proxy -> SSL Proxy Settings...,在SSL Proxying选项卡中可以添加需要进行HTTPS报文解密的域名和端口,并勾选Enable SSL Proxying。如图1-13所示。
图1‑13 Charles配置示意图
对于mPaaS公有云用户,需要增加的域名包括:
*.aliyun.com
*.alipay.com
*.aliyuncs.com
对于私有云用户,参考上述配置,加入自定义域名。上述配置完成后,应该可以在Charles中看到HTTPS报文的内容,例如:配置前:HTTPS报文处于乱码状态。如图1-14所示。
图1‑14 Charles抓包乱码示意图
配置完成后,HTTPS报文内容被解密,如图1-15所示。
图1‑15 Charles抓包解密后示意图
4)小结
在本节中,简单介绍了Charles的原理、安装、配置和HTTPS解密配置的内容。Charles在Mac端是相当重要的HTTP报文分析工具,在许多问题的排查中能够发挥相当重要的作用,帮助开发者高效定位和解决问题。
3.TCP抓包
Charles和Fiddler可以帮助捕获和分析HTTP层面的问题,如果问题发生在TCP/IP层面,则需要TCP报文的捕获和分析工具。Wireshark(支持Mac/Windows平台)、Network Monitor(Windows 平台)和tcpdump是常用的三种网络层抓包工具。比较常见的网络层问题包括SSL握手失败和TCP链接中断、重发等。本文讲主要介绍TCP层的抓包工具。
1)抓包原理
不再像Charles/Fiddler那样可以通过“中间人”代理模式来捕获报文,TCP报文的抓取一般是非侵入试的,通过监听网卡接口数据,直接进行TCP报文的“镜像”捕获。在一般场景下,可以抓包的点比较多,可以在客户端抓(A),可以在中间设备上抓(B),也可以在服务端上抓(C),如图1-16所示。不同点上抓取的包都有各自的局限性(只能说明部分链路的网络情况,一个点上的网络表现不能简单推广到全链路上),因此需要结合症状和其他日志合理选取抓包方式。在某些极端的案例中,我们需要在客户端、中间设备和服务端同时抓包,才能相互交叉比对验证问题的根源。下面几个小结会介绍几种抓包工具和方式。
图1‑16 TCP抓包示意图
2)抓包工具
(1)Wireshark使用:在Wireshark官网下载安装包:https://www.wireshark.org/安装并启动,主界面如图1-17所示,其中Mac和Windows版本界面略有差别。
图1‑17 Wireshark示意图
开始抓包,在Wireshark主界面上,一般可以看到本机的网络接口,以本机为例,双击Wi-Fi: en0接口开始抓取该网卡接口上的网络包,如图1-18所示。抓包数据如图1-19所示。
图1‑18 Wireshark示意图
图1‑19 Wireshark抓包数据示意图
抓包结束可以通过点击菜单栏上的红色停止按钮(CMD+E),停止抓包。点击保存按钮(CMD+S)保存捕获的网络包,以便离线分析,如图1-20所示。
图1‑20 Wireshark抓包暂停示意图
(2) TCPDUMP
Tcpdump是一个小巧紧致的命令行网络包捕获、分析工具。虽然易用性上和 Wireshark 比稍微差一些,但优势是可以运行在更多的平台和环境下,方便直接在客户端或服务端进行抓包。
Tcpdump 在不同环境下支持的参数并不完全相同,建议通过 man tcpdump 命令确认当前支持的参数类型和使用方法。一个常见的基本命令组合如下
// 抓取完整报文并报错到文件中
tcpdump -s 0 -w myCapture.pcap
3)手机端抓包
(1)iOS平台
iOS客户端出口抓包需要把iOS移动设备通过usb连接到macbook上,并在Mac上建立的一个该设备网卡的虚拟映射。Wireshark通过该虚拟网卡捕获iOS移动设备上的网络包。
首先获取iPhone的UDID,将iOS移动设备通过USB接口连接Mac上,然后在终端上使用如下命令获取iOS设备的UDID(Serial Number):
$ system_profiler SPUSBDataType
或者通过Xcode->Window->Devices and Simulators查看UDID(Identifiler)
图1‑21 查看UDID
创建虚拟网卡映射,茹素1-22所示,rvi0即虚拟网卡名。
$ rvictl -s < Your Device UUID >
Starting device < Your Device UUID > [SUCCEEDED] with interface rvi0
图1‑22 创建虚拟网卡
然后启动抓包(已Wireshark为例)打开Wireshark,本地接口列表界面中出现了rvi0。图示如下:
图1‑23 启动抓包
双击rvi0进入抓包界面,进入默认自动开始抓包,如图1-24所示。
图1‑24 抓包数据
问题复现后,在菜单栏点击结束(CMD+E)按钮停止抓包,点击保存(CMD+S)按钮
保存按钮保存。
(1)Android平台
Android客户端出口抓包需要提前获取设备root权限,通过adb在设备上调用tcpdump命令实现抓包。
首先下载TCPDump for Android,下载地址:https://www.androidtcpdump.com/。然后安装TCPDump。通过如下命令把TCPDump安装到设备上,并赋予执行权限:
adb push tcpdump /data/local/tcpdump
adb shell chmod 6755 /data/local/tcpdump
启动tcpdump开始抓包
cd /data/local
./tcpdump -i any -p -s 0 -w /sdcard/myCapture.pcap
问题复现后,需要停止抓包时,根据提示停止抓包(按下Ctrl+ C)。通过如下命令将报文数据复制出来:
adb pull /sdcard/myCapture.pcap
4)服务端抓包
某些问题需要在服务端启动抓包,本节以TCPDump为例。
安装tcpdump,在CentOS上安装:
yum install tcpdump
在Debian和Ubuntu上安装:
apt-get install tcpdump
然后启动抓包。TCPDump本身可配置的参数较多,可以结合具体场景进行参数配置,参数详情见:https://www.tcpdump.org/#documentation。例如:
tcpdump -s 0 -w myCapture.pcap
问题复现后,按下Ctrl+C停止抓包,将捕获的报文保存到合适的地方。
4)小结
网络包的捕获首先需要结合场景和问题合理地规划抓包方式。因为场景比较丰富,可选择的工具也比较多,实践中需要根据实际的系统环境正确选择。本节提到三个工具均既可以作为抓包工具,也可以作为后期的报文分析工具。具体的分析过程不在此详述。
二 MGS证书问题
1.背景
HTTPS作为站点安全的最佳实践之一,已经得到了最广泛的支持。然而在实际生产过程中,由 TLS/SSL 握手失败引起的连接异常问题依然十分常见。本文将结合MGS客户端实际排查案例,介绍这类问题在移动领域的排查和解决方案。
2.TLS/SSL握手流程
HTTPS的主要作用是在不安全的网络上创建一个基于 TLS/SSL 协议安全信道,对窃听和中间人攻击提供一定程度的合理防护。TLS/SSL 握手的基本流程如下图描述:
图1‑25 握手流程
3. 案例分享
1)CFCA证书的历史问题
(1) 背景
某客户为其生产环境的站点申请了一张由CFCA签发的证书。相关域名正确配置该证书且启用 HTTPS 后,经测试发现他们的客户端 App 在低版本手机上( iOS < 10.0,Android < 6.0)无法连接到相关站点。客户端调试发现,控制台会看到证书无效的错误信息(Invalid Certificate 或 Certificate Unknown )。
(2) 排查
起初,工程师并不知道客户的证书是由哪个机构签发以及有什么问题。而对于这类问题,一般均需要客户端网络包做进一步的分析与判断。因此安排客户在受影响的设备上进行问题复现及客户端抓包操作。获取到网络包后,首先确认了客户端连接失败的直接原因为 TLS
握手过程异常终止,如图1-26所示。
图1‑26 抓包数据
查看 Encrypted Alert 内容,错误信息为 0x02 0x2E。根据 TLS 1.2 协议(RFC5246)的定义该错误为因为 certificate_unknown。继续查看该证书的具体信息,根据 Server Hello 帧中携带的证书信息得知该证书由证书机构 China Financial Certification Authority(CFCA) 签发。再根据证书信息中的Authority Information Access (AIA) 信息确认 Intermediate CA 和 Root CA 证书。确认该证书签发机构的根证书为 CFCA EV ROOT。
回到存在问题的手机设备上(Android 5.1),检查系统内置的受信任 CA 根证书列表,未能找到 CFCA EV ROOT CA 证书;而在正常连接的手机上,可以找到该 CA 的根证书并默认设置为”信任“。
查阅 CFCA 证书的相关说明,该机构的证书在 iOS 10.1 及 Android 6.0 及以上版本才完成入根接入,参考如1-27所示。
图1‑27 证书介绍
(3)小结
从上面的分析可以看到,该问题的根因是低版本客户端设备没有内置CFCA的CA根证书。因此,基本的解决方案包括:
方案1:更换其他 CA 机构签发的证书,保证其 CA 根证书的在特定设备上已默认信任。
方案2:手动在受影响的设备上安装该 CA 根证书及中间证书,并配置为信任状态。
方案3:客户端 App 预置该 CA 根证书,并通过客户端代码配置信任该证书。
需要结合不同的业务场景选择合理解决方案。
2)证书链信任模式引起的问题
(1)背景
某客户新增了一个容灾备用接入地址,启用了一个新的域名并配置了一张全新的证书。测试发现,切换到该备用地址时,Android 客户端无法正常连接,报证书未知错误(Certificate Unknown);iOS 客户端表现正常。
(2)排查
首先在受影响的设备上进行问题复现及客户端抓包操作。获取到网络包之后,确认了客户端连接失败的直接原因为 TLS 握手过程异常终止,原因如图1-28所示,为Certificate Unknown:
图1‑28 报文截图
查看该证书的 CA 根证书及根证书的信任情况。发现该证书由中间 CA 机构 Secure Site Pro CA G2 签发,其根 CA 为 DigiCert Global Root CA,如图1-29所示。
图1‑29 证书截图
DigiCert Global Root CA 作为一个广泛支持的证书签发机构,其根CA 证书在绝大多数的设备上均为受信任状态,这一点在受影响的设备上也得到了确认。既然根 CA 的证书处于信任状态,为何证书验证还是失败?这成为下一步排查的重点方向。同一台设备,切换到正常环境下,也完成一次抓包操作。获取到新的网络包后做对比分析,发现两种情况下网络包中体现的区别为,正常环境下,服务器返回的证书包含了完整的 CA 证书链,而异常情况下,服务端返回的证书仅包含叶节点 CA 证书。如图1-30所示。
图1‑30 报文截图对比
根据上述线索进行排查研究,发现:不同于其他平台,Android 客户端默认是不会通过 AIA Extension去做证书链的校验。因此,当中间 CA 证书未安装或未缓存时,客户端App 是不会主动拉取中间 CA 证书并做进一步信任链校验的,从而导致证书校验失败。
(3)小结
从上面的排查分析看到,该问题和Android 平台自身的证书校验机制和证书打包方式相关。解决方案包括:
方案1:代码层面手动定制 TrustManager 去定制校验过程;
方案2:重新打包证书,将中间 CA 证书和根 CA 证书一同打包到服务端证书中。
该客户综合开发成本与环境现状,选择重新打包证书。新的证书配置完成后,问题得到解决。
3)加密套件协商引起的问题
(1)背景
某客户反馈他们的iOS客户端App用户在特定运营商网络环境下无法打开特定的业务站点(HTTPS 站点)。客户端处于白屏等待状态并最终报错;而在同样的网络环境下,系统浏览器可以打开该站点;同一台设备,切换到另一个网络运营商下,也可以访问该站点。
(2)排查
由于该问题直接表现在Web层,因此首先尝试通过 Charles 抓取 HTTP 层包进行分析。HTTP 日志发现相关 HTTP 请求并未发出。由此怀疑问题发生在 TCP 层,进而在受影响的设备上进行问题复现及客户端抓包操作。
获取到网络包后,首先确认问题,通过页面域名在网络包中寻找DNS解析结果。根据DNS解析结果找到站点IP,并过滤出客户端与该IP之间的访问情况。观察客户端与该服务
器之间的网络活动,发现存在 TLS 握手失败的情况,如图1-31所示。
图1‑31 报文报错
从上面的网络包可以看到,服务端(机房P中的服务器提供接入服务)在收到Client Hello 后,直接返回了Handshake Failure,这种情况下,一般需要服务端配合排查握手失败的直接原因。在客户端条件下,可以进一步缩小排查疑点。
重新考虑客户问题条件:相同的网络条件下,系统浏览器可以打开该页面;同一设备切换到另一运营商下(站点此时由机房 Q 中的服务器提供接入服务),可以正常访问。针对这这两种正常情况进行抓包和进一步分析。
通过对三种情况的网络观察发现。问题App发出的Client Hello显示支持17种加密套件,如图1-32所示。
图1‑32 报文报错
正常App发出的Client Hello显示支持26种加密套件,如图1-33所示。
图1‑33 报文报错
正常App和机房P服务器协商的加密套件为:TLS_RAS_WITH_3DES_EDE_CBC_SHA (0x000a) (不在问题 App 支持的加密套件范围内);问题 App 和机房 Q 服务器协商的加密套件为:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)(在问题 App 支持的加密套件范围内);
根据上述情况,可以推论问题的基本情况为:
问题App发出去的握手请求,支持17种加密套件(A集合);
正常App发出去的握手请求,支持26种加密套件(B集合);
机房P的接入服务器,能支持B集合种的至少一种加密套件,不支持A集合中的所有加密套件;
机房Q的接入服务器,既支持A集合中的至少一种加密套件,也支持B集合中的至少一种加密套件;
最终导致问题App无法通过机房P中的服务器访问该站点。
(3)小结
从上面的分析结论可以看到,由于客户端和服务端加密套件不匹配,导致在特定情况下的握手失败。进一步的问题解决方案包括:
方案1:调整客户端加密套件,增加支持的Cipher Suites(涉及客户端底层TLS/SSL库的升级);
方案2:调整服务端加密套件,增加支持的Cipher Suites(涉及服务端TLS/SSL 接入配置)。
该客户最终选择调整服务端加密套件,问题得到解决。
3)总结
从上述案例的分享和实践中可以看到,TLS层面的问题在客户端的症状表现上有相似之处,但是问题的根因却大相径庭。这里例举的问题虽不能覆盖所有的问题场景,但可以看到基本的排查思路如下:
判断问题是否属于 TLS/SSL 层面的问题。抓取网络包;有条件的情况下,可以针对正常和异常情况抓取两份网络包,以便后续进行对比分析。根据网络包探寻问题发生的直接原因,进而进一步探究问题的根本原因。根据分析结论并结合业务场景,选择合适的解决方案。
这类问题的排查基础是对 HTTPS 和 TLS/SSL 协议的理解以及对分析工具的掌握。在移动领域,这类问题存在一定的共性,直接了解上述结论和分析方法可以帮助开发者快速“出坑”。