如何使用HttpClient的在使用SSL证书,无论多么“糟糕”是

布拉德·帕克斯:

我使用的Apache的HttpClient的网络爬虫是只爬行公共数据。

我想它能够以无效证书,爬行网站无论多么无效。

我的履带不会传递任何用户名,密码等,并没有任何敏感数据被发送或接收。

对于这种使用情况下,我会抓取http网站的版本,如果它存在,但有时它当然不是。

怎么可以这样做与Apache的HttpClient的

我试着像一些建议这一个,但他们还是失败了一些无效的证书,例如:

failed for url:https://dh480.badssl.com/, reason:java.lang.RuntimeException: Could not generate DH keypair
failed for url:https://null.badssl.com/, reason:Received fatal alert: handshake_failure
failed for url:https://rc4-md5.badssl.com/, reason:Received fatal alert: handshake_failure
failed for url:https://rc4.badssl.com/, reason:Received fatal alert: handshake_failure
failed for url:https://superfish.badssl.com/, reason:Connection reset

请注意,我想这与我的$JAVA_HOME/jre/lib/security/java.security文件的jdk.tls.disabledAlgorithms设置为无,以保证这不是一个问题,我还是得到像上述故障。

user3474985:

简短的回答你的问题,这是特别信任所有证书,将使用TrustAllStrategy,做这样的事情:

SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
sslContextBuilder.loadTrustMaterial(null, new TrustAllStrategy());
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
        sslContextBuilder.build());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
        socketFactory).build();

但是...一个无效的证书可能不是你的主要问题。一个handshake_failure可能会因多种原因,但在我的经验,这通常是由于SSL / TLS版本不匹配或密码套件协商失败。这并不意味着该SSL证书是“坏”的,它只是在服务器和客户端之间的不匹配。你可以清楚地看到握手使用Wireshark之类的工具(没有更多介绍

虽然Wireshark的能极大的看到它的失败,它不会帮助你拿出一个解决方案。每当我已经走了关于过去,我调试handshake_failures发现这个工具特别有用:https://testssl.sh/

您可以指向该脚本在任何发生故障的网站,以了解更多关于什么协议可对目标和你的客户端需要支持,以建立成功的握手。它也将打印有关证书的信息。

例如(仅示出2 testssl.sh的输出的部分):

./testssl.sh www.google.com
....
 Testing protocols (via sockets except TLS 1.2, SPDY+HTTP2) 

 SSLv2               not offered (OK)
 SSLv3               not offered (OK)
 TLS 1               offered
 TLS 1.1             offered
 TLS 1.2             offered (OK)
 ....
Server Certificate #1
   Signature Algorithm          SHA256 with RSA
   Server key size              RSA 2048 bits
   Common Name (CN)             "www.google.com"
   subjectAltName (SAN)         "www.google.com" 
   Issuer                       "Google Internet Authority G3" ("Google Trust Services" from "US")
   Trust (hostname)             Ok via SAN and CN (works w/o SNI)
   Chain of trust               "/etc/*.pem" cannot be found / not readable
   Certificate Expiration       expires < 60 days (58) (2018-10-30 06:14 --> 2019-01-22 06:14 -0700)
 ....
 Testing all 102 locally available ciphers against the server, ordered by encryption strength 
(Your /usr/bin/openssl cannot show DH/ECDH bits)

Hexcode  Cipher Suite Name (OpenSSL)       KeyExch.  Encryption Bits
------------------------------------------------------------------------
xc030   ECDHE-RSA-AES256-GCM-SHA384       ECDH       AESGCM    256       
xc02c   ECDHE-ECDSA-AES256-GCM-SHA384     ECDH       AESGCM    256       
xc014   ECDHE-RSA-AES256-SHA              ECDH       AES       256       
xc00a   ECDHE-ECDSA-AES256-SHA            ECDH       AES       256       
x9d     AES256-GCM-SHA384                 RSA        AESGCM    256       
x35     AES256-SHA                        RSA        AES       256       
xc02f   ECDHE-RSA-AES128-GCM-SHA256       ECDH       AESGCM    128       
xc02b   ECDHE-ECDSA-AES128-GCM-SHA256     ECDH       AESGCM    128       
xc013   ECDHE-RSA-AES128-SHA              ECDH       AES       128       
xc009   ECDHE-ECDSA-AES128-SHA            ECDH       AES       128       
x9c     AES128-GCM-SHA256                 RSA        AESGCM    128       
x2f     AES128-SHA                        RSA        AES       128       
x0a     DES-CBC3-SHA                      RSA        3DES      168 

因此,使用这个输出我们可以看到,如果您的客户端只支持SSLv3的,握手会失败,因为该协议没有服务器支持。该协议的产品是不可能的问题,但您可以通过双击得到启用的协议列表中选中你的Java客户端支持。你可以提供一个重写的实现从上面的代码片断的SSLConnectionSocketFactory来获得的启用/支持的协议和密码套件列表如下(SSLSocket的):

class MySSLConnectionSocketFactory extends SSLConnectionSocketFactory {
    @Override
    protected void prepareSocket(SSLSocket socket) throws IOException {
        System.out.println("Supported Ciphers" + Arrays.toString(socket.getSupportedCipherSuites()));
        System.out.println("Supported Protocols" + Arrays.toString(socket.getSupportedProtocols()));
        System.out.println("Enabled Ciphers" + Arrays.toString(socket.getEnabledCipherSuites()));
        System.out.println("Enabled Protocols" + Arrays.toString(socket.getEnabledProtocols()));
    }
}

我经常遇到handshake_failure时,有一个密码套件协商失败。为了避免这种错误,所支持的加密套件的客户的名单必须至少包含一个匹配的密码套件从支持的加密套件的服务器的列表。

如果服务器需要基于AES256加密套件,你可能需要的Java加密扩展(JCE)。这些库是国家限制,它们可能无法提供给美国以外的人。

更多关于密码的限制,如果你有兴趣:https://crypto.stackexchange.com/questions/20524/why-there-are-limitations-on-using-encryption-with-keys-beyond-certain-length

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章