代码之家  ›  专栏  ›  技术社区  ›  Matt Jacob

perl lwp:为什么io::socket::ssl使用tls 1.0,而net::ssl使用tls 1.2?

  •  1
  • Matt Jacob  · 技术社区  · 8 年前

    当我运行以下代码时:

    use strict;
    使用警告;
    
    使用io::socket::ssl;
    使用lwp::useragent;
    
    我的$ua=lwp::useragent->新建(ssl_Opts=>){
    验证“主机名”=>0,
    })(二)
    
    my$res=$ua->get('https://internal.foo.bar.baz:20002');
    将$res->打印为\u string;
    

    我从LWP得到一个内部错误:

    500 can't connect to internal.foo.bar.baz:20002(bad file descriptor)
    内容类型:文本/普通
    客户日期:2018年6月29日星期五21:23:13格林尼治标准时间
    客户端警告:内部响应
    
    无法连接到内部.foo.bar.baz:20002(错误的文件描述符)
    
    D:/草莓/perl/site/lib/lwp/protocol/http.pm第50行的文件描述符错误。
    

    网络流量显示它是一个“客户机hello”,然后服务器立即重置,协议是tlsv1。服务器只允许TLS 1.2连接,因此这是有意义的。

    当我更改代码以指定客户端只应使用tls 1.2时,我得到相同的响应。

    my$ua=lwp::useragent->新建(ssl_Opts=>){
    验证“主机名”=>0,
    ssl_version=>'tlsv1_2',
    })(二)
    

    事实上,网络流量看起来是相同的:

    当我显式使用net::ssl而不是io::socket::ssl时:

    use strict;
    使用警告;
    
    使用net::ssl;
    使用lwp::useragent;
    
    我的$ua=lwp::useragent->新建(ssl_Opts=>){
    验证“主机名”=>0,
    })(二)
    
    my$res=$ua->get('https://internal.foo.bar.baz:20002');
    将$res->打印为\u string;
    

    工作原理:

    http/1.1 401 unauthorized
    日期:2018年6月29日星期五21:33:35格林尼治标准时间
    服务器:Kestrel
    客户日期:2018年6月29日星期五21:33:37格林尼治标准时间
    客户端对等端:**.*.*.*.209:20002
    客户端响应数:1
    客户端SSL证书颁发者:********************************************************
    客户端ssl证书主题:********************************************************************************
    客户端SSL密码:ecdhe-rsa-aes256-sha384
    客户端SSL套接字类:net::ssl
    客户端SSL警告:对等证书未验证
    客户端传输编码:分块
    客户端警告:缺少身份验证头
    严格的运输安全:最大年龄=2592000
    x-powered-by:asp.net
    

    协议正确设置为tlsv1.2:。

    奇怪的是,analyze ssl.plnegotiates tls 1.2 with io::socket::ssl:。

    --internal.foo.bar.baz port 20002
    你看!使用证书验证(默认)->SSL连接尝试失败错误:1416F086:SSL例程:tls_process_server_certificate:证书验证失败
    *最大SSL版本:tlsv1_2(sslv23)
    *支持使用握手和首选密码的SSL版本:
    *握手协议密码
    *SSLv23 TLSV1_2 ECDHE-RSA-AES256-SHA384
    *tlsv1_2 tlsv1_2 ecdhe-rsa-aes256-sha384
    *tlsv1_1失败:SSL连接尝试失败
    *TLSV1失败:SSL连接尝试失败
    *密码顺序:未知
    *支持SNI:没有SNI证书验证失败
    *已验证证书:失败:SSL连接尝试失败错误:1416F086:SSL例程:tls_process_server_certificate:证书验证失败
    *链在***.**.**.209上
    *[0/0]位=2048,ocsp_uri=,,*******************************************************************************************************************
    *[1/1]位=2048,ocsp_uri=,********************************************************
    *[2/2]位=2048,ocsp_uri=,***********************************************************************
    
    
    

    如何防止IO::Socket::SSL尝试从LWP建立TLS 1.0连接?


    2 回复  |  直到 7 年前
        1
  •  3
  •   Steffen Ullrich    8 年前

    它不应该像您描述的那样运行,事实上,我不能用Win10上新安装的最新草莓Perl来重现您的问题,即使用您使用的相同Perl版本。您的第一个代码与目的地保持不变,并使用 openssl s_server -www... 作为目标。它与TLS 1.2完美连接,数据包捕获也清楚地显示了TLS 1.2。

    我的猜测是您的设置出了问题:可能是系统上的一些旧的Perl安装仍在干扰或类似的问题。这个混乱的设置可能是特定于自运行以来如何运行脚本的 analyze.pl 没有这样的问题。因此,我建议实际检查脚本中实际使用的内容,即

    use strict;
    use warnings;
    use IO::Socket::SSL;
    use LWP::UserAgent;
    use LWP::Protocol::https;
    
    printf("openssl version compiled=0x%0x linked=0x%0x -- %s\n",
        Net::SSLeay::OPENSSL_VERSION_NUMBER(),
        Net::SSLeay::SSLeay(),
        Net::SSLeay::SSLeay_version(0));
    printf("IO::Socket::SSL version=%s\n",$IO::Socket::SSL::VERSION);
    printf("LWP::UserAgent version=%s\n",$LWP::UserAgent::VERSION);
    printf("LWP::Protocol::https version=%s\n",$LWP::Protocol::https::VERSION);
    printf("Net::https version=%s\n",$Net::https::VERSION);
    
    my $ua = LWP::UserAgent->new(ssl_opts => {
        verify_hostname => 0,
    });
    
    my $res = $ua->get('https://internal.foo.bar.baz:20002');
    print $res->as_string;
    

    这给了我一个新的设置略为不同的版本的LWP(6.33对6.34)和NET::HTTPS(6.17对6.18),但其余适合您的版本。但重要的部分可能是代码实际加载的OpenSSL版本。我猜在您的特定脚本设置中,它使用的不是您期望的openssl 1.1.0,而是一些旧的openssl1.0.0或更旧的,不支持tls 1.2。

        2
  •  1
  •   Matt Jacob    7 年前

    由于analyze-ssl.pl工作正常,并且我的测试脚本在指向同一个服务器时没有工作,所以我开始比较它们,以找出它们之间的区别。其中一个主要区别是analyze-ssl.pl尝试与 SSL_cipher_list => '' 事实上,这就是问题所在。

    更改我的lwp::useragent实例解决了以下问题:

    my $ua = LWP::UserAgent->new(ssl_opts => {
        verify_hostname => 0,
        SSL_cipher_list => '',
    });
    
    推荐文章