You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Perl LWP::Simple请求NCBI接口在Ubuntu服务器失败本地MacOS正常

问题现象

我使用如下Perl代码请求网页内容:

#!/usr/bin/perl
use LWP::Simple;
use LWP::Protocol::https;
$url = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=protein&id=YP_009724389.1&rettype=ft&retmode=text';
$res = getprint($url);
print $res;

该代码在本地MacOS设备上运行完全正常,但在Ubuntu服务器上无法运行。经测试服务器上使用Python、wget请求该URL可正常返回,且Perl请求其他URL也可正常运行。两端设备的模块版本信息如下:

  • 服务器端:perl v5.22.1,libwww-perl为最新6.15-1版本
  • 本地端:perl v5.30.2,LWP::Simple为刚安装的最新版本

补充报错与环境信息

  1. 基础报错:500 Can't connect to eutils.ncbi.nlm.nih.gov:443 at test.pl
  2. 依赖检查:Ubuntu服务器已安装HTTPS相关依赖,liblwp-protocol-https-perl为最新6.06-2版本
  3. 详细调试报错:
DEBUG: .../IO/Socket/SSL.pm:2733: free ctx 38676848 open=38676848
DEBUG: .../IO/Socket/SSL.pm:2738: free ctx 38676848 callback
DEBUG: .../IO/Socket/SSL.pm:2745: OK free ctx 38676848
DEBUG: .../IO/Socket/SSL.pm:2700: new ctx 39560272
DEBUG: .../IO/Socket/SSL.pm:612: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:614: socket connected
DEBUG: .../IO/Socket/SSL.pm:636: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:669: using SNI with hostname eutils.ncbi.nlm.nih.gov
DEBUG: .../IO/Socket/SSL.pm:704: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:723: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:736: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:739: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:749: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:759: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:779: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:736: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:739: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:742: SSL connect attempt failed

DEBUG: .../IO/Socket/SSL.pm:742: local error: SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
DEBUG: .../IO/Socket/SSL.pm:745: fatal SSL error: SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
DEBUG: ...erl5/Net/HTTPS.pm:69: ignoring less severe local error 'IO::Socket::IP configuration failed', keep 'SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure'
DEBUG: .../IO/Socket/SSL.pm:2733: free ctx 39560272 open=39560272
DEBUG: .../IO/Socket/SSL.pm:2738: free ctx 39560272 callback
DEBUG: .../IO/Socket/SSL.pm:2745: OK free ctx 39560272

我也尝试了使用LWP::UserAgent等效代码,且设置为不校验证书,仍无效果。
4. 相关依赖版本:

1..3
ok 1 - loaded
# openssl version compiled=0x1000205f linked=0x1000207f -- OpenSSL 1.0.2g  1 Mar 2016
# Net::SSLeay version=1.72
# parent IO::Socket::IP version=0.37
ok 2 - IO::Socket::SSL::DEBUG 1
ok 3 - Net::SSLeay::trace 1

服务器上使用curl请求该URL可正常成功,curl执行输出如下:

*   Trying 130.14.29.110...
* Connected to eutils.ncbi.nlm.nih.gov (130.14.29.110) port 443 (#0)
* found 129 certificates in /etc/ssl/certs/ca-certificates.crt
* found 516 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
*    server certificate verification OK
*    server certificate status verification SKIPPED
*    common name: *.ncbi.nlm.nih.gov (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #3
*    subject: C=US,ST=Maryland,L=Bethesda,O=National Library of Medicine,CN=*.ncbi.nlm.nih.gov
*    start date: Tue, 20 Jul 2021 00:00:00 GMT
*    expire date: Wed, 10 Aug 2022 23:59:59 GMT
*    issuer: C=US,O=DigiCert Inc,CN=DigiCert TLS RSA SHA256 2020 CA1
*    compression: NULL
* ALPN, server accepted to use http/1.1
> GET /entrez/eutils/efetch.fcgi?db=protein&id=YP_009724389.1&rettype=ft&retmode=text HTTP/1.1
> Host: eutils.ncbi.nlm.nih.gov
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 17 Sep 2021 15:27:15 GMT
< Server: Finatra
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
< Content-Security-Policy: upgrade-insecure-requests
< X-Test-Test: test42
< Cache-Control: private
< NCBI-PHID: 322C09A5C8CE1A1500004CCDDDF835FE.1.1.m_5
< X-RateLimit-Remaining: 2
< NCBI-SID: 1CC49D756062E8D4_7834SID
< X-RateLimit-Limit: 3
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: X-RateLimit-Limit,X-RateLimit-Remaining
< Content-Type: text/plain
< Content-Disposition: attachment; filename="sequence.txt"
< Set-Cookie: ncbi_sid=1CC49D756062E8D4_7834SID; domain=.nih.gov; path=/; expires=Sat, 17 Sep 2022 15:27:15 GMT
< Vary: Accept-Encoding
< X-UA-Compatible: IE=Edge
< X-XSS-Protection: 1; mode=block
< Transfer-Encoding: chunked
解决方案

根因

服务器上的Net::SSLeay 1.72 + IO::Socket::SSL搭配旧版本OpenSSL 1.0.2g时,默认的TLS协商参数无法匹配NCBI服务器的加密配置,所以出现握手失败。curl能成功是因为它内置了更符合现代站点要求的默认加密套件和TLS版本规则。

修复代码

改用LWP::UserAgent手动指定TLS版本和加密套件即可:

#!/usr/bin/perl
use LWP::UserAgent;
use LWP::Protocol::https;

my $ua = LWP::UserAgent->new(
    ssl_opts => {
        # 强制使用TLS 1.2,匹配curl成功连接时的协议版本
        SSL_version => 'TLSv1_2',
        # 指定NCBI服务器支持的加密套件列表
        SSL_cipher_list => 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384',
        verify_hostname => 1,
    }
);

my $url = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=protein&id=YP_009724389.1&rettype=ft&retmode=text';
my $res = $ua->get($url);
if ($res->is_success) {
    print $res->decoded_content;
} else {
    die "请求失败: " . $res->status_line;
}

备选方案

如果上述代码依旧无效,可直接升级相关SSL模块到最新版本,旧版本模块对新TLS配置的兼容性更差:

cpanm Net::SSLeay IO::Socket::SSL

内容的提问来源于stack exchange,提问作者caceves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 00:18:05