Perl REST::Client 如何使用 TLS 1.3 连接服务端?
结论
错误发生在 TLS 握手阶段,HTTP 请求还没有发出。若要让 Perl 使用与 curl --tlsv1.3 相同的 TLS 1.3,可在 LWP::UserAgent 的 ssl_opts 中设置 SSL_version => 'TLSv1_3'。这要求 Perl 使用的 IO::Socket::SSL 和底层 OpenSSL 均支持 TLS 1.3;如果运行环境不支持,单改选项无法解决问题。
日志中的 tlsv1 alert protocol version 表示 TLS 对端返回了协议版本告警,并不表示 TLS 已经建立或收到 HTTP 500 响应。日志显示,失败发生在 LWP/Protocol/http.pm 的连接过程中。
设置 TLS 1.3
可以在现有结构中这样设置:
use LWP::UserAgent;
use REST::Client;
my $ua = LWP::UserAgent->new(
ssl_opts => {
SSL_version => 'TLSv1_3',
},
);
my $client = REST::Client->new({
host => $IP_DCIM,
timeout => 90,
useragent => $ua,
});
TLSv1_3 是 IO::Socket::SSL 使用的协议版本名称,对应 curl 参数中的 TLS 1.3。原配置 SSLv23:!TLSv1:!TLSv1_1:!SSLv3:!SSLv2 用于筛选协议;实际支持哪些协议,取决于 Perl 加载的 TLS 库及其编译选项。如果显式指定 TLS 1.3,但库不支持该版本,通常会出现本地配置或协议支持相关错误。
检查 Perl 使用的 TLS 库
先查看 Perl 环境中相关模块的版本:
perl -MIO::Socket::SSL -e 'print "$IO::Socket::SSL::VERSION\n"'
perl -MNet::SSLeay -e 'print Net::SSLeay::SSLeay_version(0), "\n"'
确认这套 Perl 环境中的 IO::Socket::SSL、Net::SSLeay 和 OpenSSL 支持 TLS 1.3。单独运行 openssl version 只能显示命令行程序所链接的 OpenSSL 版本,不一定能反映 Perl 模块实际加载的库。
如果设置 TLSv1_3 后仍然失败,检查 Perl 进程是否加载了与系统命令不同版本的依赖,并确认连接的主机名、端口和服务端 TLS 配置与 curl 命令一致。原命令中的主机地址已隐藏,无法据此进一步判断服务端配置。
注意事项
TLS 握手成功后,如果遇到认证或 HTTP 状态码问题,再检查 Perl 请求是否设置了与 curl -u 等效的认证信息,以及请求方法和 URL。当前日志指向协议协商阶段,认证设置不是这条错误的直接原因。
备注:内容仅供参考。
