关于 perl:升级 LWP 后脚本损坏”证书验证失败”

Scripts broke after upgrading LWP "certificate verify failed"

我有很多脚本,其中大部分基于 WWW::Mechanize,它们从可通过 HTTPs 访问的杂项硬件中刮取数据。升级我的大部分 perl 安装及其模块后,所有使用 HTTPS:// 的脚本都因 "certificate verify failed"

而中断

这是因为新版本的 LWP 对证书进行了适当的检查,如果有不匹配的地方,dies

在我的情况下,由于这种情况,预计证书身份验证失败,所以我需要找到一种彻底绕过此检查的方法。


说我想告诉你一件事,我不想让其他人知道。我们会安排一个密码,我会用它来加密消息,然后我会向您发送消息。

如果我不能确定向我提供密码和加密信息的人是你怎么办?那么任何数量的人都可以简单地冒充您,而加密将是徒劳的。直到最近,这还是 LWP 的 HTTPS 支持状态。

现在,LWP 实际上会检查它正在与谁交谈,除非您要求 LWP 像以前那样行事。你可以这样做:

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

如果您想影响脚本中的所有 LWP::UserAgent 实例而不在整个地方指定选项,您可以将以下内容添加到您的脚本中

1
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

或者您可以按如下方式启动您的脚本:

1
PERL_LWP_SSL_VERIFY_HOSTNAME=0 script.pl

最后,如果您希望 LWP 始终不安全,您可以在登录脚本中添加以下内容:

1
export PERL_LWP_SSL_VERIFY_HOSTNAME=0

但是,我不推荐以上任何方法。更好的选择是为您正在与之通信的主机提供证书。 (这相当于在 Firefox 中添加异常,如果您知道我的意思的话。)请参阅 $ua->ssl_opts.

的文档


对我来说,使用:

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

产量

Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client is
deprecated! Please set SSL_verify_mode to SSL_VERIFY_PEER together
with SSL_ca_file|SSL_ca_path for verification. If you really don't
want to verify the certificate and keep the connection open to
Man-In-The-Middle attacks please set SSL_verify_mode explicitly to
SSL_VERIFY_NONE in your application.

使用它并没有给出任何警告:

1
2
3
my $ua = LWP::UserAgent->new(
  ssl_opts => { SSL_verify_mode => 'SSL_VERIFY_NONE'},
);


我在代码前加上:

1
$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;

这导致脚本以干净简单的方式绕过检查。


@ikegami 很好地解释了您为什么不想禁用 SSL 主机名验证,但没有直接提及如何避免它。

如果您使用 CA 签名证书与公共系统通信,则需要将 LWP 指向您的发行版的根证书集合。在基于 Debian 的系统(Ubuntu 等)下,它保存在 /etc/ssl/certs/.

1
2
3
BEGIN {
    $ENV{HTTPS_CA_DIR} = '/etc/ssl/certs'
}

如果您使用自签名证书与您自己的服务器通信,您可以在客户端上保存该证书的副本,并将您的脚本指向该特定文件。

1
2
3
BEGIN {
    $ENV{HTTPS_CA_FILE} = '/path/to/my/server-certificate.crt'
}

您可以在运行脚本之前在环境中设置这些(例如,从您的 shell 中导出它们),或者您可以将设置直接应用到您的 UserAgent 对象。有关详细信息,请参阅 LWP::UserAgent 文档;搜索 ssl_opts(大约在页面的中间)。