【问题标题】:CURL FTP Connection refused only on hostingCURL FTP 连接仅在主机上被拒绝
【发布时间】:2020-08-23 18:12:36
【问题描述】:

我使用 PHP 和 Curl 连接到 FTP 服务器, 奇怪的是,当我在本地设置中尝试我的代码时,它以隐式 TLS 和显式 TLS 方式工作,但是当我在任何服务器上运行相同的代码时,它不起作用并返回 Connection refused

PHP代码是:

<?php

function simple_list_test() {
    $curlopts = [];
    $debug = true;
    $return = null;
    
    $curlopts[CURLOPT_USERPWD] = "{$user}:{$password}";
    $curlopts[CURLOPT_SSL_VERIFYPEER] = false;
    $curlopts[CURLOPT_SSL_VERIFYHOST] = false;
    $curlopts[CURLOPT_FTP_SSL] = CURLFTPSSL_TRY;
    $curlopts[CURLOPT_FTPSSLAUTH] = CURLFTPAUTH_TLS;
    $curlopts[CURLOPT_RETURNTRANSFER] = true;
    $curlopts[CURLOPT_URL] = "ftp://ftp.avidafinance.com:21/"; // I tried with ftps:// protocol too it works on local but not when you run it on a hosting
    $curlopts[CURLOPT_FTPLISTONLY] = 1;
    $curlopts[CURLOPT_UPLOAD] = 0;
    $curlopts[CURLOPT_RETURNTRANSFER] = 1;

    $ch = curl_init();

    foreach($curlopts as $key => $value) {
        curl_setopt($ch, $key, $value);
    }

    if ($debug) {
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        $verbose = fopen('php://temp', 'w+');
        curl_setopt($ch, CURLOPT_STDERR, $verbose);
    }

    $return = curl_exec($ch);

    if ($debug) {
        rewind($verbose);
        $verboseLog = stream_get_contents($verbose);
        echo "Verbose information:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
    }

    if ($error = curl_error($ch)) {
        throw new Exception($error);
    }

    return $return;
}

我花了一整天的时间,尝试了很多方法,包括设置 CURLOPT_PORT ,设置 ftps:// 协议,增加超时,包括服务器 .crt.pem curl 证书,但它们都不起作用所以我是想知道是否有人可以在这里帮我一把,

以下是使用 PHP 7.3 和 curl 7.68.0 的本地开发环境的详细输出简介:

*   Trying 13.53.118.182:21...
* TCP_NODELAY set
* Connected to ftp.avidafinance.com (13.53.118.182) port 21 (#0)
< 220 FileZilla Server 0.9.60 beta
> AUTH TLS
< 234 Using authentication type TLS
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*  subject: OU=Domain Control Validated; CN=ftp.avidafinance.com
*  start date: Mar 23 12:46:23 2020 GMT
*  expire date: Mar 23 12:46:23 2022 GMT
*  issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
*  SSL certificate verify ok.
> USER ****
< 331 Password required for *****
> PASS *****
< 230 Logged on
> PBSZ 0
< 200 PBSZ=0
> PROT P
< 200 Protection level set to P
> PWD
< 257 "/" is current directory.
* Entry path is '/'
* Request has same path as previous transfer
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 229 Entering Extended Passive Mode (|||57081|)
*   Trying 13.53.118.182:57081...
* TCP_NODELAY set
* Connecting to 13.53.118.182 (13.53.118.182) port 57081
* Connected to ftp.avidafinance.com (13.53.118.182) port 21 (#0)
> TYPE A
< 200 Type set to A
> NLST
< 150 Opening data channel for directory listing of "/"
* Maxdownload = -1
* Doing the SSL/TLS handshake on the data stream
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* SSL re-using session ID
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*  subject: OU=Domain Control Validated; CN=ftp.avidafinance.com
*  start date: Mar 23 12:46:23 2020 GMT
*  expire date: Mar 23 12:46:23 2022 GMT
*  issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
*  SSL certificate verify ok.
* Remembering we are in dir ""
< 226 Successfully transferred "/"
* Connection #0 to host ftp.avidafinance.com left intact

但是当我在主机上运行完全相同的代码时(尝试了超过 3 个不同的服务器),它会是这样的:

*   Trying 13.53.118.182...
* TCP_NODELAY set
* Connected to ftp.avidafinance.com (13.53.118.182) port 21 (#0)
< 220 FileZilla Server 0.9.60 beta
> AUTH TLS
< 234 Using authentication type TLS
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*  subject: OU=Domain Control Validated; CN=ftp.avidafinance.com
*  start date: Mar 23 12:46:23 2020 GMT
*  expire date: Mar 23 12:46:23 2022 GMT
*  issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
*  SSL certificate verify ok.
> USER *****
< 331 Password required for ******
> PASS *****
< 230 Logged on
> PBSZ 0
< 200 PBSZ=0
> PROT P
< 200 Protection level set to P
> PWD
< 257 "/" is current directory.
* Entry path is '/'
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 229 Entering Extended Passive Mode (|||57093|)
*   Trying 13.53.118.182...
* TCP_NODELAY set
* Connecting to 13.53.118.182 (13.53.118.182) port 57093
* connect to 13.53.118.182 port 21 failed: Connection refused
* Failed to connect to ftp.avidafinance.com port 21: Connection refused
* Failed EPSV attempt. Disabling EPSV
> PASV
< 227 Entering Passive Mode (13,53,118,182,222,194)
*   Trying 13.53.118.182...
* TCP_NODELAY set
* Connecting to 13.53.118.182 (13.53.118.182) port 57026
* connect to 13.53.118.182 port 21 failed: Connection refused
* Failed to connect to ftp.avidafinance.com port 21: Connection refused
* Closing connection 0

简而言之,我需要一个 Explicit FTP Over TLS 连接,我尝试使用 curlftp_ssl_connect fsockets,...。它们都不起作用,我将不胜感激,它不一定是卷曲

【问题讨论】:

  • 主机可能具有不允许此类访问的限制性防火墙设置。您是否尝试过托管服务器上的任何其他 FTP 客户端?
  • 看起来不像防火墙,初始连接已建立。 Connection refused 通常来自远程主机。我能发现的唯一区别是EPSV(不管是什么......)。编辑:阅读jscape.com/blog/what-is-the-ftp/… - 只有在不涉及防火墙的情况下才能使用 EPSV。
  • @SteffenUllrich 主机是 cpanel,它们没有任何其他 FTP 客户端
  • @LarsStegelitz:“EPSV 只能在不涉及防火墙的情况下使用。” - 并非如此。但是被动模式(EPSV 和 PASV)要求防火墙允许任意传出 TCP 连接。主动模式(EPRT、PORT)更糟糕,需要允许所有来自端口 20 的传入 TCP 连接。防火墙上的特殊 FTP 帮助程序可能会放松这些限制,但如果涉及 TLS,这些将不起作用,就像这里的情况一样。

标签: php ssl curl ftp


【解决方案1】:

让我们总结一下这里的内容:https://slacksite.com/other/ftp.html

在主动模式 FTP 中,客户端从一个随机的非特权端口 (N > 1023) 连接到 FTP 服务器的命令端口,即端口 21。

在被动模式 FTP 中,客户端启动到服务器的两个连接,解决了防火墙过滤从服务器到客户端的传入数据端口连接的问题。在打开 FTP 连接时,客户端会在本地打开两个随机的非特权端口(N > 1023 和 N+1)。

这适用于您的计算机,因为非限制端口策略,很高兴知道这不适用于服务器,您不能只是“开放端口”。

我遇到了类似的问题,我用 Python ftputil 库解决了这个问题。

【讨论】:

    【解决方案2】:

    经过几周的尝试,我发现正如您在详细信息中看到的那样,连接和登录工作正常,因为它们位于端口 21 上,但是当涉及到目录列表和自 FTP 服务器上传/下载时正在为他们使用不同的端口,它拒绝连接,这是由于我的托管服务提供商的防火墙不允许这些端口上的传出连接,我要求他们打开端口范围,问题解决了

    【讨论】:

    • 或者,您也可以强制您的连接使用“主动”而不是“被动”模式。这样你就可以留在 21 端口。
    【解决方案3】:

    你试过被动模式吗?

    $curlopts[CURLOPT_FTP_USE_EPRT] = 1;
    

    【讨论】:

    • 所以。如果托管不允许直接连接到端口 21,也许尝试使用代理?
    • 主机阻塞21端口会不会有问题?
    • 当然可以
    • 但是,如果您看到详细信息,它不会在第一次连接时拒绝连接
    • 它不会拒绝连接,因为第一个命令总是发送到端口 21,没关系,这里的问题是在第一个命令之后它会更改端口并且根本不会系统阻塞的工作原因。
    猜你喜欢
    • 2017-07-23
    • 1970-01-01
    • 2020-03-14
    • 2021-12-16
    • 2014-05-31
    • 2016-01-27
    • 2015-12-12
    • 2015-09-20
    相关资源
    最近更新 更多