File Transfer Protocol (FTP), one of the oldest of Internet protocols, is still widely deployed, but it's the protocol sysadmins love to hate. Back in FTP's early days, the Internet was just a small network of computers where everyone knew everyone else, and FTP made little provision for security. Later revisions of the specification tried to add security features, but you can't fix an amputation with a Band-Aid. Fortunately, as we'll see, newer alternatives that are easy to deploy can replace FTP and provide the missing security.
So, what's wrong with FTP? To start with, it uses no encryption; user credentials and files are transferred in the clear, waiting to be intercepted by an attacker. You can add encryption by using SSL certificates, but this increases the complexity of the setup and the total cost; certificates from trusted authorities are not cheap.
By default FTP users are system users with valid shells. This makes targeting the FTP service a good starting point for hackers attempting to gain unauthorized access to a system. Most FTP servers support virtual users with usernames and passwords stored via LDAP (Lightweight Directory Access Protocol) and in databases such as PostgreSQL or MySQL. While this approach partially solves the problem with system users, it makes configuration and management a burden, especially on small-scale setups.
Managing access with a firewall is the first thing admins do when deploying new servers. Normally administrators start with a default policy of dropping all incoming connections except for the services they want the server to offer. FTP has two modes of operation: active and passive. In both modes the client initiates a connection to the TCP port number 21 on the server – otherwise known as command channel – but opening just that port is not enough to allow people to access a server. In active mode, when the client requests a file, the server makes a new connection back to the client and then transfers the data. This can cause problems if the client is behind a NAT gateway or a firewall. If you use FTP over SSL, things are even worse, since the client's firewall is not able to inspect the traffic and allow the connection. With passive mode, the client asks the server to pick a random port for the data connection and then connects to that port to transfer the requested files. Passive mode is becoming the default because it makes things smoother on the client side. However, to support it, you need to define a range of TCP port numbers in the FTP daemon configuration and open this range on your server's firewall. Each such open port is a potential attack vector.
Finally, the FTP service is yet another daemon running on your server for which you have to worry about possible security problems waiting to be discovered and exploited.
A better, secure alternative to FTP is probably already installed on your server: OpenSSH, the open source Secure Shell program suite that provides encrypted communications over insecure networks, such as the Internet itself. Out of the box the sshd daemon offers the SFTP service through the sftp-server subsystem – the "s" stands for "secure." With slight modifications to the configuration you can have users chrooted in their home directories accessing their files securely.
First, you need to make sure that sftp in installed on your system. On Debian and Ubuntu it is part of the openssh-client package, while CentOS administrators need to install the openssh-clients package. You need the sshd daemon too, of course; if it is not already installed, you can find it in the openssh-server package.
Create a system group called sftpusers and add the users you want to have sftp access to that group. Open the sshd_config configuration file; by default it's installed in /etc/ssh. Find the line that starts with Subsystem sftp and replace it with: Subsystem sftp internal-sftp; this will force the use of an in-process sftp server that requires no support files when used in chrooted directories. Then add the following lines to the end of the file, save it, and restart the sshd daemon:
Subsystem sftp internal-sftp
Match Group sftpusers ForceCommand internal-sftp ChrootDirectory %h X11Forwarding no AllowTcpForwarding no
This configuration forces the use of internal-sftp when members of the sftpusers group connect to the server, chrooting them inside their home directories. The last two lines disallow X11 forwarding (for running remote X applications) and TCP forwarding (or tunneling). Since only the SFTP service is provided to sftpusers members there's no need for forwardings.
The sftpusers members' home directories must have root ownership for chroot to work, and not be writable by any other user or group. For example, for the user somedomain whose home directory is located at /vhosts/somedomain.tld and contains the directories public_html and fcgi-bin, you should run the commands chown root:root /vhosts/somedomain.tld; chmod 755; chown -R somedomain:somedomain /vhosts/somedomain.tld/*; chmod 750 /vhosts/somedomain.tld/*. The last command ensures that only the somedomain user – and the members of the somedomain group (usually apache or www-data) – can access the contents of the public_html and fcgi-bin subdirectories.
chown root:root /vhosts/somedomain.tld; chmod 755; chown -R somedomain:somedomain /vhosts/somedomain.tld/*; chmod 750 /vhosts/somedomain.tld/*
Now you should be able to log in to your SFTP server from any desktop FTP client or even directly from the file manager of your OS; most modern file managers support SFTP out of the box.
With this setup none of the members of the sftpusers group can login via SSH, even if they're configured to use a valid shell, such as /bin/bash. However it is good practice to change their shell to a fake shell such as /sbin/nologin or /bin/false to block unauthorized access using other means, such as via remote KVM or web-based control panel.
If you use a web hosting control panel you can easily integrate this setup with your web hosting by defining all new hosting users to be members of the sftpusers group. You should also disable the FTP module from the control panel. I had no problem replacing FTP with SFTP this way on a few servers running Virtualmin.
What if you want to offer anonymous FTP access to the public for file downloads? You can instead serve these files directly over HTTP. For large files or busy servers you can switch to BitTorrent, saving bandwidth giving users faster downloads at the same time.
Replacing FTP with SFTP is an upgrade for your server security, but you can improve things further by utilizing standard practices for securing the SSH daemon. You should not allow it root access, and limit access to SSH and SFTP to members of the sftpusers and administrators groups. Open sshd_config and change PermitRootLogin yes to PermitRootLogin no. Also add this line: AllowGroups admins sftpusers, where admins is the name of the administrators group.
AllowGroups admins sftpusers
The most common threat to the SSH daemon is a dictionary-based brute force attack to its default TCP port 22. Of course you use secure passwords (right?) but such attacks are still annoying. Simply changing the port sshd listens for connections to something else, such as 2022, can partially stop this kind of attack. Change Port 22 to Port 2022 in sshd_config. To stop more sophisticated attacks on different ports, use software like DenyHosts that parses log files for repeated failed connection attempts and blocks connections accordingly. Or you can do what I do and stop attacks right on the firewall without wasting server resources running additional programs. The following iptables commands allow only three connections per minute per host, using the ipt_recent module. If this limit is exceeded, access is denied for that host for one minute, which is enough to stop most automated attacks without annoying users who insist on forgetting their passwords. All denied connections are also logged.
export _SSH_PORT="2022"iptables -A INPUT -p tcp --dport $_SSH_PORT -m state --state NEW -m recent --set --name ssh_bf -j ACCEPTiptables -A INPUT -p tcp --dport $_SSH_PORT -m recent --update --seconds 60 --hitcount 4 --rttl --name ssh_bf -j LOG --log-prefix "firewall; ssh_bf: "iptables -A INPUT -p tcp --dport $_SSH_PORT -m recent --update --seconds 60 --hitcount 4 --rttl --name ssh_bf -j DROP
You can run these commands directly on your shell and then use iptables-save or an iptables front-end program to save them with the rest of your firewall rules. Or you can simply paste them in the end of your /etc/rc.local file to have them run on boot-up.
FTP had a good run for many years but it is time for it to be replaced. OpenSSH has become the standard for accessing and administering remote systems securely. With this setup you can have a viable alternative without expending much effort and without needing to learn and deploy a new product.
Allowed tags: <a> link, <b> bold, <i> italics