【问题标题】:cURL: connection refused from PHP, but works from command linecURL:PHP 拒绝连接,但可以从命令行运行
【发布时间】:2017-05-10 17:11:58
【问题描述】:

我有一个奇怪的 cURL 行为。

当我尝试使用 PHP 函数发出请求时,如下所示:

$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://<url_here>",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => "<body here>",
    CURLOPT_HTTPHEADER => array(
        "content-type: application/xml"
    ),
));

我收到Failed to connect to &lt;url_here&gt; port 443: Connection refused

但是当我尝试从命令行(在 PHP 脚本所在的服务器上)进行完全相同的调用时,我得到了一个有效的响应。所以,环境还好,443端口没有堵。

此外,当我在另一台服务器上运行相同的 PHP 代码时,它也可以工作。

是否有可能某些 PHP 配置选项会阻止 cURL 工作?还是我应该检查其他内容?

谢谢。


本地curl_version()的输出:

array(9) {
  ["version_number"]=>
  int(470784)
  ["age"]=>
  int(3)
  ["features"]=>
  int(968605)
  ["ssl_version_number"]=>
  int(0)
  ["version"]=>
  string(6) "7.47.0"
  ["host"]=>
  string(19) "x86_64-pc-linux-gnu"
  ["ssl_version"]=>
  string(14) "OpenSSL/1.0.2g"
  ["libz_version"]=>
  string(5) "1.2.8"
  ["protocols"]=>
  array(21) {
    [0]=>
    string(4) "dict"
    [1]=>
    string(4) "file"
    [2]=>
    string(3) "ftp"
    [3]=>
    string(4) "ftps"
    [4]=>
    string(6) "gopher"
    [5]=>
    string(4) "http"
    [6]=>
    string(5) "https"
    [7]=>
    string(4) "imap"
    [8]=>
    string(5) "imaps"
    [9]=>
    string(4) "ldap"
    [10]=>
    string(5) "ldaps"
    [11]=>
    string(4) "pop3"
    [12]=>
    string(5) "pop3s"
    [13]=>
    string(4) "rtmp"
    [14]=>
    string(4) "rtsp"
    [15]=>
    string(3) "smb"
    [16]=>
    string(4) "smbs"
    [17]=>
    string(4) "smtp"
    [18]=>
    string(5) "smtps"
    [19]=>
    string(6) "telnet"
    [20]=>
    string(4) "tftp"
  }
}

本地curl -V的输出:

curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets

服务器curl_version()的输出:

array(9) {
  ["version_number"]=>
  int(462597)
  ["age"]=>
  int(2)
  ["features"]=>
  int(1597)
  ["ssl_version_number"]=>
  int(0)
  ["version"]=>
  string(6) "7.15.5"
  ["host"]=>
  string(23) "x86_64-redhat-linux-gnu"
  ["ssl_version"]=>
  string(15) " OpenSSL/0.9.8b"
  ["libz_version"]=>
  string(5) "1.2.3"
  ["protocols"]=>
  array(9) {
    [0]=>
    string(4) "tftp"
    [1]=>
    string(3) "ftp"
    [2]=>
    string(6) "telnet"
    [3]=>
    string(4) "dict"
    [4]=>
    string(4) "ldap"
    [5]=>
    string(4) "http"
    [6]=>
    string(4) "file"
    [7]=>
    string(5) "https"
    [8]=>
    string(4) "ftps"
  }
}

【问题讨论】:

  • curl_version() 中的 ssl 与 curl -V 有何不同?
  • 该错误消息听起来像是来自远程服务器 - 这意味着它不是防火墙问题。你能检查一下PHP ini设置curl.cainfo在每种情况下的值吗?
  • @AlexBlex,恐怕,不。我已经为问题添加了版本。
  • @CBroe,curl.cainfo 在服务器上为空 ("")(通过 ini_get())。而且恐怕我不知道如何通过控制台获取它。
  • 另一台服务器上是空的吗,你说它也在哪里工作?您能否将有关 cURL 的 phpinfo 输出与您服务器的输出进行比较?

标签: php curl https connection-refused


【解决方案1】:

感谢Alex Blex's comment 我启用了 PHP cURL 的详细输出,并使用 -vvv 选项运行命令行 cURL。

这让我看到,命令行请求实际上是通过代理发送的,而 PHP cURL 试图进行直接调用,但失败了。

然后我为我的 PHP 请求使用了CURLOPT_PROXY 选项,它也开始工作了。

【讨论】:

  • 我有与 docker 完全相同的场景。请问哪个CURLOPT_PROXY 选项?
  • 这取决于您的请求配置。对我来说,这是不同的代理设置
  • 抱歉误读了您的答案。我虽然你的意思是它是 php 7 CURLOPT_PROXY_xxxx 选项之一,例如 CURLOPT_PROXY_SERVICE_NAME 。我现在看到这本身就是一个选项curl.haxx.se/libcurl/c/CURLOPT_PROXY.html
【解决方案2】:

您忽略了提供端口...

在下面检查您更正的代码:

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://<url_here>",
    CURLOPT_PORT => "443", //MY CORRECTION TO YOUR CODE
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => "<body here>",
    CURLOPT_HTTPHEADER => array(
        "content-type: application/xml"
    ),
));

(另见this post...)

【讨论】:

  • 当协议是https时,我认为cURL足够聪明,可以自己找出默认端口。另外,错误消息说使用了端口 443,所以我怀疑这是解决方案。
  • 猜你是对的......另一件事是:你的服务器是否有机会运行 SELinux?如果是,请禁用它并重试...
  • 不幸的是,它没有帮助。这是一个 linux docker 镜像。
猜你喜欢
  • 2021-05-10
  • 2015-12-26
  • 2019-04-13
  • 2018-10-19
  • 1970-01-01
  • 2018-06-19
  • 2015-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多