How to Configure Encrypted FTP for Your Web Server

Updated on September 3, 2020
How to Configure Encrypted FTP for Your Web Server header image

Introduction

This guide explains how to set up vsftpd (Very Secure File Transfer Protocol Daemon), which allows users to upload files via FTPS (also known as FTP-SSL and FTP Secure). This guide is written for the Vultr One-Click LAMP server on Ubuntu 18.04 using a free Let's Encrypt SSL/TLS certificate. With minor modifications, you can adapt this guide to any server distribution with vsftpd in their repository, and use Apache or Nginx.

Prerequisites

1. Install vsftpd

Update the local package index.

$ sudo apt update

Install the vsftpd daemon.

$ sudo apt install vsftpd

2. Configure the Firewall

UFW, or Uncomplicated Firewall, is installed by default on Ubuntu systems. If it is enabled, open the necessary ports: 20 and 21 for FTP, 40000-50000 for passive FTP, and 990 for TLS.

$ sudo ufw allow 20/tcp
$ sudo ufw allow 21/tcp
$ sudo ufw allow 40000:50000/tcp
$ sudo ufw allow 990/tcp
$ sudo ufw status

If the firewall is enabled, the rules should look like this:

Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Apache Full                ALLOW       Anywhere
20/tcp                     ALLOW       Anywhere
21/tcp                     ALLOW       Anywhere
40000:50000/tcp            ALLOW       Anywhere
990/tcp                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Apache Full (v6)           ALLOW       Anywhere (v6)
20/tcp (v6)                ALLOW       Anywhere (v6)
21/tcp (v6)                ALLOW       Anywhere (v6)
40000:50000/tcp (v6)       ALLOW       Anywhere (v6)
990/tcp (v6)               ALLOW       Anywhere (v6)

3. Configure FTP Access

  1. Create a dedicated user to log in to FTP, and use a strong password.

     $ sudo adduser ftpaccess
  2. For increased security, block this user from logging in via SSH.

     $ sudo nano /etc/ssh/sshd_config
  3. Add the following line to the bottom of the file.

     DenyUsers ftpaccess
  4. Save and exit the file.

  5. Restart SSH to enforce the changes.

     $ sudo service sshd restart
  6. Set the home directory to the folder above the default webroot. vsftpd restricts the user's access to their specific home directory using chroot jails and requires that the directory be not writable by the user. For Apache, the default webroot is /var/www/html.

     $ sudo usermod -d /var/www ftpaccess
  7. Set the ownership of the webroot to the FTP user.

     $ sudo chown ftpaccess:ftpaccess /var/www/html
  8. Verify the permissions of the directory.

     $ sudo ls -la /var/www/html

4. Configure vsftpd

  1. Open the configuration file for vsftpd.

     $ sudo nano /etc/vsftpd.conf
  2. Ensure anonymous FTP access is disabled and local users can log in.

     #
     # Allow anonymous FTP? (Disabled by default).
     anonymous_enable=NO
     #
     # Uncomment this to allow local users to log in.
     local_enable=YES
     #
  3. Uncomment these lines to allow the FTP user to upload files, and prevent them from accessing any files outside of their home directory.

     write_enable=YES
     local_umask=022
     chroot_local_user=YES
  4. Add force_dot_files=YES in the file to show hidden files such as .htaccess.

     force_dot_files=YES
  5. Set the range of ports available for passive FTP. Make sure these values match the firewall settings added in Step 2.

     pasv_min_port=40000
     pasv_max_port=50000
  6. Restrict FTP access to users specified in /etc/vsftpd.userlist.

     userlist_enable=YES
     userlist_file=/etc/vsftpd.userlist
     userlist_deny=NO
  7. Save and exit the file.

  8. Edit /etc/vsftpd.userlist.

     $ sudo nano /etc/vsftpd.userlist
  9. Add the ftpaccess user to the file.

     ftpaccess
  10. Save and exit the file.

  11. Restart vsftpd to load the changes.

    $ sudo systemctl restart vsftpd

You should be able to log in with any FTP client as the ftpaccess user, but the server is un-encrypted. Continue with Step 5 to set up encryption.

5. Encrypt Transactions

By default, FTP does not encrypt credentials or data in transit. Follow these steps to use the server's Let's Encrypt certificate to secure the connection. You can follow our guide to obtain a Let's Encrypt certificate for a LAMP server if you need to install one first.

  1. Edit the vsftpd configuration file.

     $ sudo nano /etc/vsftpd.conf
  2. Find the two lines beginning with rsa_ and comment them out by adding # at the beginning.

     #rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
     #rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
  3. Add the following lines. Adjust the pathname to match the location of the server's certificate files.

     rsa_cert_file=/etc/letsencrypt/live/example.com/fullchain.pem
     rsa_private_key_file=/etc/letsencrypt/live/example.com/privkey.pem
  4. Add this line to allow clients that can't connect over TLS to use SSL.

     ssl_enable=YES
  5. Deny anonymous connections and force a secure connection by adding the following lines.

     allow_anon_ssl=NO
     force_local_data_ssl=YES
     force_local_logins_ssl=YES
  6. Specify which protocols to use. For security, allow TLS and block older versions of SSL.

     ssl_tlsv1=YES
     ssl_sslv2=NO
     ssl_sslv3=NO
  7. Add the following to use strong encryption methods.

     ssl_ciphers=HIGH
  8. Do not require the reuse of SSL sessions. Setting this to yes may interfere with many FTP clients.

     require_ssl_reuse=NO
  9. Add the ports used for passive FTP.

     pasv_min_port=40000
     pasv_max_port=50000
  10. Save and exit the file.

  11. Restart the server.

    $ sudo systemctl restart vsftpd

7. Verify Encrypted FTP

A good verification test is to attempt a connection with the default command-line ftp client, which will fail because it doesn't support encryption.

  1. Connect using command-line ftp from a different machine.

     $ ftp example.com
  2. Enter the username when prompted and ensure access is denied.

     530 Non-anonymous sessions must use encryption.
     ftp: Login failed.
  3. With a client that supports FTPS, such as FileZilla or Cyberduck, connect to the server and check the connection log. You should find entries similar to this:

     Status: Connection established, waiting for welcome message...
     Status: Initializing TLS...
     Status: Verifying certificate...
     Status: TLS connection established.

Conclusion

You can now securely connect to your server via FTPS and upload files to your website directory.