被动 FTP 连接不能通过 PHP 工作

Posted

技术标签:

【中文标题】被动 FTP 连接不能通过 PHP 工作【英文标题】:Passive FTP connection does not work via PHP 【发布时间】:2018-07-10 08:01:06 【问题描述】:

我的应用程序连接到通过 *** 连接到服务器的 FTP 客户端。到目前为止,所有客户端都支持主动 php,我使用的库默认使用主动 FTP,所以没有问题。然而,现在我们已经安装了一些新的客户端,它们不能通过主动 PHP 正常工作,所以我发现从服务器(通过 FTP cli 和 RDP 上的 FileZilla)可以通过被动连接连接到所有客户端并与之交谈。

但是,当尝试在 PHP 中建立被动连接时,所有 FTP 命令(例如nlist)都会超时。我遇到了this blog post,它为特定的被动 FTP 问题提供了一个补丁(现在在常规 PHP 版本中可用),所以我尝试像这样测试它:

$conn = ftp_connect($address);
$login = ftp_login($conn, 'username', 'password');

ftp_set_option($conn, USEPASVADDRESS, false);
ftp_pasv($conn, true);

$contents = ftp_nlist($conn, '.');

var_dump($contents);

ftp_close($conn);

ftp_pasv 返回 true,因此它正在切换到被动模式,但 ftp_nlist 超时,它不适用于主动模式和兼容的客户端。

PHP 的 FTP 实现和 FTP cli 应用程序有什么不同?

【问题讨论】:

您从ftp_nlist 收到的确切错误消息是什么? + 显示“FTP cli”日志文件(我是否正确理解您从同一台机器/服务器运行“FTP cli”的内容,您正在运行您的 PHP 代码?) “FTP cli”是/usr/bin/ftpftp_nlist 不会抛出错误,它只是超时并返回 false 你没有回答我所有的问题。 不确定ftp是否会写日志文件,所以我不知道去哪里找,我现在只能给你这个:pastebin.com/FUEXbBRN至于另一个问题,是的,我在运行 PHP 脚本的服务器上运行它。 所以在您的 PHP 代码中,$address192.168.12.10? + 你如何运行 PHP 代码?从命令行?来自与ftp 相同的环境? + 您可以访问服务器端日志文件吗?如果没有,您可以进行 Wireshark 捕获(或类似操作)吗? 【参考方案1】:

我想我已经弄清楚了我的情况的确切问题。我不确定这是否对其他人有帮助,但如果您遇到类似问题,不妨考虑一下。

激活被动模式时,服务器会告诉您要连接的 IP 和端口以进行数据传输。使用ftp CLI 时,实际的PASV 命令仅在您发送数据命令(如请求文件夹内容)时发送。在这些情况下,CLI 发送 PASV 命令,接收 IP/端口,连接到它,然后通过它发送原始命令 (LIST)。

PHP 的做法似乎有所不同:一旦您在我们的代码中切换到被动连接,它就会发送 PASV 命令并立即从服务器接收 IP/端口 - 但 PHP 尚未连接到它.然后当我询问目录列表时,首先激活 ASCII 模式,然后才连接到先前收到的 IP/端口以发送 LIST 命令。

因此,我怀疑我要连接的 FTP 服务器有问题。我的想法是,一旦它收到PASV 命令,它就会等到有人真正连接到该被动连接,然后才开始接受任何其他命令。事实上,我设法验证了这一点。当 PHP 脚本仍在等待响应时,我手动建立了与接收到的被动端口的 TCP 连接,之后我的 PHP 代码恢复运行并显示结果。

不幸的是,这意味着我根本无法在这些服务器上使用被动 FTP,并且无法更新/切换到不同的服务器实现。主动 FTP 也几乎是不可能的,因为我的应用是在 Docker 中运行的。

【讨论】:

我不这么认为。 PHP ftp_pasv 不做任何事情,它只设置一个内部标志。只有在您使用ftp_nlist 或类似功能后,PHP 才会发送TYPE,然后是PASV,并立即连接到提供的IP 地址和端口。见github.com/php/php-src/blob/php-8.0.2/ext/ftp/ftp.c#L1607 我已经有一段时间没有调试这个了,我只是想用我当时的发现来更新这篇文章。我查看了使用此 FTP 服务器和已知良好服务器之间的 tcpdump 差异,以及通过 ftp CLI 和 PHP 连接到其中的任何一个。 PHP 显示了错误行为,就像我说的那样,我可以通过手动连接到被动端口来修复。即使 PHP 本身不是问题,我很确定 FTP 服务器是,当我手动建立一个完全独立的连接时突然我的 PHP 脚本(刚刚停止)继续运行。

以上是关于被动 FTP 连接不能通过 PHP 工作的主要内容,如果未能解决你的问题,请参考以下文章

FTP两种工作模式:主动模式(Active FTP)和被动模式

FTP两种工作模式:主动模式(Active FTP)和被动模式

FtpWebRequest.UsePassive属性:设置FTP工作模式

大白话解释一下“被动FTP模式”是啥意思?

FTP的主动模式和被动模式的相关知识

FTP的主动模式和被动模式区别