如何使用 LWP::UserAgent 接受自签名证书
Posted
技术标签:
【中文标题】如何使用 LWP::UserAgent 接受自签名证书【英文标题】:How to accept self-signed certificates with LWP::UserAgent 【发布时间】:2018-05-19 15:15:59 【问题描述】:我正在尝试设置使用 HTTPS 的 node.js 服务器。然后我将在 Perl 中编写一个脚本来向服务器发出 HTTPS 请求并测量往返的延迟。
这是我的 node.js:
var express = require('express');
var https = require('https');
var fs = require('fs');
var key = fs.readFileSync('encrypt/rootCA.key');
var cert = fs.readFileSync('encrypt/rootCA.pem');
// This line is from the Node.js HTTPS documentation.
var options =
key: key,
cert: cert
;
https.createServer(options, function (req, res)
res.writeHead(200);
res.end("hello world - https\n");
).listen(8088);
密钥/证书生成如下:
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem
这是我的 Perl 脚本:
#!/usr/bin/perl
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(GET => 'https://127.0.0.1:8080');
my $res = $ua->request($req);
if ($res->is_success)
print $res->as_string;
else
print "Failed: ", $res->status_line, "\n";
返回错误:
Failed: 500 Can't verify SSL peers without knowing which Certificate Authorities to trust
node.js 文档描述了如何设置 HTTPS 服务器,但对生成主证书和中间证书的内容含糊不清。
https://medium.com/netscape/everything-about-creating-an-https-server-using-node-js-2fc5c48a8d4e
【问题讨论】:
所以您的问题实际上是“如何配置 LWP::UserAgent 以接受 HTTPS 的自签名证书?” 实际上是的。你知道怎么做吗? 我明白了。感谢@amon 为我指明了正确的方向 【参考方案1】:此类问题的典型答案是完全禁用证书验证。但是,这是完全不安全的,并且基本上禁用了 HTTPS 提供的大部分保护。 如果验证被完全禁用,中间人攻击者可以使用任意证书拦截连接并嗅探和修改数据。因此,不要这样做。
处理此类证书的正确方法是将这些证书添加为受信任的。这可以通过SSL_ca_file
参数来完成:
my $ua = LWP::UserAgent->new;
$ua->ssl_opts(SSL_ca_file => 'rootCA.pem');
$ua->get('https://127.0.0.1:8080');
通过将自签名服务器证书明确信任为 CA,它将不再抛出“证书验证失败”。
但是,除非您的服务器证书实际颁发给“127.0.0.1”,否则您现在将收到“主机名验证失败”,因为证书的主题与 URL 的域不匹配。这可以通过设置预期的主机名来解决:
my $ua = LWP::UserAgent->new;
$ua->ssl_opts(
SSL_ca_file => 'rootCA.pem',
SSL_verifycn_name => 'www.example.com',
);
$ua->get('https://127.0.0.1:8080');
请注意,SSL_ca_file
需要自签名证书将 CA 标志设置为 true,即该证书是可用于颁发其他证书的 CA 证书。如果您的证书不是这种情况,或者您只想接受特定证书,无论它是否已过期、被吊销、与主机名不匹配等,您都可以使用证书的指纹进行验证。
my $ua = LWP::UserAgent->new;
$ua->ssl_opts(SSL_fingerprint => 'sha1$9AA5CFED857445259D90FE1B56B9F003C0187BFF')
$ua->get('https://127.0.0.1:8080');
这里的指纹和openssl x509 -noout -in rootCA.pem -fingerprint -sha1
一样,只是前面加了算法(sha1$...
),去掉了冒号。
【讨论】:
【参考方案2】:要使 LWP::UserAgent 忽略服务器证书,请使用以下配置:
my $ua = LWP::UserAgent->new;
$ua->ssl_opts(
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
verify_hostname => 0
);
【讨论】:
这不仅仅是接受自签名证书。这是接受 any 证书,因此 使连接对中间攻击中的任意人开放。 @SteffenUllrich 这就是接受自签名证书的作用,是的。 @duskwuff: “这就是接受自签名证书的作用,是的。” - 不,您可以以安全的方式接受特定的自签名证书,即无需完全禁用验证,从而接受此处所做的任意证书。这也很容易。看我的回答。以上是关于如何使用 LWP::UserAgent 接受自签名证书的主要内容,如果未能解决你的问题,请参考以下文章
为啥 LWP::UserAgent 是通过 require LWP::UserAgent 而不是使用 LWP::UserAgent 导入的?
Perl LWP::UserAgent 错误处理 UTF-8 响应