Crypt-SSLeay 无法验证主机名

Dmi*_*nyy 1 perl ssl gentoo

我根本不是 Perl 人。但在某些情况下,我必须在新的 gentoo 服务器上部署 perl 脚本。脚本在另一个人配置的其他几个服务器上运行良好。所以我自己安装了一台新服务器,并且某些软件包有不同的版本。由于给定的 perl 脚本,我遇到了一个问题:

来自 Crypt-SSLeay 的 Net::SSL 无法验证主机名;安装 IO::Socket::SSL 或通过将 PERL_LWP_SSL_VERIFY_HOSTNAME 环境变量设置为 0 来关闭验证

其实已经安装好了。

perl -MIO::Socket::SSL -e 'print "$IO::Socket::SSL::VERSION\n"' 2.024

为什么它看不到安装的模块。我可以在新服务器上做些什么来解决问题而无需修改脚本?版本差异有那么重要吗?新服务器 Perl 版本:5.24.0 旧服务器 Perl 版本:5.22.1

新服务器:

perl -v

这是为 x86_64-linux 构建的 perl 5, version 24, subversion 0 (v5.24.0)

perl -MCrypt::SSLeay -e '打印“$Crypt::SSLeay::VERSION\n”'

0.72

perl -MIO::Socket::SSL -e '打印“$IO::Socket::SSL::VERSION\n”'

2.024

环境 | grep PERL_LWP_SSL_VERIFY_HOSTNAME

旧服务器:perl -v

这是为 x86_64-linux 构建的 perl 5, version 22, subversion 1 (v5.22.1)

network6 ~ # perl -MCrypt::SSLeay -e 'print "$Crypt::SSLeay::VERSION\n"'

0.72

network6 ~ # perl -MIO::Socket::SSL -e 'print "$IO::Socket::SSL::VERSION\n"'

2.012

环境 | grep PERL_LWP_SSL_VERIFY_HOSTNAME

ike*_*ami 5

选择可能会受到程序中完全不相关的部分的影响。我建议在程序顶部附近添加以下内容:

use IO::Socket::SSL;
Run Code Online (Sandbox Code Playgroud)

或者,在启动程序的过程中将 var 设置PERL_NET_HTTPS_SSL_SOCKET_CLASSIO::Socket::SSL

export PERL_NET_HTTPS_SSL_SOCKET_CLASS=IO::Socket::SSL
Run Code Online (Sandbox Code Playgroud)
  • 如果您的程序现在抛出异常,这可能就是使用 Net::SSL 的原因。

    解决方案:解决该错误,或​​解决安全性较低的 Net::SSL(需要将 env var 设置PERL_LWP_SSL_VERIFY_HOSTNAME0)。

  • 如果您的程序现在运行良好,则 Net::SSL 正在您程序的其他地方加载,这会影响决策过程。

    解决方案:继续使用两种解决方案之一。


详细版

该消息来自 Net::HTTPS,LWP::Protocol::https 使用它,LWP::UserAgent 和 LWP::Simple(因此 WWW::Mechanize)使用它。

以下是 Net::HTTPS 用于确定使用哪个 SSL 类的过程:

package Net::HTTPS;

use vars qw( $SSL_SOCKET_CLASS );

# Figure out which SSL implementation to use
if ($SSL_SOCKET_CLASS) {
    # somebody already set it
}
elsif ($SSL_SOCKET_CLASS = $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS}) {
    unless ($SSL_SOCKET_CLASS =~ /^(IO::Socket::SSL|Net::SSL)\z/) {
        die "Bad socket class [$SSL_SOCKET_CLASS]";
    }
    eval "require $SSL_SOCKET_CLASS";
    die $@ if $@;
}
elsif ($IO::Socket::SSL::VERSION) {
    $SSL_SOCKET_CLASS = "IO::Socket::SSL"; # it was already loaded
}
elsif ($Net::SSL::VERSION) {
    $SSL_SOCKET_CLASS = "Net::SSL";
}
else {
    eval { require IO::Socket::SSL; };
    if ($@) {
        my $old_errsv = $@;
        eval {
            require Net::SSL;  # from Crypt-SSLeay
        };
        if ($@) {
            $old_errsv =~ s/\s\(\@INC contains:.*\)/)/g;
            die $old_errsv . $@;
        }
        $SSL_SOCKET_CLASS = "Net::SSL";
    }
    else {
        $SSL_SOCKET_CLASS = "IO::Socket::SSL";
    }
}
Run Code Online (Sandbox Code Playgroud)

一般来说,如果安装了 Net::HTTPS 将使用 IO::Socket::SSL,否则使用 Net::SSL。

一种可能会被意外覆盖的方法是在加载 Net::HTTPS ( elsif ($Net::SSL::VERSION))之前加载 Net::SSL 。

# Causes the "elsif ($Net::SSL::VERSION)" path to be taken
use Net::SSL;
Run Code Online (Sandbox Code Playgroud)

换句话说,选择可能会受到程序其他部分的影响。

这可以通过在加载 Net::HTTPS 之前加载 IO::Socket::SSL 或通过在启动程序的过程中设置 env varPERL_NET_HTTPS_SSL_SOCKET_CLASS来抵消IO::Socket::SSL

因此,请尝试将以下内容添加到程序的顶部:

# Causes the "elsif ($IO::Socket::SSL::VERSION)" path to be taken
use IO::Socket::SSL;
Run Code Online (Sandbox Code Playgroud)

或者尝试在启动程序的过程中执行以下操作:

# Causes the "elsif ([...]$ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS})" path to be taken
export PERL_NET_HTTPS_SSL_SOCKET_CLASS=IO::Socket::SSL
Run Code Online (Sandbox Code Playgroud)