从iOS应用到AWS Elastic Beanstalk后端的间歇性SSL错误

Jon*_*Cox 10 ssl amazon-web-services ios amazon-elastic-beanstalk app-transport-security

我的iOS应用程序向后端发出HTTPS请求几个月以来,出现间歇性SSL错误。

错误说明:

An SSL error has occurred and a secure connection to the server cannot be made.
Run Code Online (Sandbox Code Playgroud)

控制台在调试模式下记录:

2019-07-06 15:12:37.012198+0100 MyApp[37255:12499941] [BoringSSL] nw_protocol_boringssl_input_finished(1543) [C2.1:2][0x159e8e4a0] Peer disconnected during the middle of a handshake. Sending errSSLClosedNoNotify(-9816) alert
2019-07-06 15:12:37.026641+0100 MyApp[37255:12499941] TIC TCP Conn Failed [2:0x280486d00]: 3:-9816 Err(-9816)
2019-07-06 15:12:37.027759+0100 MyApp[37255:12499941] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9816)
2019-07-06 15:12:37.027839+0100 MyApp[37255:12499941] Task <D5AF17C0-C202-4229-BD52-690EFDB10379>.<1> HTTP load failed (error code: -1200 [3:-9816])
2019-07-06 15:12:37.028016+0100 MyApp[37255:12499941] Task <D5AF17C0-C202-4229-BD52-690EFDB10379>.<1> finished with error - code: -1200
2019-07-06 15:12:37.032759+0100 MyApp[37255:12500041] Task <D5AF17C0-C202-4229-BD52-690EFDB10379>.<1> load failed with error Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSErrorFailingURLStringKey=https://api.example.com/v1/example/example?param=example, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <D5AF17C0-C202-4229-BD52-690EFDB10379>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <D5AF17C0-C202-4229-BD52-690EFDB10379>.<1>"
), NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://api.example.com/v1/example/example?param=example, NSUnderlyingError=0x283ff2160 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9816, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9816}}, _kCFStreamErrorCodeKey=-9816} [-1200]
Run Code Online (Sandbox Code Playgroud)

该错误主要发生在3G / 4G而不是wifi上,并且在网络信号较低时更经常发生。如果发生一次,它将在接下来的几个请求中继续发生,但最终将在此后不久再次起作用。

根据分析,用户评论和用户错误报告:它影响很大一部分用户,但不是100%。

--

后端托管在AWS Elastic Beanstalk上。使用Nginx代理服务器以及负载均衡器后面的多个实例充当Docker应用程序。

我尝试增加和减少实例大小,但这似乎没有什么区别。

我最近从零开始创建了一个全新的Elastic Beanstalk环境,以查看是否有帮助。以前它使用的是经典负载均衡器,现在它使用的是应用程序负载均衡器。早期迹象表明它减少了SSL错误的数量,但仍在发生。

新的负载平衡器正在使用以下SSL策略:

ELBSecurityPolicy-FS-2018-06
Run Code Online (Sandbox Code Playgroud)

此处定义:https : //docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html

是否应该使用其他SSL策略?

--

在应用程序中,Web请求是使用URLSession.shared.dataTask...etc 发出的。我还尝试使用Alamofire库来查看是否有所作为。它没有。

我觉得这可能与Apple的App Transport Security有关。但是,由于它间歇性地失败,所以我对方法一无所知。

相关的Apple文档在此页面的底部:https : //developer.apple.com/security/

如果您需要更多信息来帮助调试,请告诉我。

--

更新:

因此,在尝试了许多建议(感谢所有贡献者!)之后,并且进一步了解了SSL,负载平衡器等,我发现了可以解决此问题的方法。

(次要警告:由于问题的断断续续的性质以及我对它的跟踪不太好,因此我不能100%地确定它已完全解决,但是所有可用的证据都表明问题已得到解决。)

“解决方案”是将服务移至Google Cloud Run,该服务对于Docker容器基本上是无服务器的。

至关重要的是,Google Cloud会自动处理SSL证书的设置,因此我可以零花钱。另一个优点是,我现在只为实际使用的计算时间付费,因此它更便宜。

为阅读本文的人致歉,以寻求对原始问题的实际解决方案,但是在下面的答案和评论中有很多不错的事情要研究。

kar*_*har 5

免责声明:这不是您的问题的答案,我只是想与您大声思考

这是我要检查的几点,假设您有此信息或可以选择获取这些信息,这可能会帮助我确定问题的根本原因,否则除非您可以与他人共同调试,否则它将是一个黑匣子亚马逊

  • 显然,这是证书固定问题

  • 通过3g调制解调器通过Wireshark检查是否发送了TLS版本请求,并从AWS检查要求,例如,它们可能需要1.2,而您正在发送1.1

  • 这对于在服务器端检查证书字符串并将其与客户端进行手动比较非常重要,它可能会通过连接管道进行不同的编码

  • 只要您说连接速度慢时它可能更经常失败,请检查证书固定超时(服务器可能会获得证书字符串的一部分,并将其与它所拥有的证书字符串进行比较,并发现由于连接延迟而导致不匹配)

  • 确保负载均衡器后面的docker应用的所有实例都具有与您固定的证书完全相同的版本

  • 检查其连接失败的iOS版本的统计信息,并检查此特定版本中的安全性