How to Configure Encrypted FTP for Your Web Server
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
- A One-Click LAMP server configured with a Fully Qualified Domain Name (FQDN).
- A free Let's Encrypt certificate pointing to your domain name.
- A non-root user with sudo privileges.
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
Create a dedicated user to log in to FTP, and use a strong password.
$ sudo adduser ftpaccess
For increased security, block this user from logging in via SSH.
$ sudo nano /etc/ssh/sshd_config
Add the following line to the bottom of the file.
DenyUsers ftpaccess
Save and exit the file.
Restart SSH to enforce the changes.
$ sudo service sshd restart
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
Set the ownership of the webroot to the FTP user.
$ sudo chown ftpaccess:ftpaccess /var/www/html
Verify the permissions of the directory.
$ sudo ls -la /var/www/html
4. Configure vsftpd
Open the configuration file for
vsftpd
.$ sudo nano /etc/vsftpd.conf
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 #
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
Add
force_dot_files=YES
in the file to show hidden files such as.htaccess
.force_dot_files=YES
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
Restrict FTP access to users specified in
/etc/vsftpd.userlist
.userlist_enable=YES userlist_file=/etc/vsftpd.userlist userlist_deny=NO
Save and exit the file.
Edit
/etc/vsftpd.userlist
.$ sudo nano /etc/vsftpd.userlist
Add the ftpaccess user to the file.
ftpaccess
Save and exit the file.
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.
Edit the
vsftpd
configuration file.$ sudo nano /etc/vsftpd.conf
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
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
Add this line to allow clients that can't connect over TLS to use SSL.
ssl_enable=YES
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
Specify which protocols to use. For security, allow TLS and block older versions of SSL.
ssl_tlsv1=YES ssl_sslv2=NO ssl_sslv3=NO
Add the following to use strong encryption methods.
ssl_ciphers=HIGH
Do not require the reuse of SSL sessions. Setting this to yes may interfere with many FTP clients.
require_ssl_reuse=NO
Add the ports used for passive FTP.
pasv_min_port=40000 pasv_max_port=50000
Save and exit the file.
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.
Connect using command-line
ftp
from a different machine.$ ftp example.com
Enter the username when prompted and ensure access is denied.
530 Non-anonymous sessions must use encryption. ftp: Login failed.
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.