无法仅在首次尝试时建立 SSL 连接


Unable to establish SSL connection on first attempt only

我有一个电子商务网站,已经运行了几个月,没有代码更改(几年来,对卡处理路径只有很小的更改(。我现在遇到一个问题,即首次打开与信用卡处理器安全服务器的连接时,连接失败。在第二次(或第三次,或第四次等(尝试时,连接成功。一段时间后(可能是 5 分钟(,初始连接将再次失败,后续连接将成功。

来自信用卡处理器的 PHP API 文件的示例代码:

$url = 'https://esplus.moneris.com:443/gateway_us/servlet/MpgRequestArray';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt ($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$dataToSend);
curl_setopt($ch,CURLOPT_TIMEOUT,$gArray[CLIENT_TIMEOUT]);
curl_setopt($ch,CURLOPT_USERAGENT,$gArray[API_VERSION]);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
$response=curl_exec ($ch);
if(!$response) {
    print curl_error($ch);
    print "'n";
    print curl_errno($ch);
    print "'n";
} else {
    print "Success'n";
}

输出:

% php tester_curl.php
error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
35
% php tester_curl.php
Success
% php tester_curl.php
Success
% php tester_curl.php
Success

有一些类似的问题,但我无法解决问题,也没有看到任何具有相同错误消息和初始失败后后续连接尝试成功的症状,例如:

  • 无法建立 SSL 连接,如何修复我的 SSL 证书?
  • curl errno 35(连接到 [安全站点]:443 时出现未知 SSL 协议错误((相同的错误消息(
  • 如何修复仅在第一次调用脚本时发生的cURL SSL连接超时(不同的错误消息,但SSL连接首次尝试失败,随后成功(

服务器有点坏了。它确实支持 TLS1.2 和 TLS1.0,但不支持 TLS1.1(回复 TLS1.0 没问题(。这通常不是问题,除非您的客户端代码试图通过排除其他协议来强制执行特定协议。

您描述的行为看起来像一个客户端,它在连接失败时降级连接,将此降级缓存一段时间,但在一段时间后再次重试最初失败的版本。要追踪问题,请执行以下操作:

  • 检查问题是否也出在其他服务器上
  • 检查其他客户端是否在同一服务器上出现问题
  • 检查底层实现。Curl可以使用GnuTLS,NSS,OpenSSL等等。从错误消息来看,它看起来像 OpenSSL,但哪个版本?
  • 检查服务器路径中是否有任何可能导致问题的中间盒(防火墙、负载均衡器等(
  • 进行数据包捕获并以可用于Wireshark(例如Cloudshark(的形式将其发布在此处

有关如何调试此类问题以及哪些附加信息有用的详细信息,请查看 http://noxxi.de/howto/ssl-debugging.html#aid_external_debugging

我使用旧VirtualMerchant网关的客户端发生了确切的事情。它在星期一下午 5:00 开始失败,并在第二天上午 10 点神奇地再次开始工作。

无论是在命令行上通过openssl或curl,还是通过PHP中的curl,连接都会在第一次失败,然后如果你运行相同的命令,第二个命令它将起作用。

我尝试强制使用IPv4(而不是IPv6(,设置超时,强制使用不同的协议,降级openssl等,但都不起作用。

假设这是网关端与DNS和/或服务器相关的内容,因为我们没有做任何事情来修复它,它自己修复了。

我们运行的是一个较旧的openssl,它只支持TLS 1.1,但它正在工作,然后它又开始工作,所以它不仅仅是我们的客户。但是,我们客户端的年龄一定是问题的一部分,因为其他新客户端在同一时间段内没有遇到"首次尝试失败"。

长话短说,如果发生这种情况,它可能不是您(除了您有一个较旧的 OpenSSL(,并且您调用的另一个网关/服务器可能需要修复/调整某些内容才能重新开始工作。

请记住,openssl 是 Linux 核心软件包的一部分,因此您不能简单地升级 openssl,而不会有弄乱服务器的严重风险。您必须升级到较新版本的操作系统才能获得更现代的openssl。