配置DigiCert中介签发SSL证书的私有IP HTTPS接口访问问题排查
问题
我通过NAT连接供应商访问其API,HTTP方式正常,但生产环境需用HTTPS,请求时出现两类错误:
- 启用SSL验证时:cURL error 60: SSL certificate problem: unable to get local issuer certificate,请求地址为
https://xyz.xyz.xyz.xyz:18423/interface//request - 禁用SSL验证时:cURL Error #:OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
已执行的SSL配置步骤:
- 用openssl生成证书请求和私钥:
openssl req -new -newkey rsa:2048 -nodes -keyout mycompany.key -out mycompany.csr
注意:使用的FQDN为
api.mycompany.com,该域名不存在,服务器仅通过内网私有IP访问(供应商可通过NAT回调我方)。
- 将CSR发送给供应商签名
- 供应商返回以下文件:
- mydomain.cer
- mydomain.p7b
- broker_vendor_com.crt
- DigiCertCA.crt
- 解码mydomain.cer
- 将mydomain.cer与DigiCertCA.crt合并为bundle.crt
- 在Nginx中配置证书:
ssl_certificate /etc/ssl/bundle.crt; ssl_certificate_key /etc/ssl/salaammfbank.key;
另外,终端执行curl -kv https://xyz.xyz.xyz.xyz:18423/interface//request可成功返回200,但PHP cURL请求同样报错:
- 禁用验证时:cURL Error #:OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
- 启用验证时:cURL Error #:SSL certificate problem: unable to get local issuer certificate
PHP代码如下:
$url = 'https://xyz.xyz.xyz.xyz:18423/interface//request'; $body = ''; $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 40, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $body, CURLOPT_HTTPHEADER => ["Accept: application/json", "Content-Type: application/xml"] ]); #curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); #curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; }
请问遗漏了哪些配置,才能通过HTTPS从服务器访问供应商端点?
解决方案
一、解决SSL证书验证失败(cURL 60错误)
- 配置PHP cURL信任完整证书链
终端curl能成功是因为系统默认信任DigiCert根证书,但PHP cURL可能使用独立的证书存储。将供应商提供的broker_vendor_com.crt(中间证书)和DigiCertCA.crt(根证书)合并成完整链文件,然后在PHP代码中指定:
// 替换为合并后的证书链文件路径 curl_setopt($curl, CURLOPT_CAINFO, '/etc/ssl/full_vendor_chain.crt');
也可以修改php.ini全局配置(需重启PHP服务):
curl.cainfo = "/etc/ssl/full_vendor_chain.crt" openssl.cafile = "/etc/ssl/full_vendor_chain.crt"
- 确认证书链顺序
合并证书时需按「用户证书→中间证书→根证书」的顺序,比如你的bundle.crt应调整为mydomain.cer在前,接着是broker_vendor_com.crt,最后是DigiCertCA.crt。
二、解决禁用验证时的EOF错误(error:0A000126)
该错误多因SSL握手不完整导致,尝试以下调整:
- 强制指定SSL/TLS版本
终端curl会自动协商合适版本,PHP cURL可能需显式指定:
// 根据供应商支持情况选择TLSv1_2或TLSv1_3 curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
- 调整编码设置
终端curl的-k模式默认压缩逻辑可能和PHP cURL不同,尝试修改编码配置:
// 注释掉原CURLOPT_ENCODING,或指定具体压缩格式 // CURLOPT_ENCODING => "", CURLOPT_ENCODING => "gzip",
- 简化请求头
你的PHP请求同时设置了Accept: application/json和Content-Type: application/xml,可能触发供应商的校验逻辑,尝试简化:
CURLOPT_HTTPHEADER => ["Content-Type: application/xml"]
- 区分Nginx证书作用
你配置的Nginx证书是用于接收供应商回调的,和服务器主动请求供应商API无关,无需依赖该证书处理出站HTTPS请求。
三、额外排查点
- 检查服务器防火墙/安全组是否允许出站访问
xyz.xyz.xyz.xyz:18423,若终端curl能通但PHP不行,可能是PHP进程受SELinux等权限限制。 - 对比终端curl和PHP cURL版本:执行
curl --version和php -i | grep cURL,版本差异可能导致SSL协商逻辑不同。
内容的提问来源于stack exchange,提问作者Noor
相关产品推荐
相关产品推荐

