当前位置: 首页 > 面试题库 >

使用Python连接到“通过TLS的显式FTP”(??)

董良策
2023-03-14
问题内容

我无法弄清楚如何使用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:

我试图将被动标志设置为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成功测试



 类似资料:
  • 我试图通过TLS连接到使用JMS的IBM MQ。我将TLS_RSA_WITH_AES_256_CBC_SHA256设置为IBM MQ控制台通道上的SSL密码规范。 在连接工厂中,我执行以下操作: 我得到: 我不确定这个错误是否意味着握手失败(由于证书/密钥库配置错误)或其他原因。

  • 我正试图通过MQTT发布服务器发布事件。在提供程序URL中提到了tls://URL:port 当我试图执行时,它会给出以下错误:。我使用的是apache jmeter 5.0和MQTT jar版本:mqtt-jmeter-0.0.1-snapshot java.lang.IllegalArgumentException:tls://...:1887 at org.eclipse.paho.clie

  • 如何连接到FTP通过TLS在Apache蚂蚁?ftp任务似乎不支持这一点。在TLS上的FTP还有其他任务吗?

  • 我试图理解Retheart文档的这部分内容,但无法理解:https://softinstigate.atlassian.net/wiki/spaces/rh/pages/9207828/installation+and+setup#installationandsetup-5.1connectreshearttomongodbovertls/ssl 使用keytool创建导入mongod使用的公共

  • 我正在寻找将Python连接到交互式代理应用编程接口。谷歌搜索显示了ibPy的可用性(见https://pypi.python.org/pypi/ib),但是这个库似乎没有得到维护,也不支持Python 3。我还发现https://github.com/colin1alexander/IbPython3但是这个项目已经被取消了。 我知道Quantopian使用交互式代理作为其执行代理,但有一个用于

  • 我试图通过API访问XML文档。当我尝试用python连接时,我得到一个403状态代码。但是,当我将链接粘贴到chrome浏览器中时,数据将按其应有的方式显示。我知道我可能需要在Python中为我的请求添加一些头,但我不知道如何这样做。 我可以在chrome中获取标题,但不确定需要添加哪些标题到请求中 接受:text/html、application/xhtml-xml、application/x