This example shows how you might set up a large internet facing FTP site for distributing file or software updates. The emphasis will be on security and performance. VSFTPD will make sure only world-readable files and directories are served to the world via anonymous / ftp account. You force to originates FTP port connections from a secure port - so users on the FTP server cannot try and fake file content. You will hide the FTP server user IDs and just display ftp in directory listings. This is also a performance boost. Set a 40000-60000 port range for passive connections. This will help firewall setup.
- The default port - 21 and 20
- The default directory to upload your files - /var/ftp/pub for anonymous access. By default all users are chrooted to /var/ftp and they are not allowed to change the directory.
- Anonymous login details - Use anonymous / anonymous or ftp / ftp as username / password combo.
FTP Server Configuration
Edit the vsftpd configuration file, enter:
# vi /etc/vsftpd/vsftpd.conf
Add or correct the following configuration option:
Only allow anonymous access ftp access:
Disable local users login to ftp server:
Disable upload files and writing permission on the FTP server:
write_enable=NO anon_upload_enable=NO anon_mkdir_write_enable=NO anon_other_write_enable=NO
Only allow file reading permission to the rest of the world:
anon_world_readable_only=YES connect_from_port_20=YES hide_ids=YES pasv_min_port=40000 pasv_max_port=60000
Turn on log features
xferlog_enable=YES # Do not allow the use of "ls -R" to avoid consume a lot of resources ls_recurse_enable=NO ascii_download_enable=NO async_abor_enable=YES
Set performance option:
# Uses one process per connection to gain performance. # This is used to supports huge numbers of simultaneously connected users. one_process_model=YES # The timeout, in seconds, which is the maximum time a remote client may spend # between FTP commands. If the timeout triggers, the remote client is kicked off. idle_session_timeout=120 # The timeout, in seconds, which is roughly the maximum time we permit data # transfers to stall for with no progress. If the timeout triggers, the remote client # is kicked off. data_connection_timeout=300 # The timeout, in seconds, for a remote client to establish connection with # a PASV style data connection. accept_timeout=60 # The timeout, in seconds, for a remote client to respond to our PORT # style data connection. connect_timeout=60 # The maximum data transfer rate permitted, in bytes per second, # for anonymous clients. anon_max_rate=50000
Restart the ftp server:
# service vsftpd restart
Sample Iptables Rules to Open Passive FTP Port Ranges
Add the following rules to your firewall shell script:
$IPT -I INPUT -m state --state NEW -j ACCEPT -p tcp -m multiport --ports 40000:60000
If you are using /etc/sysconfig/iptables, add the following lines, ensuring that they appear before the final LOG and DROP lines for the RH-Firewall-1-INPUT:
-A RH-Firewall-1-INPUT -m state --state NEW -j ACCEPT -p tcp -m multiport --ports 40000:60000
Save and close the file. Restart the firewall and vsftpd:
# service vsftpd restart
# service iptables restart
FTP Server Protected by an External *BSD PF Firewall Running NAT
In this case, the firewall must redirect traffic to the VSVTPD FTP server (running on RHEL) in addition to not blocking the required ports. In order to accomplish this, you need to use ftp-proxy.
ftp-proxy can be run in a mode that causes it to forward all FTP connections to a specific FTP server. Basically we'll setup the proxy to listen on port 21 of the firewall and forward all connections to the back-end server.
Edit /etc/rc.conf.local (FreeBSD use should use /etc/rc.conf) and add the following:
ftpproxy_flags="-R 10.1.3.100 -p 21 -b 192.168.1.1"
- 10.1.3.100 - the IP address of the actual RHEL VSFTPD FTP server.
- 21 - the port we want ftp-proxy to listen on
- 192.168.1.1 - the address on the firewall that we want the proxy to bind to.
Next, pdate your /etc/pf.conf as follows:
ext_ip = "192.168.1.1" ftp_server_ip = "10.1.3.100" nat-anchor "ftp-proxy/*" nat on $ext_if inet from $int_if -> ($ext_if) rdr-anchor "ftp-proxy/*" pass in on $ext_if inet proto tcp to $ext_ip port 21 flags S/SA keep state pass out on $int_if inet proto tcp to $ftp_ip port 21 user proxy flags S/SA keep state anchor "ftp-proxy/*"
Restart pf firewall:
# pfctl -nf /etc/pf.conf && pfctl -f /etc/pf.conf