When dealing with legacy applications requiring FTP (not SFTP), we often need to implement security measures that exceed the protocol's inherent limitations. The classic approach involves:
- Deploying VSFTPD as the FTP server
- Restricting port 21 access via firewall rules
- Establishing SSH tunnels for secure transport
To make VSFTPD listen exclusively on localhost, modify /etc/vsftpd.conf
with these critical parameters:
listen=YES listen_address=127.0.0.1 anonymous_enable=NO local_enable=YES write_enable=YES chroot_local_user=YES allow_writeable_chroot=YES userlist_enable=YES userlist_file=/etc/vsftpd.userlist userlist_deny=NO
While VSFTPD's native configuration provides the first layer, combining it with firewall rules creates defense in depth. For UFW users:
sudo ufw allow from 127.0.0.1 to any port 21 sudo ufw deny 21
For iptables purists:
iptables -A INPUT -p tcp --dport 21 -s 127.0.0.1 -j ACCEPT iptables -A INPUT -p tcp --dport 21 -j DROP
The complete secure workflow involves establishing the SSH tunnel:
ssh -L 2121:localhost:21 user@your_server
Then configure your legacy client to connect to:
- Host: localhost
- Port: 2121
Validate your setup with these commands:
netstat -tulnp | grep 21 # Should show 127.0.0.1:21 nmap -p 21 your_server_ip # From external host should show filtered
For active connection testing:
ftp localhost # Should work ftp your_server_ip # Should fail
When dealing with legacy applications requiring FTP (not SFTP), security-conscious developers often need to restrict access at multiple layers. While firewall rules can block external connections, configuring VSFTPD itself to listen only on localhost provides an additional security boundary.
The most effective method involves modifying vsftpd.conf with these critical directives:
listen=YES
listen_address=127.0.0.1
listen_ipv6=NO
This configuration ensures:
- The server binds exclusively to IPv4 localhost
- IPv6 listening is disabled (prevents potential ::1 binding)
- All external connection attempts are rejected at the service level
After restarting VSFTPD (systemctl restart vsftpd
), verify the binding:
ss -tulnp | grep vsftpd
# Should only show: tcp LISTEN 0 32 127.0.0.1:21
For your tunneled access solution, the client-side SSH command would be:
ssh -L 2121:localhost:21 user@your-server
The legacy application can then connect to localhost:2121 while traffic is securely tunneled.
Consider adding these to vsftpd.conf for defense-in-depth:
allow_writeable_chroot=YES
chroot_local_user=YES
userlist_enable=YES
userlist_deny=NO
This configuration:
- Restricts users to their home directories
- Implements explicit user whitelisting
- Maintains functionality while enhancing security
If connections fail, check:
- SELinux contexts (
restorecon -Rv /etc/vsftpd
) - Firewall rules even for localhost (
iptables -L -n -v
) - Proper file permissions for chrooted users