Having trouble connecting Filezilla to an FTP server that's behind a NAT router? If it connects, but then gives a "Failed to retrieve directory listing" error, then you have likely hit a classic NAT router problem.

I first encountered this when trying to connect to ZitaFTP Server when it was running from within the Qemu emulator. Filezilla was running on the host machine, and ZitaFTP on the emulated one. The ports were forwarded correctly, Filezilla would connect, log in, and then fail to retrieve the directory listing. Other FTP clients (including CURL) would work just fine.

The Problem: PASV and the NAT Router

The FTP protocol is unusual in that it uses two connections: a control connection for commands, and a separate data connection for transferring things such as files and directory listings. In an ideal world, Filezilla would use the newer EPSV command to request a data connection. The server returns a port number (e.g., 9000), which Filezilla then connects to, and data transfers happen.

FTP Control and Data Connections

Filezilla does this for version 6 of the Internet Protocol (IPv6). However, for some reason it'll always fallback to the older PASV command for the older IPv4. It'll do this even if the server says that it supports the nat6 feature, including EPSV.

The older PASV command will send both an IP address and port number. Here's where the problems begin. The Network Address Translation (NAT) router gives the server a private IP address (e.g., 10.0.2.5). So, the server replies "connect to 10.0.2.5, port 9000." Unfortunately, Filezilla sits on the other side of the NAT, where 10.0.2.5 isn't accessible. It connected using the router's IP address.

FTP PASV and NAT Router Problem

Filezilla notices the discrepancy, and will correct it in some cases. With my server running in an emulator it didn't, because the connection was via "localhost" (i.e., 127.0.0.1).

The end result: the data connection can't be established, causing it to fail.

The Solution: A Hidden Filezilla Feature

I spotted this feature in Filezilla's source code. Basically, if the "Pasv reply fallback mode" is set to 2, then it'll always use the control connection's IP address for the data connection. Exactly what we need.

There's no way to enable this from Filezilla's settings UI (which is why it's a "hidden" feature). Instead, enable it as follows:

  1. Close Filezilla if it's open
  2. Find the filezilla.xml configuration file. It can be found in:
  • <userpath>/AppData/Roaming/Filezilla on Windows
  • ~/.config/filezilla on MacOS X (and possibly some Linux distros)
  • Try /etc/filezilla on Linux
  • Find the line containing: <Setting name="Pasv reply fallback mode">
  • Change the setting above to 2. The line should look something like <Setting name="Pasv reply fallback mode">2</Setting>
  • Save filezilla.xml

Now start Filezilla, and try connecting to the server again. It should work this time. At least, it did for me with ZitaFTP Server running in an emulator.

Filezilla working around PASV NAT problem by using the same IP