Perl LWP: почему IO :: Socket :: SSL использует TLS 1.0, а Net :: SSL использует TLS 1.2? - PullRequest
0 голосов
/ 30 июня 2018

Когда я запускаю следующий код:

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. Сервер допускает только соединения TLS 1.2, так что это имеет смысл.

Wireshark 1

Когда я изменяю свой код, чтобы указать, что клиент должен только использовать TLS 1.2, я получаю тот же ответ.

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

И, фактически, сетевой трафик выглядит одинаково:

Wireshark 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:

Wireshark 3

Как ни странно, analyse-ssl.pl согласовывает TLS 1.2 с IO :: Socket :: SSL:

-- 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 не пытался установить соединение TLS 1.0 с LWP?


  • Perl 5.26.2 MSWin32-x64-multi-thread (Strawberry)
  • OpenSSL 1.1.0h 27 марта 2018
  • LWP 6.34
  • Net :: HTTPS 6.18
  • IO :: Socket :: SSL 2.056
  • Net :: SSL 2,86

Вывод из сценария Штеффена Ульриха:

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

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Так как analyse-ssl.pl работал, а мой тестовый скрипт не работал, когда он указывал на один и тот же сервер, я начал сравнивать их, чтобы выяснить, в чем различия. Одно из основных отличий заключается в том, что analyse-ssl.pl пытается установить соединение с SSL_cipher_list => '', и выясняется, что на самом деле это была проблема.

Изменение моего экземпляра LWP :: UserAgent решило проблему:

my $ua = LWP::UserAgent->new(ssl_opts => {
    verify_hostname => 0,
    SSL_cipher_list => '',
});
0 голосов
/ 30 июня 2018

Это не должно вести себя так, как вы описываете, и на самом деле я не могу воспроизвести вашу проблему с недавно установленной последней версией Strawberry Perl на Win10, то есть с той же версией 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, а какой-то старый OpenSSL 1.0.0 или более старый, который не поддерживает TLS 1.2.

...