necrux - Blog

(S)FTP(S) or: How I Learned to Stop Worrying and Love File Transfer

File transfer is a fundamental concept of the Internet, however there are a plethora of configuration options that often lead to confusion. In this article I am going to discuss installation and configuration of FTP, FTPS, and SFTP as well as how to chroot (i.e. jail) users for these services.

FTP, The Basics

FTP is an atypical service due to the fact that it utilizes multiple ports (command and data) and has multiple modes (active and passive). For FTP the default command port will always be TCP port 21 and the default data port will be TCP port 20 for active connections only.

Below is a brief write-up on the different modes. If you are interested in a more thorough write-up of active versus passive FTP then I would highly recommend reading ‘Active FTP vs. Passive FTP, a Definitive Explanation’.

Active FTP

When using active FTP mode, the client will establish a connection from a random unprivileged TCP port to the server’s command port (TCP port 21). The server will then connect from it’s data port (TCP port 20) to the data port specified by the client. This often leads to problems since the client’s firewall will likely block the incoming data connection.

Passive FTP

When using passive FTP mode, the client will establish a connection from a random unprivileged TCP port to the server’s command port (TCP port 21). The server will then specify the TCP port that will be used for the data connection and the client connects to that port. The primary difference here is that the client establishes both the command and data connection, meaning that we are no longer concerned with the client’s firewall configuration. For most situations this will be the recommended configuration since you have control of the server’s firewall.

FTP, Installation and Configuration

There are several options available for an FTP server. In my examples I am going to be using the very secure FTP daemon, or vsftpd (don’t be fooled, FTP is not secure). The installation will vary depending on your Linux distribution, but the general steps are as follow:

  1. Install vsftpd with your distribution’s package manager.
  2. Ensure that vsftpd starts at boot by using your distribution’s start-up manager.
  3. Open up the vsftpd configuration file and ensure that write_enable=YES is set.
  4. Disable anonymous FTP (optional): open up the vsftpd configuration file and ensure that anonymous_enable=NO is set.
  5. Start the vsftpd service.

By default vsftpd will be using active FTP mode. You can change this by appending the following to the vsftpd configuration file, typically /etc/vsftpd/vsftpd.conf:

pasv_enable=Yes
pasv_min_port=60050
pasv_max_port=60100

Note: You can use whatever port range you like. The choice to use 60050-60100 is an arbitrary decision.

Lastly you will need to configure the firewall and restart the vsftpd service:

Iptables

iptables -I INPUT -p tcp --dport 21 -j ACCEPT
iptables -I INPUT -p tcp --dport 60050:60100 -j ACCEPT
iptables-save > /etc/sysconfig/iptables

UFW

ufw allow 21/tcp
ufw allow 60050:60100/tcp

FirewallD

firewall-cmd --add-service=ftp
firewall-cmd --add-service=ftp --permanent
firewall-cmd --add-port=60050-60100/tcp
firewall-cmd --add-port=60050-60100/tcp --permanent

Note: The above commands for FirewallD will amend the default zone. To add the rules to a different zone use the --zone=<zone> flag.

FTP, How to chroot (jail) Users

If you have a multi-user system you may decide to jail the users to their home directory, this is referred to as changing the root directory for the user, i.e. chroot the user. Depending on your needs there are 3 approaches: chroot all users, chroot specified users, or chroot users NOT specified.

To chroot all FTP users, append the following to the vsftpd server configuration file and restart vsftpd:

chroot_local_user=YES

To chroot specified FTP users, append the following to the vsftpd server configuration file and restart vsftpd:

chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list

Note: In this example, /etc/vsftpd/chroot_list is the list of users that are chrooted.

To chroot FTP users NOT specified, append the following to the vsftpd server configuration file and restart vsftpd:

chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list

Note: In this example, /etc/vsftpd/chroot_list is the list of users that are NOT chrooted.

FTPS

FTP is extremely convenient but it is important to remember that communication over FTP is not encrypted, making it less than ideal for modern day usage. If you decide to implement FTP in your environment then it is highly recommended that you secure the communication with TLS, i.e. FTPS. All of the above concepts still apply to FTPS, we are simply adding a layer of security. To get started you will first want to generate an SSL certificate:

mkdir -p /etc/ssl/private/; pushd $_
openssl req -subj '/CN=EXAMPLE.COM' -x509 -nodes -days 365 -newkey rsa:2024 -sha256 -keyout vsftpd.key -out vsftpd.crt; popd

Once the SSL certificate and key have been created, append the following to the end of the vsftpd server configuration file:

rsa_cert_file=/etc/ssl/private/vsftpd.crt
rsa_private_key_file=/etc/ssl/private/vsftpd.key
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=YES
ssl_ciphers=HIGH

Note: The above set-up forces secure connections, only supports TLS, and requires secure ciphers. If the client(s) does not support this set-up then the configuration may require additional tweaking.

SFTP

SFTP is completely different than FTP/FTPS. It is simply file transfer over SSH; it only uses TCP port 22 and does not have different modes. In fact any user that has SSH access to the system already has full use of SFTP!

SFTP only requires additional configuration if you decide to revoke shell access and chroot them to their home directory. To do so requires the use of SSH Match statements; something that is not supported on older versions of OpenSSH. To find out more about SSH Match statements and what systems support it, refer to this article.

First create an sftp only group:

groupadd sftponly

Next add/modify your users:

useradd -s /bin/false -G sftponly <user>
passwd <user>

And lastly you will need to make a few changes to the SSH server configuration (/etc/ssh/sshd_config) and restart SSH.

Comment out this line:

Subsystem sftp /usr/lib/openssh/sftp-server

And append these lines:

Subsystem sftp internal-sftp

Match Group sftponly
     ChrootDirectory %h
     X11Forwarding no
     AllowTCPForwarding no
     ForceCommand internal-sftp

Troubleshooting

In order for SFTP to work correctly, the directory that the user to chrooted to MUST be owned by root:root with permissions no greater than 755; facls will not work either. Fortunately permission issues for SFTP are easily identified by looking through /var/log/secure!

Because of the ownership/permissions required for chrooting, it is very important to consider directory structure when implementing a chrooted environment. One possible solution is to bind mount any content required by that user to their home directory and changing it’s group ownership accordingly. When chrooting with vsftpd, it is also important to make sure the user’s shell is listed in /etc/shells as PAM builds of the service enforce the check_shells parameter.

Regardless of what solution you choose to implement for file transfer, it is of the utmost importance that you test the solution! There are plenty of command line options available to test with (ftp, ftp-ssl, and sftp), or else you can use a GUI like Filezilla. Testing the solution takes very little time and will save you headaches down the road.