gpt4 book ai didi

python - 在 Python 中连接到 'Explicit FTP over TLS'(??)

转载 作者:太空宇宙 更新时间:2023-11-03 12:37:11 36 4
gpt4 key购买 nike

我不知道如何使用 ftplib 查看 FTP 站点的文件内容。

我可以很好地使用 WinSCP 连接到 FTP 站点,并在根目录中看到 6 个文件。

在 Python 3.4 中,我使用以下代码:

        from ftplib import FTP_TLS
ftps = FTP_TLS(timeout=100)
ftps.connect(ipAddress, 21)
ftps.auth()
ftps.prot_p()
ftps.login('username', 'password')

产生:

        Out[72]: '230 User logged in.'

然后我可以运行这个:

        ftps.pwd()

...我看到我在根目录中:

        Out[73]: '/'

一切似乎都是肉汁。但是,当我尝试使用 ftps.dir() 或 ftps.retrlines('NLST') 或我尝试过的任何其他方法查看目录中的内容时,出现超时:

TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

我用谷歌搜索了一下,发现有几个人说这可能是“被动与主动”连接设置问题。然而,我问了 FTP 的管理员它是被动的还是主动的,他表现得难以置信,只是说,“这不是 SFTP。它是基于 TLS 的显式 FTP!!”

我对这些一无所知。我只是想使用 ftplib(或任何其他包!)连接到他的 FTP 并下载一些文件。

我错过了什么??

编辑:我刚刚发现 WinSCP 使用的是被动模式,所以这似乎是可行的。据我了解,ftplib 默认情况下是被动的,但我还是继续将标志设置为 true。这什么也没做,我仍然遇到同样的问题。

我也检查了我的防火墙(捕获吸管),它完全关闭了,所以那里应该没有问题。

我还尝试使用“.sendcmd()”方法发送显式命令,它似乎能够发送命令,但不会获取任何响应(或者它看不到响应)。

是否有某种原因导致我能够看到我所在的目录,但看不到任何其他数据?我显然已连接并与服务器通信,而且目录对我来说可用和可见似乎意味着数据可以来回传输。数据是否可能以某种 ftplib 无法识别的方式返回?关于我应该从哪里开始对此进行故障排除有什么想法吗?

最后,再一次,似乎一切都已正确设置,因为我可以在 WinSCP 中看到一切正常。我应该检查哪些设置以与 ftplib 进行比较?

编辑 2:

按照要求,我设置了调试级别(感谢这个提示),下面是输出:

ftps = FTP_TLS(timeout=15)
ftps.set_debuglevel(2)
ftps.connect(ipAddress, 21)
ftps.set_pasv(True)
ftps.auth()
ftps.prot_p()
ftps.login('username', 'password')
ftps.retrlines('NLST')
*get* '220 Microsoft FTP Service\n'
*resp* '220 Microsoft FTP Service'
*cmd* 'AUTH TLS'
*put* 'AUTH TLS\r\n'
*get* '234 AUTH command ok. Expecting TLS Negotiation.\n'
*resp* '234 AUTH command ok. Expecting TLS Negotiation.'
*cmd* 'PBSZ 0'
*put* 'PBSZ 0\r\n'
*get* '200 PBSZ command successful.\n'
*resp* '200 PBSZ command successful.'
*cmd* 'PROT P'
*put* 'PROT P\r\n'
*get* '200 PROT command successful.\n'
*resp* '200 PROT command successful.'
*cmd* 'USER username'
*put* 'USER username\r\n'
*get* '331 Password required for username.\n'
*resp* '331 Password required for username.'
*cmd* 'PASS ****************'
*put* 'PASS ****************\r\n'
*get* '230 User logged in.\n'
*resp* '230 User logged in.'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A.\n'
*resp* '200 Type set to A.'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (10,19,1,137,195,128).\n'
*resp* '227 Entering Passive Mode (10,19,1,137,195,128).'
Traceback (most recent call last):

File "<ipython-input-13-a79eb3c23dc5>", line 8, in <module>
ftps.retrlines('NLST')

File "C:\Anaconda3\lib\ftplib.py", line 467, in retrlines
with self.transfercmd(cmd) as conn,
File "C:\Anaconda3\lib\ftplib.py", line 398, in transfercmd
return self.ntransfercmd(cmd, rest)[0]

File "C:\Anaconda3\lib\ftplib.py", line 793, in ntransfercmd
conn, size = FTP.ntransfercmd(self, cmd, rest)

File "C:\Anaconda3\lib\ftplib.py", line 360, in ntransfercmd
source_address=self.source_address)

File "C:\Anaconda3\lib\socket.py", line 516, in create_connection
raise err

File "C:\Anaconda3\lib\socket.py", line 507, in create_connection
sock.connect(sa)

timeout: timed out

编辑 3:

我试图将 passive 标志设置为 false,但是当我请求文件时,我得到以下信息:

ftps.retrlines('NLST')
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A.\n'
*resp* '200 Type set to A.'
*cmd* 'PORT 10,1,10,100,223,39'
*put* 'PORT 10,1,10,100,223,39\r\n'
*get* '501 Server cannot accept argument.\n'
*resp* '501 Server cannot accept argument.'

编辑 4:

我在 WinSCP 上启用了日志记录,看起来很有帮助的 Steffen Ullrich 是对的!这是在 WinSCP 的日志中:

< 2017-05-19 08:44:27.880 227 Entering Passive Mode (10,19,1,137,195,139).
< 2017-05-19 08:44:27.880 Server sent passive reply with unroutable address 10.19.1.137, using host address instead.

那么,我如何让 ftplib 做同样的事情呢?

编辑 5:

找到 THIS - 这只是重写源代码以使其看起来适合主机。还有其他人有更简单、侵入性更小/可能具有破坏性的方法来做到这一点吗?

作为第二种选择,由于管理员似乎不太合格,我是否可以明确地告诉他去对主机做些什么以使这项工作更好(即 - 被动返回正确的 IP)?

最佳答案

*get* '227 Entering Passive Mode (10,19,1,137,195,128).\n'

问题是服务器在对 PASV 命令的响应中返回了错误的 IP 地址。这对于某些防火墙后面的某些内部网络中的服务器来说是典型的。在这种情况下,返回 10.19.1.137,这是一个只能在本地网络中使用的 IP 地址。

这是 FTP 服务器的错误设置。但不幸的是,这种错误的设置很常见,因此许多客户端通过忽略响应中给定的 IP 地址并使用控制连接的 IP 地址来解决它。 ftplib 不支持此类解决方法。但是可以猴子修补它来提供这样的支持:

from ftplib import FTP_TLS

# replace original makepasv function with one which always returns
# the peerhost of the control connections as peerhost for the data
# connection
_old_makepasv = FTP_TLS.makepasv
def _new_makepasv(self):
host,port = _old_makepasv(self)
host = self.sock.getpeername()[0]
return host,port
FTP_TLS.makepasv = _new_makepasv

ftp = FTP_TLS(ipAddress)
ftp.login(...)
ftp.nlst()

这已成功通过 Python 2.7.12 和 Python 3.5.2 测试

关于python - 在 Python 中连接到 'Explicit FTP over TLS'(??),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44057732/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com