遇到 iOS App 在特定版本上报 SSL 握手失败,优先检查服务器 TLS 配置是否兼容旧系统,以及客户端 Info.plist 中的 ATS 设置是否过于严格。
先说结论:大多数特定版本报错源于 TLS 协议版本不匹配或证书链不完整,需同时排查服务端配置与客户端信任策略。
- 先确认:使用 OpenSSL 或在线工具检测服务端支持的 TLS 版本和证书链。
- 先处理:服务端启用 TLS 1.2 及以上,客户端按需调整 ATS 例外域。
- 再验证:通过 Charles 或 Xcode 控制台查看具体握手错误码。
命令速用版
在终端使用 curl 模拟不同 TLS 版本请求,快速判断服务端兼容性(注意参数格式):
curl -v `--tlsv1`.2 https://your-domain.comcurl -v `--tlsv1`.0 https://your-domain.com若低版本 TLS 报错而高版本正常,说明服务端关闭了旧协议,旧版 iOS 可能无法连接。也可使用 OpenSSL 深入检测:
openssl s_client -connect your-domain.com:443 -tls1_2Info.plist 配置示例
若需兼容特定域名或测试环境,可在 Info.plist 中配置 ATS 例外。以下是标准 XML 结构示例:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>your-domain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>注意:生产环境严禁使用 NSAllowsArbitraryLoads 绕过所有安全检查,可能导致审核被拒。
常见 SSL 错误码对照
在 Xcode 控制台或日志中查找 CFNetwork 相关错误码,辅助定位问题:
- -9800 (SSLHandshakeFailed): 握手失败,通常是协议版本不匹配或证书不被信任。
- -9802 (SSLBadCert): 证书无效,可能过期、域名不匹配或链不完整。
- -9807 (SSLClientHelloFailed): 客户端 Hello 消息发送失败,常见于网络拦截或 TLS 配置错误。
- -9814 (SSLBadCipherSuite): 加密套件不匹配,服务端未启用客户端支持的加密算法。
分步处理
1. 检查服务端证书链:使用 SSL Labs 测试域名,确保 Certificate Chain 完整,无缺失中间证书。
2. 确认 TLS 版本支持:服务端应至少启用 TLS 1.2,若需兼容 iOS 9 及以下,需确认是否允许 TLS 1.0/1.1(不建议长期保留)。
3. 检查客户端 Info.plist:在 Xcode 中查看 Info.plist,确认 NSAppTransportSecurity 设置。若开发测试需要,可临时添加 NSExceptionDomains 例外,但发布需谨慎。
4. 核对证书有效期:确保证书未过期,且针对 iOS 12.2.1 以下设备,避免使用仅依赖 ISRG Root X1 且未交叉签名的 Let's Encrypt 证书(2021 年 9 月后部分旧设备受影响)。
怎么验证是否生效
1. Xcode 控制台日志:运行 App 时观察 Console 输出,查找 CFNetwork SSLHandshake 错误码,如 -9800 表示握手失败。
2. 真机测试:使用不同 iOS 版本的测试机访问同一接口,对比结果。
3. 抓包工具:使用 Charles 配置 SSL Proxying,查看握手阶段的 Client Hello 和 Server Hello 内容,确认协议版本协商结果。
常见坑
1. ATS 例外滥用:在 Info.plist 中设置 NSAllowsArbitraryLoads 会绕过所有安全检查,可能导致 App 被审核拒绝或存在安全风险。
2. 旧设备信任库:iOS 12.2.1 之前的系统可能不信任新的根证书,需确保服务端发送完整的证书链包括交叉签名。
3. 时间同步问题:部分用户设备系统时间错误会导致证书验证失败,需在 App 内增加时间校验提示。
参考来源
- Apple Developer Documentation, App Transport Security, https://developer.apple.com/documentation/security/preventing_insecure_network_connections
- Let's Encrypt, DST Root CA X3 Expiration, https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/
- SSL Labs, SSL Server Test, https://www.ssllabs.com/ssltest/