[iOS] 调试 SSL 握手失败
Source: Dev.to
问题:意外的配置冲突
最近,我们的监控仪表板开始出现零星的网络错误日志。它们不是典型的 404 或 500,而是碎片化的低层错误,指向一个特定的罪魁祸首:SSL Handshake Failures。
这出乎意料,因为我们的 ATS(App Transport Security)配置看起来是完全宽松的。我们在 Info.plist 中明确将 NSAllowsArbitraryLoads 设置为 true。
NSAppTransportSecurity
NSAllowsArbitraryLoads
理论上,这个设置应该绕过 ATS 检查,允许连接使用自签名证书或旧版 TLS 的服务器。然而,尽管有此配置,我们仍然看到持续的 TLS/SSL 网络错误。
在深入阅读文档后,我发现了 Apple 配置规则中的一个隐藏覆盖。
发现:InWebContent 覆盖
根本原因在于我们为 WebView 启用了另一个关键键:NSAllowsArbitraryLoadsInWebContent。
我们启用了它以允许应用内浏览器加载混合内容。然而,Apple 文档中有一条关键说明:
“如果存在
NSAllowsArbitraryLoadsInWebContent,则NSAllowsArbitraryLoads的值会被覆盖为 NO。”
由于我们面向 iOS 10+,InWebContent 键的存在会悄悄地覆盖全局的 “Allow All” 设置。
- 在 WebView 中: 任意加载被允许。
- 本地网络(API 调用、图片加载): 全局标志被忽略,ATS 恢复为其 默认的严格模式。
这导致我们的应用对所有 API 调用强制执行严格的 ATS 策略(TLS 1.2+,需要前向保密),即使我们本意是允许任意加载。
为什么 TLS 设置是嫌疑人
一旦明确严格的 ATS 已启用,“SSL Handshake Failure” 日志就变得合情合理。
- 客户端(App): 强制使用 TLS 1.2 或更高(ATS 默认)。
- 服务器端: 只能使用 TLS 1.0 的旧版服务器。
结果: 协商失败,连接被中断。
我们不经意间阻断了自己的旧版服务器,因为应用的安全标准在默认情况下被静默地设为最高。
误解:“不安全” ≠ “旧协议”
一种常见的解决办法是为有问题的域名启用 NSExceptionAllowsInsecureHTTPLoads。人们常误以为允许 “不安全加载” 会关闭所有检查,包括 TLS 版本要求。
这是错误的。
NSExceptionAllowsInsecureHTTPLoads 只允许对指定域名进行 HTTP(未加密)连接,但它 不会:
- 降低 TLS 版本要求(HTTPS 仍然需要 TLS 1.2)。
- 绕过证书验证(自签名或已过期的证书仍会失败)。
如果服务器仅支持 TLS 1.0,握手仍会失败,无论此设置如何。
解决方案:精确配置
与其再次尝试强制全局 “Allow All”(这通常是不好的做法),我采用了精确的修复方式。
目标是:
- 保持高安全性: 必须保持证书验证开启。
- 降低兼容性障碍: 为特定的旧版域名显式允许旧协议。
以下是最终的 Info.plist 配置:
NSExceptionDomains
legacy-api.example.com
NSExceptionMinimumTLSVersion
TLSv1.0
NSExceptionRequiresForwardSecrecy
NSIncludesSubdomains
此配置指示应用 严格检查证书,但 即使使用较旧的 TLS 1.0 协议也接受连接。
部署与后续步骤
已部署更新的配置。如果假设正确,那些旧域名的 SSL/TLS 错误应该会消失。如果错误仍然存在,可能还有其他层面的原因——比如密码套件不匹配或中间证书问题。
我会在此帖子中更新结果。祈祷这就是这场 saga 的终点! 🤞
Summary
- Watch out for overrides:
NSAllowsArbitraryLoadsInWebContentsilently disablesNSAllowsArbitraryLoads. - Know your keys:
NSExceptionAllowsInsecureHTTPLoadsallows HTTP connections, butNSExceptionMinimumTLSVersionis required for TLS version issues. - Be specific: Don’t disable security globally. Configure exceptions only for the domains that actually need them.