Why is vsftpd (behind firewall) returning its internal ip address for the pasv address?
If you are behind an external firewall, the incoming connection comes actually from the external firewall. So the server IP address is its internal IP address. What you describe is a "correct" behavior. The FTP server is not aware (and cannot be) of the external IP address of the firewall.
What you can do is to assign two IP addresses to the FTP server. One for an external use and one for an internal use. And configure the FTP server to return the firewall external IP address for connections on the external IP address; and internal IP address for connections on the internal IP address.
Though I'm no sure, if vsftpd does allow such configuration. ProFTPD does.
To get this working using vsfptd, I did a few things:
- Changed the conf file for the existing vsfptd service
- Listen on port 2121
- Respond with external IP
- Forward port 21 from the firewall to port 2121 on the ftp server
- Added a second vsftpd service (named vsftpd-internal)
- Listen on the default port 21
- Respond with internal IP
This makes the existing service handle external connections only and the new vsftpd-internal service handle internal connections only.
Edit to show conf options (requested in comments)
External (/etc/vsftpd.conf):
listen_port=2121
pasv_address=x.x.x.x # External IP - port forwarded from FW to this machine
Internal (/etc/vsftpd-internal.conf):
# nothing special in this one, mostly default
FTP causes headake very often, because it doesn't do data transport on the already-established control connection, but requires to open an additional connection for transporting data. The first version of FTP required the server to open this connection to the client - this was at times where NAT was unknown. To make this work with NAT, PASV was invented, so the client could open this second connnection. Better, but - as you experienced - not optimal.
Three options come to my mind:
- You use sftp instead - it doesn't suffer from this problem, because it is essentially using ssh for control and data in one and only one connection. Of course this is a different protocol, so depending on your environment this might not be an option.
- Instead of NATing on your Debian firewall, you use some ftp proxy software like "ftp-proxy".
- You set up two vsftp servers, one listening for internal connections on standard port, another one on, say, 2121, for external use, which gets pasv_address configured to the firewall's external IP. NAT needs to be adapted to translate port 21 into port 2121.