This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Add the ftplib option, overrides the IP address.
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.8
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: giampaolo.rodola Nosy List: giampaolo.rodola, matrixise, r.david.murray, studioes
Priority: normal Keywords: patch

Created on 2018-01-16 18:46 by studioes, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 5207 closed studioes, 2018-01-16 19:00
Messages (8)
msg310102 - (view) Author: Hideyuki (studioes) * Date: 2018-01-16 18:46
Add the ftplib's option, overrides the IP address to be used with the PORT command.
Currently, the PORT command is sending its self IP address.
If the host is connected with NAT, it will not work.
If that command has a NAT external IP address, it is working.
So add an option to overrides the IP address sending with the PORT command.
This is useful when active FTP transfer needed on a 1:1 NAT connected host so like AWS VPC.
msg311408 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2018-02-01 09:24
Hi Hideyuki,

Thank you for your contribution but we need some changes from your PR.

1. Could you add a documentation in Doc/library/ftplib.rst +- line 170, after FTP.set_debuglevel ?

2. There is no tests, please could you add a test in Lib/test/test_ftplib.py

3. Fix the remarks on your PR

Thank you
msg311431 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2018-02-01 14:49
I'd like confirmation from someone involved in maintaining the ftplib package that this is in fact the correct solution.
msg311432 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2018-02-01 15:06
+1 for this point David,

but also the minimum is the documentation and a test, I suppose you will
confirm.
msg311440 - (view) Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer) Date: 2018-02-01 15:25
Mmmm out of curiosity, how common is this? Usually when client is behind a NAT it's supposed to use PASV. What you're proposing is a configuration option which typically belong to servers, not clients. I don't remember ever bumping into a FTP client allowing such an option (e.g. does FileZilla have it?). Also, this has some security implications as you could potentially dictate a naive FTP server to connect to a malicious host:port, and basically this is the reasons why servers do such a "IP replacement", not clients. In pyftpdlib (which is a server) I explicitly reject PORT connections with an IP != client's IP (because it's a security concern), even though the check can be disabled:  
https://github.com/giampaolo/pyftpdlib/blob/9dcbf685e10906fbdf4969cda1138a25f96bf16d/pyftpdlib/handlers.py#L383-L396
I believe proftpd and vsftpd does the same by default.
msg311441 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2018-02-01 15:36
I too wondered if pasv was the correct solution to the problem.
msg311447 - (view) Author: Hideyuki (studioes) * Date: 2018-02-01 16:40
I understand that it is best to use PASV.
But this FTP server is managed by another person, and that server required active mode. 
Also, my host is in a VPC environment, it is connected by 1:1 NAT. This NAT BOX does not support FTP transparent.

In this case, we recognize that IP packet received by the FTP server is from the external IP address of the NAT BOX, but ftplib will send the IP address on host NIC.
So dose not match IP packet source address and PORT address, it will be closed with the indicated code.

The purpose of this feature is to communicate by overriding the IP address sending by PORT command with the NAT external IP address(so the client IP address seen by server).
msg311454 - (view) Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer) Date: 2018-02-01 17:19
Considering the security implications and the fact that it's a corner case I don't think this is worth adding as a new, public API, sorry. I think ftplib should expose and promote APIs reflecting common scenarios and good practices, yet be flexible enough in order to allow "breaking the rules". FWIW, you may get away with something like this, which IMO is not too bad (not tested): 


class FTP(ftplib.FTP):
    externalip = None

    def sendport(self, host, port):
        return super().sendport(self.externalip or host, port)

    def sendeprt(self, host, port):
        return super().sendeprt(self.externalip or host, port)
History
Date User Action Args
2022-04-11 14:58:56adminsetgithub: 76753
2018-02-01 17:19:30giampaolo.rodolasetstatus: open -> closed
resolution: rejected
messages: + msg311454

stage: patch review -> resolved
2018-02-01 16:40:43studioessetmessages: + msg311447
2018-02-01 15:36:17r.david.murraysetmessages: + msg311441
2018-02-01 15:25:36giampaolo.rodolasetassignee: giampaolo.rodola
messages: + msg311440
2018-02-01 15:06:37matrixisesetmessages: + msg311432
2018-02-01 14:49:04r.david.murraysetnosy: + r.david.murray
messages: + msg311431
2018-02-01 09:24:25matrixisesetnosy: + matrixise
messages: + msg311408
2018-01-19 20:29:37terry.reedysetnosy: + giampaolo.rodola

versions: - Python 3.6, Python 3.7
2018-01-16 19:00:48studioessetkeywords: + patch
stage: patch review
pull_requests: + pull_request5061
2018-01-16 18:46:18studioescreate