简体   繁体   English

升级 LWP “证书验证失败”后脚本中断

[英]Scripts broke after upgrading LWP "certificate verify failed"

I have a lot of scripts, most of them based around WWW::Mechanize that scrape data off of misc hardware that is accessible via HTTPs.我有很多脚本,其中大多数基于WWW::Mechanize ,它从可通过 HTTPs 访问的杂项硬件中刮取数据。 After upgrading most of my perl installation and its modules, all scripts using HTTPS:// broke because of "certificate verify failed"升级我的大部分 perl 安装及其模块后,所有使用 HTTPS:// 的脚本都因"certificate verify failed"而中断

This is a result of the fact that the newer versions of LWP does a proper check on the certificate and dies if something doesn't match.这是因为较新版本的 LWP 对证书进行了适当的检查,如果不匹配dies

In my case, the failed certificate authentication is expected due to the circumstances, so i needed to find a way of cleanly circumventing this check.就我而言,由于这种情况,预计证书身份验证会失败,因此我需要找到一种彻底规避此检查的方法。

Say I want to tell you something, and I don't want anyone else to know it.假设我想告诉你一些事情,我不想让其他人知道。 We'd arrange a password, and I'd use it to encrypt the message, then I'd send you the message.我们会安排一个密码,我会用它来加密消息,然后我会将消息发送给你。

What if I didn't make sure the person to whom I gave the password and encrypted message was you?如果我不能确定向我提供密码和加密信息的人是你怎么办? Then any number of people could simply impersonate you and the encryption would be for naught.那么任何数量的人都可以简单地冒充您,而加密将是徒劳的。 That was the state of LWP's HTTPS support until recently.直到最近,这还是 LWP 的 HTTPS 支持状态。

Now, LWP actually checks to whom it's talking unless you ask LWP to behave as it once did.现在,LWP 实际上会检查它正在与谁交谈,除非您要求 LWP 像以前那样行事。 You can do that using:你可以这样做:

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

If you want to affect all LWP::UserAgent instances in your script without specifying the option all over the place, you can add the following to your script如果您想影响脚本中的所有 LWP::UserAgent 实例而不在整个地方指定选项,您可以将以下内容添加到您的脚本中

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

Or you can launch your script as follows:或者您可以按如下方式启动您的脚本:

PERL_LWP_SSL_VERIFY_HOSTNAME=0 script.pl

Finally, if you want LWP to always be unsafe, you can add the following to your login script:最后,如果您希望 LWP 始终不安全,您可以将以下内容添加到您的登录脚本中:

export PERL_LWP_SSL_VERIFY_HOSTNAME=0

However, I recommend none of the above .但是,我不推荐以上任何一种 The far better option would be to provide the certificate for the host to which you are communicating.更好的选择是为您正在与之通信的主机提供证书。 (This is the equivalent of adding an exception in Firefox, if you know what I mean.) See the documentation for $ua->ssl_opts . (这相当于在 Firefox 中添加异常,如果您知道我的意思的话。)请参阅$ua->ssl_opts文档

For me, using:对我来说,使用:

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

Yielded产量

Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client is deprecated!不推荐对客户端使用 SSL_VERIFY_NONE 的 SSL_verify_mode 的默认值! Please set SSL_verify_mode to SSL_VERIFY_PEER together with SSL_ca_file|SSL_ca_path for verification.请将 SSL_verify_mode 设置为 SSL_VERIFY_PEER 以及 SSL_ca_file|SSL_ca_path 以进行验证。 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.如果您真的不想验证证书并保持连接对中间人攻击开放,请在您的应用程序中将 SSL_verify_mode 显式设置为 SSL_VERIFY_NONE。

Using this did not give any warnings:使用它没有给出任何警告:

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

I prepended my code with:我在我的代码前面加上:

$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;

This caused the script to circumvent the check in a clean and simple way.这导致脚本以干净简单的方式绕过检查。

@ikegami makes a good argument for why you don't want to disable SSL hostname verification, but doesn't directly mention how to avoid it. @ikegami 为您为什么不想禁用 SSL 主机名验证提供了一个很好的论据,但没有直接提及如何避免它。

If you're talking to a public system with a CA-signed certificate, you need to point LWP to your distribution's root certificate collection.如果您使用 CA 签名证书与公共系统通信,则需要将 LWP 指向您的发行版的根证书集合。 Under a Debian-based system (Ubuntu, etc.), this is kept under /etc/ssl/certs/ .在基于 Debian 的系统(Ubuntu 等)下,它保存在/etc/ssl/certs/下。

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

If you are talking to your own server with a self-signed certificate, you can save a copy of that certificate on the client, and point your script to that particular file.如果您使用自签名证书与自己的服务器通信,则可以在客户端上保存该证书的副本,并将脚本指向该特定文件。

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

You could instead set these in the environment before running your script (eg export them from your shell), or you could apply the settings directly to your UserAgent object.您可以在运行脚本之前在环境中设置这些(例如,从您的 shell 中导出它们),或者您可以将设置直接应用到您的 UserAgent 对象。 See the LWP::UserAgent documentation for more details;有关详细信息,请参阅LWP::UserAgent 文档 search for ssl_opts (around halfway down the page).搜索ssl_opts (大约在页面的中间)。

Add the library in the top, and add rest of the ENV declarations and IO socket info before using the LWP module functions.在顶部添加库,并在使用 LWP 模块功能之前添加其余的 ENV 声明和 IO 套接字信息。 Then try, It will workout.然后尝试,它会锻炼。

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

$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;
$ENV{HTTPS_DEBUG} = 1;
        
IO::Socket::SSL::set_ctx_defaults(
  SSL_verifycn_scheme => 'www',
  SSL_verify_mode => 0,
);

$ua = LWP::UserAgent->new();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM