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

从iOS应用程序到AWS Elastic Beanstalk后端的间歇性SSL错误,ios,amazon-web-services,ssl,amazon-elastic-beanstalk,app-transport-security,Ios,Amazon Web Services,Ssl,Amazon Elastic Beanstalk,App Transport Security,几个月来,我的iOS应用程序在向后端发出HTTPS请求时出现间歇性SSL错误 错误描述: An SSL error has occurred and a secure connection to the server cannot be made. 处于调试模式时,控制台将记录: 2019-07-06 15:12:37.012198+0100 MyApp[37255:12499941] [BoringSSL] nw_protocol_boringssl_input_finished(1543)

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

错误描述:

An SSL error has occurred and a secure connection to the server cannot be made.
处于调试模式时,控制台将记录:

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]
此处定义如下:

它应该使用不同的SSL策略吗

-

在应用程序中,web请求是使用
URLSession.shared.dataTask…
等进行的,我还尝试使用库来查看这是否会产生影响。事实并非如此

我觉得这可能与苹果的应用程序传输安全有关。然而,由于它断断续续地失败,我不知道该怎么做

相关苹果文档位于本页底部:

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

-

更新:

因此,在尝试了许多建议(感谢所有参与的人!)并了解了更多关于SSL、负载平衡器等的信息之后,我找到了一些解决问题的方法

(小警告:我不能100%肯定它是完全修复的,因为问题的间歇性和我对它的跟踪不是很好,但所有可用的证据表明它现在已经修复。)

解决方案是将服务转移到谷歌,这基本上是Docker容器的无服务器服务。

至关重要的是,谷歌云会自动处理SSL证书的设置,所以我没有任何地方要搞砸。另一个优点是,我现在只支付我实际使用的计算时间,所以更便宜

向阅读本文以寻求原始问题的实际解决方案的任何人致歉,但在下面的回答和评论中有许多好事情需要调查。

免责声明: 这不是对你问题的回答,我只是想和你一起大声思考

以下是我将要检查的几点,我认为这可能有助于我确定问题的根本原因,假设您有这些信息或可以选择获取这些信息,否则它将是一个黑盒子,除非您可以与amazon联合调试

  • 很明显,这是证书固定问题

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

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

  • 只要您说过,当连接速度较慢时,它可能会更频繁地失败,请检查证书固定超时(服务器可能会获取部分证书字符串,并将其与已有的证书字符串进行比较,发现由于连接延迟而不匹配)

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

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


您是否在Info.plist文件中添加了应用程序传输安全设置密钥

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsForMedia</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>YOUR_SERVER_COM</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
        <key>facebook.com</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
        <key>fbcdn.net</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
        <key>graph.facebook.com</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>
</plist>

NSAllowsArbitraryLoads
NSAllowsArbilarLoadsFormedia
NSAllowsArbilarLoadsInWebContent
NSExceptionDomains
您的服务器\u COM
NSExceptionRequiresForwardSecretary
n包括多个域
facebook.com
NSExceptionRequiresForwardSecretary
n包括多个域
fbcdn.net
NSExceptionRequiresForwardSecretary
n包括多个域
graph.facebook.com
NSExceptionRequiresForwardSecretary
n包括多个域

首先,我有你描述的所有症状。在寻找解决方案、网络团队、安全团队、软件团队等时,我与所有团队进行了交谈。这是一个很难解决的问题,但简要解释一下我们是如何解决它的将是有益的

提示1:正如您所看到的,SSL身份验证并不总是错误的。有时它会有投掷错误。SSL密钥或基础结构中使用的任何文件最终都是一个包含字节的文件,这有时会导致此错误,因为并非所有字节都可以在网络上发送。我想,在我的情况下,甚至调试的情况,它就是这样。由此导致的文件包损坏

提示2:对于不同的客户端,请求可以正常工作,有时不正确的一般原因是服务器通过缓存响应某些请求。这通常与LoadBalancer配置有关。在我的例子中,基于cookie的身份验证与软件工程师使用的其他身份验证模型发生了变化。这会通过ram中的静态对象演化请求,导致字节传输出现问题,从而获得更好的性能


我强烈推荐的观点。在服务器端,您应该逐个检查LoadBalancer属性。回顾生命周期管理。您甚至可以通过将LoadBalancer改为基于会话或基于cookie的身份验证方法(如果您需要的话)。

我对您的后端体系结构(docker,nginx)了解不多。我的猜测是,您的后端最初是为非移动浏览器编写的,完全加密的内容,但是在迁移到AWS之前编写的,是否进行后端身份验证?现在,他们要求你在前端构建IOS应用程序,而在后端构建Elastic Beanstalk?这是一个很好的策略,因为它更容易在云上运行,并且Elastic Beanstalk提供了扩展功能

此策略的问题在于,当原始后端加密流量达到负载平衡,并且加密会话未配置时
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsForMedia</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>YOUR_SERVER_COM</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
        <key>facebook.com</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
        <key>fbcdn.net</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
        <key>graph.facebook.com</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>
</plist>