Cannot list FTP directory using ftplib – but FTP client works
Asked Answered
C

2

8

I'm trying to connect to an FTP but I am unable to run any commands.

ftp_server = ip
ftp_username = username
ftp_password = password

ftp = ftplib.FTP(ftp_server)
ftp.login(ftp_username, ftp_password)
'230 Logged on'

ftp.nlst()

The ftp.nlst throws this error:

Error:
[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


I've tested the connection using FileZilla (running on the same machine) and it works fine.

This is FileZilla log:

Status: Connection established, waiting for welcome message...
Status: Insecure server, it does not support FTP over TLS.
Status: Logged in Status: Retrieving directory listing...
Status: Server sent passive reply with unroutable address. Using server address instead.
Status: Directory listing of "/" successful
Curren answered 23/4, 2019 at 15:33 Comment(1)
Have a look at this question / answer as well, it solved my problem #50060537Kudu
W
15

Status: Server sent passive reply with unroutable address

The above means that the FTP server is misconfigured. It sends its internal network IP to outside network (to the client – FileZilla or Python ftplib), where it is invalid. FileZilla can detect that and automatically fall back to the original IP address of the server.

Python ftplib does not do this kind of detection.

You need to fix your FTP server to return the correct IP address.


If it is not feasible to fix the server (it's not yours and the admin is not cooperative), you can make ftplib ignore the returned (invalid) IP address and use the original address instead by overriding FTP.makepasv:

class SmartFTP(FTP):
    def makepasv(self):
        invalidhost, port = super(SmartFTP, self).makepasv()
        return self.host, port

ftp = SmartFTP(ftp_server)

# the rest of the code is the same

In recent versions of Python (3.6 and newer), ftplib doesn't consider the IP address in PASV response on its own.


Another solution may be to use IPv6. See Python 3.8.5 FTPS connection.

For a different problem with similar consequences, see vsftpd returns 0,0,0,0 in response to PASV.

Warbeck answered 26/4, 2019 at 20:51 Comment(1)
You are the best. And I am astounded on how little information is present in the internet for this thingMuriah
D
0

In python 3.9.3 they changed the default behavior of passive mode so it now uses the original host.

If you want to use & trust the passive mode that's being sent trust_server_pasv_ipv4_address needs to be set to True (if not omit that line).

ftp_server = ip
ftp_username = username
ftp_password = password

ftp = ftplib.FTP(ftp_server)
ftp.login(ftp_username, ftp_password)
ftp.trust_server_pasv_ipv4_address = True
ftp.set_pasv(True)

ftp.nlst()
Damarisdamarra answered 6/2 at 18:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.