使用Java API的S3/AWS的SSL问题:"证书中的主机名不匹配"

Gra*_*ray 8 java ssl amazon-s3 amazon-web-services

亚马逊在1.3.21版本的AWS Java SDK中"升级"了SSL安全性.在使用Amazon的AWS Java API时,这会破坏访问其名称中具有句点的任何S3存储桶.我使用的是版本1.3.21.1,目前是2012年10月5日.我在下面的回答中提供了一些解决方案,但我正在寻找针对此问题的其他解决方法.

如果您收到此错误,您将在例外/日志中看到类似以下消息的内容.在此示例中,存储桶名称为foo.example.com.

INFO: Unable to execute HTTP request: hostname in certificate didn't match:
       <foo.example.com.s3.amazonaws.com> != <*.s3.amazonaws.com>
       OR <*.s3.amazonaws.com> OR <s3.amazonaws.com>
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:220)
at org.apache.http.conn.ssl.StrictHostnameVerifier.verify(StrictHostnameVerifier.java:61)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:149)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:130)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:390)
Run Code Online (Sandbox Code Playgroud)

您可以在AWS S3论坛上查看此问题的文档:

https://forums.aws.amazon.com/thread.jspa?messageID=387508

亚马逊对此问题的回应如下.

对于具有此命名模式的存储桶,我们应该能够通过使用旧的路径样式的桶寻址方法(而不是更新的虚拟主机样式寻址)来解决此问题.我们将开始修复并确保我们的内部集成测试具有包含句点的存储桶名称的测试用例.

任何变通方法或其他解决方案?感谢您的任何反馈.

Rya*_*man 8

事实证明,亚马逊在2012年9月底"升级"了S3上的SSL安全性.这打破了使用亚马逊AWS Java API时在其名称中有句号的任何S3存储桶的访问.

这是不准确的.S3的SSL通配符匹配与2006年S3推出时相同.更有可能的是,AWS Java SDK团队能够对SSL证书进行更严格的验证(好),但最终破坏了与S3的SSL相冲突的存储桶名称证书(坏).

正确的答案是您需要使用路径样式寻址而不是DNS样式寻址.这是解决SSL证书上通配符匹配问题的唯一安全方法.禁用验证可以让您了解中间人攻击.

我目前不知道的是Java SDK是否将其作为可配置选项提供.如果是这样,那就是你的答案.否则,听起来像Java SDK团队说"我们将添加此功能,然后添加集成测试以确保一切正常."


Gra*_*ray 6

亚马逊发布了1.3.22版,解决了这个问题.我已经验证我们的代码现在有效.引用他们的发行说明:

现在可以通过HTTPS再次正确地处理名称包含句点的存储桶.

除了等到亚马逊发布新API之外,我还能看到几个解决方案.

  1. 显然,您可以回滚到1.3.20版本的AWS Java SDK.不幸的是,我需要1.3.21中的一些功能.

  2. 您可以替换org.apache.http.conn.ssl.StrictHostnameVerifier类路径中的.这是一个hack但是我会想要删除所有对Apache http连接的SSL检查.这是适用于我的代码:http://pastebin.com/bvFELdJE

  3. 我最终从AWS源jar下载并构建了自己的包.我将以下近似补丁应用于HttpClientFactory源.

    ===================================================================
    --- src/main/java/com/amazonaws/http/HttpClientFactory.java     (thirdparty/aws)      (revision 20105)
    +++ src/main/java/com/amazonaws/http/HttpClientFactory.java     (thirdparty/aws)    (working copy)
    @@ -93,7 +93,7 @@
    
                            SSLSocketFactory sf = new SSLSocketFactory(
                                    SSLContext.getDefault(),
    -                               SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
    +                               SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    
    Run Code Online (Sandbox Code Playgroud)
  4. 正确的解决方法是从域名桶处理更改为基于路径的处理.

顺便说一句,以下看起来似乎可能有效,但事实并非如此.AWS客户端专门请求STRICT验证者,不使用默认验证者:

SSLSocketFactory.getSystemSocketFactory().setHostnameVerifier(
    SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Run Code Online (Sandbox Code Playgroud)

  • 公平地说,如果您在URL中请求"https://foo.example.com.s3.amazonaws.com/...",则`*.s3.amazonaws.com`不会涵盖该主机名:根据[规格](http://tools.ietf.org/html/rfc2818#section-3.1)("**.a.com匹配foo.a.com但不是foo.a.com),通配符不会在点上传播bar.foo.a.com*").亚马逊可以做的是获得`*.*.*.s3.amazonaws.com`的证书. (4认同)