Intermediate 10 min FTP 425

425 Can't Open Data Connection — Passive Mode Firewall

Symptoms

- Control connection and login succeed, but LIST or file transfer fails with "425 Can't open data connection"
- FTP client shows "Passive mode refused" or hangs for 30–60 seconds before timing out
- `tcpdump` shows the PASV response arriving with an RFC 1918 IP (10.x, 172.16.x, 192.168.x) that is unreachable from the client
- The error only appears from outside the server's local network — internal clients on the same LAN can transfer files without issue
- Active mode (PORT command) may work if the client firewall allows incoming connections

Root Causes

  • Server's passive mode port range (e.g., 50000–51000) is not open in the OS firewall (iptables/nftables) or cloud security group, so the client TCP SYN is silently dropped
  • Server reports its private/internal IP in the PASV response because `pasv_address` is not set — the client tries to connect to an RFC 1918 address that is unreachable over the public internet
  • NAT router or cloud provider (AWS/GCP/Azure) security group blocks the high-numbered passive data ports even though port 21 is open
  • FTP server not configured with `pasv_min_port` / `pasv_max_port`, so it picks random ephemeral ports that cannot be predicted for firewall rules
  • Client-side firewall blocking incoming TCP connections needed for the data channel when the server uses active mode as a fallback

Diagnosis

**Step 1 — Capture the PASV exchange**

```bash
# In FileZilla: View → Message Log — look for the 227 response
# Example bad response:
# 227 Entering Passive Mode (10,0,1,50,195,149)
# Decoded: IP=10.0.1.50, Port=(195*256)+149=50069
# A private IP here means pasv_address is not set
```

**Step 2 — Decode the PASV IP and port**

```python
# The 227 response encodes the address as (h1,h2,h3,h4,p1,p2)
# IP = h1.h2.h3.h4
# Port = p1 * 256 + p2
h1,h2,h3,h4,p1,p2 = 10,0,1,50,195,149
print(f'{h1}.{h2}.{h3}.{h4}:{p1*256+p2}') # 10.0.1.50:50069
```

**Step 3 — Test connectivity to the data port**

```bash
# From the FTP client machine:
nc -zv YOUR_SERVER_PUBLIC_IP 50069
# 'Connection refused' = port blocked by firewall
# 'Connected' = port open, problem is elsewhere
```

**Step 4 — Check the passive port range is open on the server**

```bash
# iptables
sudo iptables -L INPUT -n | grep '50000:51000'
# If empty, the range is not open:
sudo iptables -A INPUT -p tcp --dport 50000:51000 -j ACCEPT

# firewalld
sudo firewall-cmd --list-ports
```

**Step 5 — Check AWS/GCP/Azure security groups**

```
AWS EC2 Security Group:
Inbound rule: TCP 50000–51000 0.0.0.0/0
GCP Firewall rule:
gcloud compute firewall-rules create ftp-passive \
--allow tcp:50000-51000 --source-ranges 0.0.0.0/0
```

Resolution

**Fix 1 — Set a fixed passive port range in vsftpd**

```ini
# /etc/vsftpd.conf
pasv_enable=YES
pasv_min_port=50000
pasv_max_port=51000
pasv_address=203.0.113.42 # your server's public IP
```

```bash
sudo systemctl restart vsftpd
```

**Fix 2 — Open the port range in iptables**

```bash
sudo iptables -A INPUT -p tcp --dport 50000:51000 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 21 -j ACCEPT
# Persist across reboots:
sudo netfilter-persistent save
```

**Fix 3 — Open the port range in firewalld**

```bash
sudo firewall-cmd --permanent --add-port=50000-51000/tcp
sudo firewall-cmd --permanent --add-service=ftp
sudo firewall-cmd --reload
```

**Fix 4 — ProFTPD equivalent configuration**

```apache
# /etc/proftpd/proftpd.conf
PassivePorts 50000 51000
MasqueradeAddress 203.0.113.42
```

**Fix 5 — Use SFTP instead**

SFTP (SSH File Transfer Protocol on port 22) uses a single connection for both control and data — passive/active mode issues do not apply. Migrate clients to SFTP to eliminate this class of firewall problem entirely.

Prevention

- Always set `pasv_address` to the public IP on any server behind NAT or in a cloud environment — without it, passive mode will fail for external clients
- Use a fixed, narrow passive port range (e.g., 50000–51000) and document it in your firewall runbook so it is included in every security group template
- Prefer SFTP over FTP for all new integrations — SFTP's single-connection model eliminates the active/passive firewall complexity entirely
- Include port 21 and the passive range in your automated firewall audit scripts so gaps are caught before they impact users
- Consider FTPS with a modern TLS certificate if SFTP migration is not immediately feasible — it at least encrypts credentials in transit

Related Status Codes

Related Terms