LWP HTTPS GET出现连接失败或证书验证失败

4

昨天我在Perl Monks上发布了这个问题,但是每个尝试过的人都成功了(请参见http://www.perlmonks.org/?node_id=909968)。然而,我使用了一个不同的URL,希望简化问题。

我正在尝试通过HTTPS连接到api.betfair.com,他们有一个有效的证书,我已经在我的浏览器中验证过。我正在运行ubuntu,并且有两个版本的Perl。系统自带的5.10.0可以工作,通过perlbrew安装的5.14.0失败了。代码如下:

use LWP::UserAgent; 
use strict;
use warnings;

#$ENV{HTTPS_CA_FILE} = "/usr/share/ca-certificates/cacert.org/cacert.org.crt";

my $ua  = LWP::UserAgent->new; 
my $req = HTTP::Request->new(GET => 'https://api.betfair.com');
my $res = $ua->request($req);

print $res->headers_as_string;
print $res->content;

在系统Perl 5.10.0下运行,它可以正常工作,我会得到以下结果:
Date: Fri, 17 Jun 2011 08:33:04 GMT
Accept-Ranges: bytes
ETag: W/"0-1307353787000"
Content-Length: 0
Content-Type: text/html
Last-Modified: Mon, 06 Jun 2011 09:49:47 GMT
Client-Date: Fri, 17 Jun 2011 08:33:04 GMT
Client-Peer: 84.20.200.10:443
Client-Response-Num: 1
Client-SSL-Cert-Issuer: /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)09/CN=VeriSign Class 3 Secure Server CA - G2
Client-SSL-Cert-Subject: /C=GB/ST=London/L=London/O=The Sporting Exchange Ltd/OU=IS/OU=Terms of use at www.verisign.com/rpa (c)05/CN=*.betfair.com
Client-SSL-Cipher: RC4-MD5
Set-Cookie: NSC_mc-80-qvcbqj.efgbvmu=ffffffff09208c5545525d5f4f58455e445a4a4229a0;expires=Fri, 17-Jun-2011 20:33:05 GMT;path=/;httponly

在 Perl 5.14.0 下运行,我得到以下结果:

Content-Type: text/plain Client-Date: Fri, 17 Jun 2011 08:34:30 GMT Client-Warning: Internal response Can't connect to api.betfair.com:443

如果我取消 HTTPS_CA_FILE 的注释并在 5.14.0 中重新运行,我会得到:

Content-Type: text/plain
Client-Date: Fri, 17 Jun 2011 08:35:09 GMT
Client-Warning: Internal response
Can't connect to api.betfair.com:443 (certificate verify failed)

LWP::Protocol::https::Socket: SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed at /home/martin/perl5/perlbrew/perls/perl-5.14.0/lib/site_perl/5.14.0/LWP/Protocol/http.pm line 51.

我已安装版本为20110409的Mozilla::CA。Mozilla::CA::SSL_ca_file()返回“/home/martin/perl5/perlbrew/perls/perl-5.14.0/lib/site_perl/5.14.0/Mozilla/CA/cacert.pem”,并且我可以读取它。我在Perl 5.14.0中使用LWP 6.02,在Perl 5.10.0中使用5.836。我读到设置HTTPS_DEBUG=1应该输出一些调试信息,但只有在使用Perl 5.10.0而不是5.14.0时才会这样做(对我来说)。
我不是SSL专家,但我尝试了一些我找到的东西,它们只让我更加困惑:
openssl verify -verbose -CAfile /home/martin/perl5/perlbrew/perls/perl-5.14.0/lib/site_perl/5.14.0/Mozilla/CA/cacert.pem < /dev/null
unable to load certificate
10888:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:647:Expecting: TRUSTED CERTIFICATE

openssl s_client -CAfile /usr/local/share/perl/5.10.0/Mozilla/CA/cacert.pem -connect api.betfair.com:443 < /dev/null
CONNECTED(00000003)
depth=1 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)09/CN=VeriSign Class 3 Secure Server CA - G2
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=GB/ST=London/L=London/O=The Sporting Exchange Ltd/OU=IS/OU=Terms of use at www.verisign.com/rpa (c)05/CN=*.betfair.com
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)09/CN=VeriSign Class 3 Secure Server CA - G2
 1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)09/CN=VeriSign Class 3 Secure Server CA - G2
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network
---
Server certificate
-----BEGIN CERTIFICATE-----
certificate snipped
sg==
-----END CERTIFICATE-----
subject=/C=GB/ST=London/L=London/O=The Sporting Exchange Ltd/OU=IS/OU=Terms of use at www.verisign.com/rpa (c)05/CN=*.betfair.com
issuer=/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)09/CN=VeriSign Class 3 Secure Server CA - G2
---
No client certificate CA names sent
---
SSL handshake has read 3068 bytes and written 303 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 1024 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-MD5
    Session-ID: 81802384A47AF45D2D809A2D10041A4E0B4B4DD821507569216A199ED467B207
    Session-ID-ctx: 
    Master-Key: 50DEC11CD2FA57E9BFA95B0156905D2717A79F333A2028FCCCB0F1C32A6B35202A958CEF24D3D2332A00CDCD158B40FB
    Key-Arg   : None
    Start Time: 1308304989
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
DONE

更新:我以为是因为我设置了PERL_UNICODE=SAL,但是取消设置并不能解决问题。

更新:版本: Linux ubuntu 10.10代号maverick openssl 0.9.80(我相信是我的ubuntu发行版最新的)


我敢打赌你没有像http://stackoverflow.com/q/5639803#5654982中那样的中间证书。 - daxim
仅供参考,将PERL_LWP_SSL_VERIFY_HOSTNAME环境变量设置为0可以绕过证书验证。当然不建议这样做,但在紧急情况下很方便。 - Tim Bunce
同意Tim的看法,但在我的系统上它没有起作用,现在仍然无法正常工作。同时,在我的系统上执行$ua->ssl_opts(verify_hostname => 0)也不起作用。我仍在努力找出原因。 - bohica
1个回答

2
$ openssl s_client -connect api.betfair.com:443 < /dev/null > api.betfair.com.pem
$ openssl x509 -in api.betfair.com.pem -issuer_hash
eb99629b

好的,你说的是相同的中间证书0xeb99629b,我之前也看到过其他人遗失这个证书,详见上方评论以获取该证书的详细信息。

顺带一提,你正在运行哪个版本的OpenSSL和ca-certificates?你的操作系统版本和供应商是什么?


更新了OpenSSL版本和系统。不确定如何查找ca-certificates版本。大约一个月前在http://www.martin-evans.me.uk/node/95上遇到了与Facebook相同的问题,但是以不同的方式解决了它。感谢Daxim - 我知道你会诊断出这个问题 - 差点直接问你。 - bohica
openssl s_client -CAfile cert.pm -connect api.betfair.com:443 < /dev/null 现在可以工作了。但是我还没有让 Perl 正常工作,仍在努力中。 - bohica
下载您指向的证书。sudo cp cert.pm /etc/ssl/certs/Verisign_Class_3_Secure_Server_CA_G2.pem; sudo c_rehash; perl ca2.pl仍然失败-相同的问题。在/etc/ssl/certs中的符号链接为4d241d64.0 -> Verisign_Class_3_Secure_Server_CA_G2.pem。 - bohica
指向系统证书是有效的 - 感谢并点赞。虽然这是一个非常烦人的问题,但我希望我能确定问题出在哪里,这样我就可以报告它了。 - bohica
这个问题涉及多个方面(如果不考虑 Perl 的文化倾向于希望取悦所有人以及 PKI 通过 CA 形成的一种完全糟糕的局面),不可能只通过简单的报告来解决。请访问 YAPC::EU,我将提交一份演讲。 - daxim
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接