0

I am been stuck in this for couple of days. I am using python to connect to my server by using FTP_TLS. I have seen many post on this error and had done almost all the changes but still nno luck. I can connect to my server, make directories but when it comes on the listing ftps.nlst() , ftps.retrlines('LIST') or ftps.dir() all got stuck/hangs at:

150 Here comes the directory listing.

Below is my server vsftpd configuration file:

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

Debug Log is:

*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

also in my code i have placed:

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

Can someone guide me where i am doing things wrong?

Thanks

1 Answers1

0

The problem is probably that the FTP server requires that the TLS session in the new data channel is the same as the control channel. This has not been fixed in Python 3.7. Subclass ftplib.FTP_TLS as in the solution found here https://stackoverflow.com/a/43301750 with a small fix by me:

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
AndersTornkvist
  • 2,610
  • 20
  • 38