(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’.
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.
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:
- Install vsftpd with your distribution’s package manager.
- Ensure that vsftpd starts at boot by using your distribution’s start-up manager.
- Open up the vsftpd configuration file and ensure that
- Disable anonymous FTP (optional): open up the vsftpd configuration file and ensure that
- 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
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 -I INPUT -p tcp --dport 21 -j ACCEPT iptables -I INPUT -p tcp --dport 60050:60100 -j ACCEPT iptables-save > /etc/sysconfig/iptables
ufw allow 21/tcp ufw allow 60050:60100/tcp
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
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:
To chroot specified FTP users, append the following to the vsftpd server configuration file and restart vsftpd:
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.
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 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:
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
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
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.