【问题标题】:WWW::Mechanize SSL connect attempt failed for https getWWW::Mechanize SSL 连接尝试失败,用于 https 获取
【发布时间】:2018-06-16 06:27:27
【问题描述】:

我正在尝试使用 WWW::Mechanize 检索网页,但由于 SSL 连接错误而失败。我该如何解决这个问题?我在 Windows 10 x64 上运行 ActivePerl 5.20.2。

这是我执行的脚本:

perl -MIO::Socket::SSL=debug4 -MWWW::Mechanize -e 'WWW::Mechanize->new()->get("https://fundresearch.fidelity.com/mutual-funds/fees-and-prices/316343201")'

输出如下:

DEBUG: .../IO/Socket/SSL.pm:2649: new ctx 98842176
DEBUG: .../IO/Socket/SSL.pm:562: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:564: socket connected
DEBUG: .../IO/Socket/SSL.pm:586: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:619: using SNI with hostname fundresearch.fidelity.com
DEBUG: .../IO/Socket/SSL.pm:654: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:673: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:686: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:689: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:699: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:709: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:729: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:686: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2552: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:2505: ok=0 cert=102327360
DEBUG: .../IO/Socket/SSL.pm:689: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:692: SSL connect attempt failed

DEBUG: .../IO/Socket/SSL.pm:692: local error: SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:695: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
DEBUG: .../lib/Net/HTTPS.pm:69: ignoring less severe local error 'IO::Socket::IP configuration failed', keep 'SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed'
DEBUG: .../IO/Socket/SSL.pm:2682: free ctx 98842176 open=98842176
DEBUG: .../IO/Socket/SSL.pm:2687: free ctx 98842176 callback
DEBUG: .../IO/Socket/SSL.pm:2694: OK free ctx 98842176
Error GETing https://fundresearch.fidelity.com/mutual-funds/fees-and-prices/316343201: Can't connect to fundresearch.fidelity.com:443 at -e line 1.

我能够使用 curl 成功检索网页。

【问题讨论】:

  • 你能得到任何其他的 https 网址吗?你使用的是什么版本的 WWW::Mechanize 和 IO::Socket::SSL?
  • 你可以用谷歌搜索实际的错误信息。 (为什么在忽略调试输出的情况下启用调试?)例如参见stackoverflow.com/questions/17084886/…
  • Schwern,我可以访问其他 https URL。比如访问google.com成功。

标签: perl www-mechanize


【解决方案1】:

TL;DR:升级 Perl 或至少升级 Mozilla::CA 模块或使用 SSL_ca_file 与您自己的信任库。


我怀疑问题是因为您使用的是旧版本的 Perl,特别是该 Perl 中包含的旧版本的 Mozilla::CA 模块。查看此站点的证书链(例如SSLLabs),您会发现它如下所示:

[0] CN=fundresearch.fidelity.com
[1] CN=Entrust Certification Authority - L1K
[2] CN=Entrust Root Certification Authority - G2   -- selfsigned

此信任链中的最后一个证书是自签名的,即此证书的信任来自证书本身。这是服务器的明显错误配置,这就是验证信任链时忽略此证书的原因。

CN=Entrust Certification Authority - L1K 的颁发者 CA 是 CN=Entrust Root Certification Authority - G2,即服务器发送但被忽略的证书,因为不应仅基于服务器发送的信任。这意味着本地信任存储中需要有此根 CA 的实例。

现代浏览器和操作系统在信任库中有这个 CA,这就是为什么您可以使用浏览器访问此站点的原因。但是,WWW::Mechanize(基于 LWP::UserAgent)不使用系统信任存储(至少在 Windows 上)。相反,信任库由 Mozilla::CA 模块提供,该模块不时从 Mozilla(即 Firefox)获取信任库的副本。

根据您的 Perl 发行版本,您可能使用 Mozilla::CA 的 20141217 版本。此版本尚未包含受信任的 CA Entrust Root Certification Authority - G2。此 CA 仅包含在下一个 version 20150826 中。由于 CA 不被认为是受信任的,因此验证将失败。

有几种可能的修复方法。

  • 一种是升级 Perl 的版本。这可能是最好的选择,因为这还包括在处理多个可能的信任路径时对 OpenSSL 的修复 - 这是您可能在其他站点遇到的问题(有关详细信息,请参阅 here)。
  • 另一种方法是只升级 Mozilla::CA 模块。但是,如果您仍然使用旧的 Perl,而上面描述的 OpenSSL 问题没有得到解决,这实际上可能会导致某些网站出现问题。
  • 或者您可以将the missing certificate 添加到您的cacert.pem(Mozilla::CA 提供的那个)。
  • 最后,您可以使用 ssl_optsSSL_ca_file 来设置您自己的信任库,其中包括缺少的 CA 证书。

【讨论】:

    【解决方案2】:

    Works For Me™ 使用 IO::Socket::SSL 2.052、WWW::Mechanize 1.86 和 Net::SSLeay 1.80。我怀疑您需要升级 Net::SSLeay。我建议升级所有这些。

    差异从这里开始。您认为证书不正确。

    DEBUG: .../IO/Socket/SSL.pm:2552: did not get stapled OCSP response
    DEBUG: .../IO/Socket/SSL.pm:2505: ok=0 cert=102327360
    

    但我的确实如此。更详细的输出是因为我升级了 Net::SSLeay。

    DEBUG: .../IO/Socket/SSL.pm:2722: did not get stapled OCSP response
    DEBUG: .../IO/Socket/SSL.pm:2675: ok=1 [2] /C=US/O=Entrust, Inc./OU=See www.entrust.net/legal-terms/OU=(c) 2009 Entrust, Inc. - for authorized use only/CN=Entrust Root Certification Authority - G2/C=US/O=Entrust, Inc./OU=See www.entrust.net/legal-terms/OU=(c) 2009 Entrust, Inc. - for authorized use only/CN=Entrust Root Certification Authority - G2
    

    该过程由 Net::SSLeay 处理。您的 Net::SSLeay 版本可能与您的 OpenSSL C 库不兼容。自从 ActivePerl 5.20.2 出来之后,就有了a lot of fixes for compatibility with OpenSSL 1.1

    【讨论】:

    • “这表示它会返回内存地址的错误。” - 不,它表示旧版本的 IO::Socket::SSL。在 2.018(2015 年 8 月发布)之前,它只在此处显示内存地址。见github.com/noxxi/p5-io-socket-ssl/commit/…
    • @SteffenUllrich 谢谢,我已经消除了这种猜测。
    • 谢谢施韦恩。问题确实出在库版本上。我将这 3 个软件包升级到 ActivePerl 提供的最新版本,这解决了问题。
    • @scorpio:感谢 Schwern 的快速回答,为您解决了问题。如果您对潜在问题的详细信息以及修复的其他选项感兴趣,您可以查看my analysis
    猜你喜欢
    • 2020-09-14
    • 1970-01-01
    • 2014-03-07
    • 2014-12-25
    • 2015-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多