簡體   English   中英

Python:nlst()使用FTP_TLS掛在“清單上來了”

[英]Python: nlst() hangs on “here come the listing” by using FTP_TLS

我被困在這幾天。 我正在使用python通過使用FTP_TLS連接到我的服務器。 我已經看到過很多關於此錯誤的文章,並做了幾乎所有的更改,但還是很不幸。 我可以連接到服務器,創建目錄,但是當它出現在清單ftps.nlst()ftps.retrlines('LIST')ftps.dir()都卡在/掛在:

150這是目錄列表。

以下是我的服務器vsftpd配置文件:

listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_file=/var/log/vsftpd.log
chroot_local_user=YES
allow_writeable_chroot=YES
pam_service_name=vsftpd
pasv_enable=YES
pasv_promiscuous=YES
pasv_min_port=40000
pasv_max_port=55999
pasv_address = ip_address
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH
user_sub_token=abc
local_root=/home/abc/ftp
user_sub_token=username
local_root=/path/to/username/images
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO

調試日志為:

*get* '220 (vsFTPd 3.0.3)\n'
*resp* '220 (vsFTPd 3.0.3)'
*welcome* '220 (vsFTPd 3.0.3)'
getwelcome >>>220 (vsFTPd 3.0.3)
<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=6, laddr=('192.168.81.11', 59660), raddr=('81.19.0.237', 21)>
*cmd* 'AUTH SSL'
*put* 'AUTH SSL\r\n'
*get* '234 Proceed with negotiation.\n'
*resp* '234 Proceed with negotiation.'
*cmd* 'USER username'
*put* 'USER username\r\n'
*get* '331 Please specify the password.\n'
*resp* '331 Please specify the password.'
*cmd* 'PASS ***************'
*put* 'PASS ***************\r\n'
*get* '230 Login successful.\n'
*resp* '230 Login successful.'
*cmd* 'PBSZ 0'
*put* 'PBSZ 0\r\n'
*get* '200 PBSZ set to 0.\n'
*resp* '200 PBSZ set to 0.'
*cmd* 'PROT P'
*put* 'PROT P\r\n'
*get* '200 PROT now Private.\n'
*resp* '200 PROT now Private.'
Current directory:
*cmd* 'PWD'
*put* 'PWD\r\n'
*get* '257 "/" is the current directory\n'
*resp* '257 "/" is the current directory'
>>>> /
*cmd* 'PWD'
*put* 'PWD\r\n'
*get* '257 "/" is the current directory\n'
*resp* '257 "/" is the current directory'
<<<>>>257 "/" is the current directory
*cmd* 'CWD /uploads/'
*put* 'CWD /uploads/\r\n'
*get* '250 Directory successfully changed.\n'
*resp* '250 Directory successfully changed.'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Switching to ASCII mode.\n'
*resp* '200 Switching to ASCII mode.'
*cmd* 'EPSV'
*put* 'EPSV\r\n'
*get* '229 Entering Extended Passive Mode (|||44788|)\n'
*resp* '229 Entering Extended Passive Mode (|||44788|)'
*cmd* 'NLST'
*put* 'NLST\r\n'
*get* '150 Here comes the directory listing.\n'
*resp* '150 Here comes the directory listing.'
^C 
Traceback (most recent call last):
File "config/timelapse_test.py", line 45, in <module>
    filenames = ftps.nlst()
File "/usr/lib/python3.4/ftplib.py", line 558, in nlst
    self.retrlines(cmd, files.append)
File "/usr/lib/python3.4/ftplib.py", line 467, in retrlines
    with self.transfercmd(cmd) as conn, \
File "/usr/lib/python3.4/ftplib.py", line 398, in transfercmd
    return self.ntransfercmd(cmd, rest)[0]
File "/usr/lib/python3.4/ftplib.py", line 793, in ntransfercmd
    server_hostname=server_hostname)
File "/usr/lib/python3.4/ssl.py", line 364, in wrap_socket
    _context=self)
File "/usr/lib/python3.4/ssl.py", line 577, in __init__
    self.do_handshake()
File "/usr/lib/python3.4/ssl.py", line 804, in do_handshake
    self._sslobj.do_handshake()
KeyboardInterrupt

在我的代碼中我也放置了:

ftps.ssl_version = ssl.PROTOCOL_SSLv23;
ftps.passive = True
ftps.prot_p()

有人可以指導我做錯事情的地方嗎?

謝謝

問題可能出在FTP服務器要求新數據通道中的TLS會話與控制通道相同。 這在Python 3.7中尚未修復。 在解決方案中找到ftplib.FTP_TLS子類,在這里找到https://stackoverflow.com/a/43301750 ,我做了一個小修復:

import ftplib


class ReusedSslSocket(SSLSocket):
    def unwrap(self):
        pass


class MyFTP_TLS(ftplib.FTP_TLS):
    """Explicit FTPS, with shared TLS session"""
    def ntransfercmd(self, cmd, rest=None):
        conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest)
        if self._prot_p:
            conn = self.context.wrap_socket(conn,
                                            server_hostname=self.host,
                                            session=self.sock.session)  # reuses TLS session            
            conn.__class__ = ReusedSslSocket  # we should not close reused ssl socket when file transfers finish
        return conn, size

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM