-1

I get a weird error while trying to push file to remote ftp server using FTP over SSL/TLS. I found no trace of solution online :/ Please help.

Here's my code:

from ftplib import FTP_TLS
import sys, os
root = "\\home\\user\\test.txt"
dest = "/Destdir"
ftps = FTP_TLS('xxx.xxx.xxx.xxx')
ftps.set_debuglevel(1)
ftps.set_pasv(False)
ftps.connect(port=21, timeout=80)
ftps.login('user', 'pass')
ftps.prot_p()
ftps.ccc()
try:
    ftps.cwd(dest)
except Exception as e:
    print(e)
try:
    file = open('test.txt', 'rb')
    ftps.storbinary('STOR test.txt', file)
    file.close()
except Exception as e:
    print(e)
ftps.close()

And here's the output of the script:

*resp* '220 nas FTP server ready.'
*cmd* 'AUTH TLS'
*resp* '234 AUTH TLS command successful.'
*cmd* 'USER user'
*resp* '331 Password required for user.'
*cmd* 'PASS **********'
*resp* '230 User user logged in.'
*cmd* 'PBSZ 0'
*resp* '200 PBSZ command successful (PBSZ=0).'
*cmd* 'PROT P'
*resp* '200 Protection level set to Private.'
*cmd* 'CCC'
*resp* '200 Clearing control channel protection.'
*cmd* 'CWD /Destdir'
*resp* '250 CWD command successful.'
*cmd* 'TYPE I'
*resp* '200 Type set to I.'
*cmd* 'PORT 10,10,99,11,220,211'
*resp* '200 PORT command successful.'
*cmd* 'STOR test.txt'
*resp* "150 Opening BINARY mode data connection for 'test.txt'."
_ssl.c:704: The handshake operation timed out

As connection to remote FTP server is fine then I suppose it is not a firewall issue.

Note: Remote FTP server is a Synology NAS, with up to date OS.

EDIT_0:

Another try with passive mode gave that result:

*resp* '220 nas FTP server ready.'
*cmd* 'AUTH TLS'
*resp* '234 AUTH TLS command successful.'
*cmd* 'USER user'
*resp* '331 Password required for user.'
*cmd* 'PASS **********'
*resp* '230 User user logged in.'
*cmd* 'PBSZ 0'
*resp* '200 PBSZ command successful (PBSZ=0).'
*cmd* 'PROT P'
*resp* '200 Protection level set to Private.'
*cmd* 'CCC'
*resp* '200 Clearing control channel protection.'
*cmd* 'CWD /Destdir'
*resp* '250 CWD command successful.'
*cmd* 'TYPE I'
*resp* '200 Type set to I.'
*cmd* 'PASV'
*resp* '227 Entering Passive Mode (xxx,xxx,xxx,xxx,216,241)'
*cmd* 'STOR test.txt'
*resp* "150 Opening BINARY mode data connection for 'test.txt'."
_ssl.c:704: The handshake operation timed out

I also tried extended passive mode now but it didn't help too:

*resp* '250 CWD command successful.'
*cmd* 'TYPE I'
*resp* '200 Type set to I.'
*cmd* 'EPSV'
*resp* '229 Entering Extended Passive Mode (|||55536|)'
*cmd* 'STOR test.txt'
*resp* "150 Opening BINARY mode data connection for 'test.txt'."
_ssl.c:704: The handshake operation timed out

EDIT_1: So the script works partially, it's able to open connection, starts transfer of the file. File get's created on the remote server but it doesn't contain the same data as source file. Destination file ends up wih 1KB size and just some random chars (file is ANSII encoded, while source file is UTF8. In the meanwhile I am able to upload a file succesfully using WinSCP.

2 Answers2

0

You use FTP active mode:

ftps.set_pasv(False)

And from your comments, it does not look like you have a good reason to do so.

FTP active mode usually does not work, as it requires the client to be able to accept incoming connections. That's typically not possible without opening a local (both Windows and local network) firewall and/or configuring NAT. Do not even try to use the active mode, unless you have a very specific reason to do so. Use the passive mode. Simply remove the ftps.set_pasv call. The passive mode is the default mode in ftplib.

See my article on FTP connection modes for details.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
0

It is likely to be a firewall problem. FTP is rather special because it uses a different connection per transfer. The connection that currently works according to your trace is the command connection which is established by the client and targeted to the server FTP port (normally 21).

The data connection is an independant connection. In active mode, it is established by the server, originating from the FTP-DATA port (20) and targetting the port sent by the client in its PORT command. In passive mode, the server sends the port where it will listen for the data connection in its response to the PASV command, and the client try to open a new connection to that (almost random) port.

That means that unless large address ranges are allowed by the firewall, or the firewall software implements special processing to dynamically allow the addresses passed in FTP commands, a firewall can allow the command connection, and then block any data connection.

Refs:

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252