ftp server on ubuntu 20.04 using vsftpd

This article describes how to install and configure the FTP server you use to share files between devices on Ubuntu 20.04.

FTP (File Transfer Protocol) is the standard network protocol used to transfer files to a remote network. There are several open source FTP servers available for Linux. The most famous and widely used ones are pureftpd, Proftpd, VSFTPD. We will install VSFTPD (VSFTPD daemon), a stable, secure and fast FTP server. We will also show you how to configure the server to restrict users to its home directory and encrypt the entire transfer using SSL/TLS.

Although FTP is a very popular protocol, for more secure and faster data transfer, you should use SCP or SFTP.

Installing VSFTPD on Ubuntu 20.04

The VSFTPD package is available in the Ubuntu repository. To install it, execute the following command.

1
2
sudo apt update
sudo apt install vsftpd

Once the installation process is complete, the FTP service will start automatically. To verify it, print the service status.

1
sudo systemctl status vsftpd

The output should show that the VSFTPD service is active and running.

1
2
3
4
● vsftpd.service - vsftpd FTP server
     Loaded: loaded (/lib/systemd/system/vsftpd.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2021-03-02 15:17:22 UTC; 3s ago
...

Configuring VSFTPD

VSFTPD server configuration is stored in the /etc/vsftpd.conf file.

Most server settings are in the file. For all available options, please visit the VSFTPD documentation page.

In the following sections, we will describe some important settings needed to configure a secure VSFTPD installation.

First open the VSFTPD configuration file.

1
sudo nano /etc/vsftpd.conf

FTP access

We only allow access to the FTP server for local users. Search for the anonymous_enable and local_enable directives and verify that your configuration matches the following lines.

/etc/vsftpd.conf

1
2
anonymous_enable=NO
local_enable=YES

Enable uploads

Locate and uncomment the write_enable directive to allow file system changes, such as uploading and deleting files.

/etc/vsftpd.conf

1
write_enable=YES

Chroot Jail

To prevent local FTP users from accessing files outside their home directory, uncomment from chroot_local_user.

/etc/vsftpd.conf

1
chroot_local_user=YES

By default, for security reasons, when chroot is enabled, VSFTPD will refuse to upload files if the user’s locked directory is writable.

Use one of the following solutions to allow uploading when chroot is enabled.

Option 1. The recommended option is to keep chroot enabled and configure the FTP directory. In this example, we will create an ftp directory in the user home page that will be used as chroot and the writable uploads directory for uploading files: /etc/vsftp.

/etc/vsftpd.conf

1
2
anonymous_enable=NO
local_enable=YES

Option 2. Another option is to enable the allow_writeable_chroot command.

/etc/vsftpd.conf

1
allow_writeable_chroot=YES

Your user to its home directory Use this option only if you must grant writable access.

Passive FTP connection

By default, VSFTPD uses active mode. To use passive mode, set the minimum and maximum range of ports:

/etc/vsftpd.conf

1
2
pasv_min_port=30000
pasv_max_port=31000

You can use any port for passive FTP connections. When passive mode is enabled, the FTP client opens a connection to the server on a random port in the selected range.

Restrict user logins

You can configure VSFTPD to allow only certain users to log in. To do this, add the following line to the end of the file.

/etc/vsftpd.conf

1
2
3
 userlist_enable=YES
userlist_file=/etc/vsftpd.user_list
userlist_deny=NO

When enabling this option, you need to explicitly specify the user name to be added to the /etc/vsftpd.user_list file (one user per line) to specify the logged in user.

Use SSL/TLS encrypted transfers

To encrypt FTP transfers via SSL/TLS, you need to have an SSL certificate and configure your FTP server to use it.

You can use an existing SSL certificate signed by a trusted certificate authority or create a self-signed certificate.

If you have a domain or subdomain that points to the IP address of your FTP server, you can quickly generate a free Let’s Encrypt SSL certificate.

We will generate a 2048-bit private key and self-signed SSL certificate, which is valid for ten years.

1
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem

Both the private key and the certificate will be saved in the same folder.

Once the SSL certificate is created, open the VSFTPD configuration file.

1
sudo nano /etc/vsftpd.conf

Find the rsa_cert_file and rsa_private_key_file directives, change their values to the pam file path, and set the ssl_enable directive to YES:

/etc/vsftpd.conf

1
2
3
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES

Restart VSFTPD service

After completing the edits, the VSFTPD configuration file (excluding comments) should look as follows.

/etc/vsftpd.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
listen=NO
listen_ipv6=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES
user_sub_token=$USER
local_root=/home/$USER/ftp
pasv_min_port=30000
pasv_max_port=31000
userlist_enable=YES
userlist_file=/etc/vsftpd.user_list
userlist_deny=NO

Save the file and restart the VSFTPD service to make the changes to take effect.

1
sudo systemctl restart vsftpd

Open firewall

If you are running the UFW firewall, you need to allow FTP traffic.

Open port 21 (FTP command port), port 20 (FTP data port) and 30000-31000 (passive port range) and run the following commands.

1
2
sudo ufw allow 20:21/tcp
sudo ufw allow 30000:31000/tcp

To avoid being locked out, make sure port 22 is open.

1
sudo ufw allow OpenSSH

Reload UFW rules by disabling and re-enabling UFW.

1
2
sudo ufw disable
sudo ufw enable

Validate changes.

1
sudo ufw status
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Status: active

To                         Action      From
--                         ------      ----
20:21/tcp                  ALLOW       Anywhere
30000:31000/tcp            ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
20:21/tcp (v6)             ALLOW       Anywhere (v6)
30000:31000/tcp (v6)       ALLOW       Anywhere (v6)
OpenSSH (v6)               ALLOW       Anywhere (v6)

Create FTP user

To test the FTP server, we will create a new user.

  • If the user to be granted FTP access already exists, skip step 1.
  • If allow_writeable_chroot=YES is set in the configuration file, skip step 3.

Create a new user named newftpuser.

1
sudo adduser newftpuser

Add the user to the list of allowed FTP users.

1
echo "newftpuser" | sudo tee -a /etc/vsftpd.user_list

Create the FTP directory tree and set the correct permissions.

1
2
3
4
sudo mkdir -p /home/newftpuser/ftp/upload
sudo chmod 550 /home/newftpuser/ftp
sudo chmod 750 /home/newftpuser/ftp/upload
sudo chown -R newftpuser: /home/newftpuser/ftp

As described in the previous section, users will be able to upload their files to the ftp/upload directory.

At this point, your FTP server is fully functional. You should be able to connect to the server using any FTP client that can be configured to use TLS encryption, such as Filezilla.

Disable shell access

By default, when creating a user, if not explicitly specified, the user will have SSH access to the server. To disable shell access, create a new shell that will print a message telling the user that their account is restricted to ftp access.

Run the following command to create the /bin/ftponly file and make it executable.

1
2
echo -e '#!/bin/sh\necho "This account is limited to FTP access only."' | sudo tee -a  /bin/ftponly
sudo chmod a+x /bin/ftponly

Append the new shell to the list of valid shells in the /etc/shells file.

1
echo "/bin/ftponly" | sudo tee -a /etc/shells

Change the user shell to /bin/ftponly.

1
sudo usermod newftpuser -s /bin/ftponly

You can use the same command to change the shell for all users who want to provide FTP access only.