Applies to: FTP servers on Linux (vsftpd, Pure-FTPd, ProFTPD) and any FTP client; tested with vsftpd 3.0.5 and curl 8.14.1 on Debian 13, UFW on Ubuntu 26.04 and firewalld on AlmaLinux 9

FTP uses two connections: a control connection on port 21 for the login and commands, and a separate data connection for every file transfer and directory listing. Active and passive mode only differ in who opens that data connection:

  • Passive mode: the client connects to the server, on a port the server announces. This is what almost every client uses today, because it works through the client’s firewall and home router.
  • Active mode: the client tells the server a port, and the server connects back to the client (with vsftpd’s sample settings, from port 20). That usually fails when the client is behind NAT or a firewall.

So for passive mode, the server must allow port 21 plus a range of passive ports. If only port 21 is open, the login works but listings and transfers hang.

What it looks like on the wire

We connected with curl -v to a vsftpd server. In passive mode the client first sends EPSV (extended passive, RFC 2428) and the server answers with the port to use:

> EPSV
< 229 Entering Extended Passive Mode (|||40026|)
* Connecting to 127.0.0.1 (127.0.0.1) port 40026

Older clients send PASV and get the address and port as six numbers:

> PASV
< 227 Entering Passive Mode (127,0,0,1,156,151).
* Connecting to 127.0.0.1 (127.0.0.1) port 40087

The first four numbers are the IP address; the port is the fifth number times 256 plus the sixth: 156 × 256 + 151 = 40087. If that IP address is a private one (for example 10.x or 192.168.x) while you connected to a public address, the server is behind NAT and needs its public IP configured (see below).

In active mode the client sends EPRT or PORT instead:

> PORT 127,0,0,1,154,161
< 200 PORT command successful. Consider using PASV.

The typical symptom: login works, listing times out

We blocked the passive range in the server’s firewall and tried again. The login succeeded, the server announced port 40075, and then:

* Connecting to 127.0.0.1 (127.0.0.1) port 40075
* Operation timed out after 12007 milliseconds with 0 bytes received

In a graphical client this shows up as a directory listing that fails or times out right after a successful login. The fix is on the server: set a fixed passive range and open it in the firewall.

Set a passive port range on the server

By default, vsftpd picks any free port (pasv_min_port is 0), which you can’t open in a firewall. Choose a range, for example 40000 to 40100. In our test every listing and transfer got a different port from the range, so make it large enough for the number of people transferring at the same time.

vsftpd (/etc/vsftpd.conf on Debian and Ubuntu, /etc/vsftpd/vsftpd.conf on AlmaLinux and Rocky Linux):

pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
# only if the server is behind NAT:
pasv_address=203.0.113.10

Pure-FTPd on Debian and Ubuntu reads one file per setting; the wrapper turns them into the -p and -P options:

echo "40000 40100" | sudo tee /etc/pure-ftpd/conf/PassivePortRange
echo "203.0.113.10" | sudo tee /etc/pure-ftpd/conf/ForcePassiveIP   # only behind NAT

ProFTPD (/etc/proftpd/proftpd.conf, where both lines are present but commented out):

PassivePorts 40000 40100
MasqueradeAddress 203.0.113.10   # only behind NAT

Restart the FTP service after the change, for example sudo systemctl restart vsftpd.

Open the ports in the firewall

UFW (Ubuntu, Debian):

sudo ufw allow 21/tcp
sudo ufw allow 40000:40100/tcp

A port range needs the protocol: without /tcp, UFW answers ERROR: Must specify 'tcp' or 'udp' with multiple ports.

firewalld (AlmaLinux, Rocky Linux, RHEL):

sudo firewall-cmd --permanent --add-service=ftp
sudo firewall-cmd --permanent --add-port=40000-40100/tcp
sudo firewall-cmd --reload

The ftp service opens port 21 and loads firewalld’s FTP helper, which can follow unencrypted FTP. With FTPS (FTP over TLS) the firewall can’t read the commands, so always open the passive range explicitly. If your server has a separate firewall in front of it, open the same ports there.

Choosing the mode in the client

Leave the client on passive. In FileZilla, the Site Manager’s Transfer Settings tab offers Default, Active and Passive; according to the FileZilla project, Default uses the global setting, which is passive unless you changed it. Use active mode only if the server doesn’t allow passive mode and your own network accepts incoming connections. More client settings: if FTP does not work.

Consider SFTP instead

SFTP runs over SSH on a single port and encrypts the password and the files, so none of the passive-port problems apply. If your users can switch, it is the simpler choice: see which port SFTP uses. To set up an FTP server with TLS, see vsftpd with TLS on AlmaLinux and Rocky Linux and the key vsftpd settings.

Official documentation: vsftpd.conf(5), RFC 959 (FTP) and RFC 2428 (EPSV and EPRT).

Ucartz services for this topic

Was this answer helpful? 0 Users Found This Useful (0 Votes)