【问题标题】:Perl LWP: why does IO::Socket::SSL use TLS 1.0, while Net::SSL uses TLS 1.2?Perl LWP:为什么 IO::Socket::SSL 使用 TLS 1.0,而 Net::SSL 使用 TLS 1.2?
【发布时间】:2018-12-09 03:32:11
【问题描述】:

当我运行以下代码时:

use strict;
use warnings;

use IO::Socket::SSL;
use LWP::UserAgent;

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 收到一个内部错误:

500 Can't connect to internal.foo.bar.baz:20002 (Bad file descriptor)
Content-Type: text/plain
Client-Date: Fri, 29 Jun 2018 21:23:13 GMT
Client-Warning: Internal response

Can't connect to internal.foo.bar.baz:20002 (Bad file descriptor)

Bad file descriptor at D:/strawberry/perl/site/lib/LWP/Protocol/http.pm line 50.

网络流量显示它是“客户端问候”,随后服务器立即重置,并且协议为 TLSv1.1。服务器只允许 TLS 1.2 连接,所以这是有道理的。

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

my $ua = LWP::UserAgent->new(ssl_opts => {
    verify_hostname => 0,
    SSL_version => 'TLSv1_2',
});

事实上,网络流量看起来是一样的:

当我明确使用 Net::SSL 而不是 IO::Socket::SSL:

use strict;
use warnings;

use Net::SSL;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new(ssl_opts => {
    verify_hostname => 0,
});

my $res = $ua->get('https://internal.foo.bar.baz:20002');
print $res->as_string;

有效:

HTTP/1.1 401 Unauthorized
Date: Fri, 29 Jun 2018 21:33:35 GMT
Server: Kestrel
Client-Date: Fri, 29 Jun 2018 21:33:37 GMT
Client-Peer: ***.**.**.209:20002
Client-Response-Num: 1
Client-SSL-Cert-Issuer: *******************************************************
Client-SSL-Cert-Subject: **************************************************************************
Client-SSL-Cipher: ECDHE-RSA-AES256-SHA384
Client-SSL-Socket-Class: Net::SSL
Client-SSL-Warning: Peer certificate not verified
Client-Transfer-Encoding: chunked
Client-Warning: Missing Authenticate header
Strict-Transport-Security: max-age=2592000
X-Powered-By: ASP.NET

并且协议正确设置为 TLSv1.2:

奇怪的是,analyze-ssl.pl 与 IO::Socket::SSL: 协商 TLS 1.2:

-- internal.foo.bar.baz port 20002
 ! using certificate verification (default) -> SSL connect attempt failed error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
 * maximum SSL version  : TLSv1_2 (SSLv23)
 * supported SSL versions with handshake used and preferred cipher(s):
   * handshake protocols ciphers
   * SSLv23    TLSv1_2   ECDHE-RSA-AES256-SHA384
   * TLSv1_2   TLSv1_2   ECDHE-RSA-AES256-SHA384
   * TLSv1_1   FAILED: SSL connect attempt failed
   * TLSv1     FAILED: SSL connect attempt failed
 * cipher order by      : unknown
 * SNI supported        : certificate verify fails without SNI
 * certificate verified : FAIL: SSL connect attempt failed error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
 * chain on ***.**.**.209
   * [0/0] bits=2048, ocsp_uri=, *******************************************************************************************************
   * [1/1] bits=2048, ocsp_uri=, *******************************************************
   * [2/2] bits=2048, ocsp_uri=, ****************************************************************

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


  • Perl 5.26.2 MSWin32-x64-多线程(草莓)
  • OpenSSL 1.1.0h 2018 年 3 月 27 日
  • LWP 6.34
  • Net::HTTPS 6.18
  • IO::Socket::SSL 2.056
  • Net::SSL 2.86

Steffen Ullrich 脚本的输出:

openssl version compiled=0x1010008f linked=0x1010008f -- OpenSSL 1.1.0h  27 Mar 2018
IO::Socket::SSL version=2.056
LWP::UserAgent version=6.34
LWP::Protocol::https version=6.07
Net::HTTPS version=6.18

【问题讨论】:

    标签: perl ssl lwp io-socket-ssl


    【解决方案1】:

    它不应该像您描述的那样运行,事实上我无法在 Win10 上使用新安装的最新 Strawberry 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,而是一些不支持 TLS 1.2 的旧 OpenSSL 1.0.0 或更早版本。

    【讨论】:

      【解决方案2】:

      由于analyze-ssl.pl 有效并且我的测试脚本在指向同一台服务器时没有,我开始比较它们以找出差异所在。主要区别之一是analyze-ssl.pl 尝试与SSL_cipher_list => '' 建立连接,事实证明这实际上是问题所在。

      更改我的 LWP::UserAgent 实例化解决了问题:

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

      【讨论】:

      • 您的更改实质上使 IO::Socket::SSL 提供了广泛的密码,而不仅仅是一小部分密码,这些密码是按照浏览器的功能建模的,并且可以解决一些损坏的问题无法处理更大密码集的服务器。看起来您的服务器只支持非常有限数量的密码。因此,您也不太可能在与其他客户端一起使用此服务器时遇到问题。
      • @SteffenUllrich 因为它只是用于内部系统之间的 API 调用,我可以接受。默认情况下,相同的请求在 cURL 和 SoapUI 中有效,因此它们也必须提供更多密码。这样做对吗?不,但就像我说的,这仅供内部使用。
      • @SteffenUllrich 原来,服务器上的组策略修改了密码套件顺序,真的把事情弄得一团糟(我原来问题的基础)。恢复到 Server 2016 默认值解决了根本问题,并使一切都符合 HTTP/2 和 TLS 1.2。万岁,企业! ◔_◔
      • 再想一想:除了您所显示的更改之外,肯定还有其他内容已更改。密码列表上的更改不会神奇地更改客户端提供的 TLS 版本。因此,您之前一定是在运行不同的代码,这些代码以某种方式通过支持 TLS 1.2 的 OpenSSL 强制执行 TLS 1.0。或者代码使用仅支持 TLS 1.0 的旧版本 OpenSSL 库运行。
      • 我刚刚通过TLS 1.2 enforcement 受到了打击,不过库是从 2018 年开始的 - 修复成功了!供参考:openssl version compiled=0x1000109f linked=0x1000210f -- OpenSSL 1.0.2p-fips 14 Aug 2018 | IO::Socket::SSL version=1.962 | LWP::UserAgent version=6.05 | LWP::Protocol::https version=6.04 | Net::HTTPS version=6.04
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-23
      • 2019-03-26
      • 2016-09-20
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      • 2014-12-12
      相关资源
      最近更新 更多