FTP passive mode connections are failing because the FTP server, often behind a NAT gateway, cannot correctly inform the client where to establish the data connection.
Cause 1: Server IP Mismatch in PASV Response
Diagnosis:
On the FTP server (e.g., vsftpd), check the configuration file (/etc/vsftpd.conf) for pasv_address. If it’s not set or set incorrectly, the server will advertise its internal IP address in the 227 Entering Passive Mode response, which is unreachable by clients outside the NAT.
Fix:
Set pasv_address to the external IP address of your NAT gateway.
# /etc/vsftpd.conf
pasv_address=203.0.113.5
Why it works: This explicitly tells vsftpd which IP address to advertise to clients for passive data connections, bypassing the need for the server to guess or rely on its internal interface IP.
Cause 2: Incorrect pasv_min_port and pasv_max_port Range
Diagnosis:
When the server responds with 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2), the client attempts to connect to h1.h2.h3.h4 on port p1*256 + p2. If these ports are not open in the firewall or the NAT gateway’s port forwarding rules, the connection will fail.
Fix: Define a specific, limited port range for passive mode and ensure these ports are forwarded.
# /etc/vsftpd.conf
pasv_min_port=40000
pasv_max_port=40100
Then, configure your NAT gateway to forward TCP ports 40000-40100 to the FTP server’s internal IP address.
Why it works: This restricts passive data connections to a predictable, manageable range of ports. By forwarding this specific range, you ensure that incoming data connection attempts from clients can reach the server through the NAT.
Cause 3: Firewall Blocking Passive Ports
Diagnosis: Even if the server advertises the correct IP and ports, a firewall on the server itself or on the NAT gateway might be blocking the passive port range.
Fix:
On the server’s firewall (e.g., iptables or firewalld), allow inbound TCP traffic to the pasv_min_port to pasv_max_port range.
Using iptables:
sudo iptables -A INPUT -p tcp --dport 40000:40100 -j ACCEPT
sudo service iptables save # or equivalent for your system
Using firewalld:
sudo firewall-cmd --permanent --add-port=40000-40100/tcp
sudo firewall-cmd --reload
Why it works: This explicitly permits the necessary data connection traffic to reach the FTP server, ensuring that the client’s attempts to connect to the advertised passive ports are not dropped by the server’s local firewall.
Cause 4: NAT Gateway Not Forwarding Correctly
Diagnosis:
The NAT gateway is responsible for translating the external IP and port advertised by the server to the internal IP and port of the server. If this forwarding is misconfigured, connections will fail. This is often seen when the pasv_address on the server is set to the internal IP, and the NAT device doesn’t have a specific rule for FTP.
Fix:
Configure your NAT gateway to perform Destination Network Address Translation (DNAT) for the passive port range. For example, on a typical Linux router using iptables:
# On the NAT gateway machine
sudo iptables -t nat -A PREROUTING -p tcp --dport 40000:40100 -j DNAT --to-destination 192.168.1.100:40000-40100
sudo iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 40000:40100 -j ACCEPT
Replace 192.168.1.100 with your FTP server’s internal IP.
Why it works: This rule tells the NAT device that any incoming TCP traffic destined for the external IP on ports 40000-40100 should be rewritten (DNAT’d) to be sent to the internal IP address of the FTP server on the same port range. The FORWARD rule then allows this translated traffic to pass through the router.
Cause 5: pasv_enable=YES Not Set
Diagnosis: Passive mode might simply be disabled on the FTP server, causing it to default to active mode (which also has NAT issues, but typically different symptoms).
Fix: Ensure passive mode is enabled in the FTP server configuration.
# /etc/vsftpd.conf
pasv_enable=YES
Why it works: This explicitly activates the passive mode functionality of the FTP server, allowing it to initiate the 227 Entering Passive Mode handshake and wait for client connections on the specified passive ports.
Cause 6: FTP Client Issues or Misconfiguration
Diagnosis:
Some older or less compliant FTP clients might have trouble with the IP address or port specified in the 227 response, or might still attempt active mode connections even when passive is preferred.
Fix:
Configure the FTP client to explicitly use passive mode (often a checkbox or command-line flag like -p for lftp or ftp in passive mode). Ensure the client is aware of the NAT’d external IP if it has specific NAT settings.
Example using lftp:
lftp -u username,password -p 21 ftp://203.0.113.5
set ftp:passive-mode on
Why it works: Forcing the client to use passive mode and ensuring it correctly interprets the server’s IP address and port information prevents it from initiating connections from unexpected source IPs or to incorrect destinations.
The next error you’ll likely encounter is a "Connection timed out" or "Connection refused" error when the client attempts to establish the data connection after the initial control connection is successful.