FTP is the abbreviation of File Transfer Protocol, a network protocol that was once widely used to move files between clients and servers. It has been replaced by faster, safer and more convenient file transfer methods. Many casual netizens want to download it directly from their web browser using https
, and it is easier for command line users to use secure protocols such as scp
or SFTP.
FTP is still used to support legacy applications and workflows with specific requirements. If you can choose which protocol to use, consider exploring more modern options. However, when you do need FTP, vsftpd is a good choice. vsftpd is optimized for security, performance and stability, can well prevent many security problems existing in other FTP servers, and is the default setting for many Linux distributions.
In this tutorial, we will show you how to configure vsftpd to allow a user to upload files to his or her home directory using FTP with SSL/TLS protected login credentials.
To follow this tutorial, you need:
Once you have an Ubuntu server, you can start.
We first update our package list and install the vsftpd daemon:
sudo apt-get update
sudo apt-get install vsftpd
After the installation is complete, we will copy the configuration file so that we can start with a blank configuration and save the original file as a backup.
sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig
By backing up the configuration, we are ready to configure the firewall. If you are using Tencent Cloud's CVM server, you can directly set it in Security Group in the Tencent Cloud console.
We will check the firewall status to see if it is enabled. If so, we will make sure to allow FTP traffic so that you don't encounter firewall rules that prevent you from testing.
sudo ufw status
In this case, only SSH is allowed:
Status: active
To Action From
------------
OpenSSH ALLOW Anywhere
OpenSSH(v6) ALLOW Anywhere(v6)
You may have other rules or no firewall rules at all. Since ssh
only allows traffic in this case, we need to add rules for FTP traffic.
We need to open ports 20 and 21 for FTP, port 990 for us to enable TLS in the future, and ports 40000-50000 for the passive port range we plan to set in the configuration file:
sudo ufw allow 20/tcp
sudo ufw allow 21/tcp
sudo ufw allow 990/tcp
sudo ufw allow 40000:50000/tcp
sudo ufw status
Now our firewall rules are as follows:
Status: active
To Action From
------------
OpenSSH ALLOW Anywhere
990 /tcp ALLOW Anywhere
20 /tcp ALLOW Anywhere
21 /tcp ALLOW Anywhere
40000:50000 /tcp ALLOW Anywhere
OpenSSH(v6) ALLOW Anywhere(v6)20/tcp(v6) ALLOW Anywhere(v6)21/tcp(v6) ALLOW Anywhere(v6)990/tcp(v6) ALLOW Anywhere(v6)40000:50000/tcp(v6) ALLOW Anywhere(v6)
With vsftpd
installed and the necessary ports opened, we are ready to proceed to the next step.
For this tutorial, we will create a user, but you may already have a user who needs FTP access. We will take care to retain existing users' access to the data in the following instructions. Even so, we recommend that you contact the new user before configuring and testing the settings.
First, we will add a test user:
sudo adduser sammy
Assign a password when prompted, you can press "ENTER" at other prompts.
When users are restricted to specific directories, FTP is usually more secure. vsftpd
uses chroot
jails to complete this step. When local users start chroot
, they will be restricted to their home directory by default. However, due to the way vsftpd
protects the directory, the user cannot write it. This is great for new users who should only connect via FTP, but existing users may need to write to their home folder (if they also have shell access).
In this example, we will create a ftp
directory as a chroot
, and create a writable files
directory to store actual files, instead of removing writable permissions from the home directory.
Create the ftp
folder, set its ownership, and make sure to remove write permissions with the following command:
sudo mkdir /home/sammy/ftp
sudo chown nobody:nogroup /home/sammy/ftp
sudo chmod a-w /home/sammy/ftp
Let's verify permissions:
sudo ls -la /home/sammy/ftp
total 84 dr-xr-xr-x 2 nobody nogroup 4096 Aug 2421:29.4 drwxr-xr-x 3 sammy sammy 4096 Aug 2421:29..
Next, we will create a directory where files can be uploaded and assign ownership to the user:
sudo mkdir /home/sammy/ftp/files
sudo chown sammy:sammy /home/sammy/ftp/files
A permission check on the files
directory should return the following:
sudo ls -la /home/sammy/ftp
Outputtotal 12
dr-xr-xr-x 3 nobody nogroup 4096 Aug 2614:01.
drwxr-xr-x 3 sammy sammy 4096 Aug 2613:59..
drwxr-xr-x 2 sammy sammy 4096 Aug 2614:01 files
Finally, we will add the file test.txt
to be used in future tests:
echo "vsftpd test file"| sudo tee /home/sammy/ftp/files/test.txt
Now that we have secured the ftp
directory and allowed users to access the files
directory, we turn our attention to configuration.
We plan to allow a single user with a local shell account to connect with FTP. Two key settings have been placed in vsftpd.conf
. First open the configuration file and verify that the settings in the configuration match the following settings:
sudo nano /etc/vsftpd.conf
...
# Allow anonymous FTP?(Disabled by default).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
local_enable=YES
...
Next, we need to change some values in the file. In order to allow users to upload files, we will uncomment the write_enable
setting so that we have:
...
write_enable=YES
...
We will also uncomment the chroot to prevent FTP connected users from accessing any files or commands outside the directory tree.
...
chroot_local_user=YES
...
We will add a user_sub_token
to insert the username in our local_root directory
path so that our configuration applies to this user and any future users that may be added.
user_sub_token=$USER
local_root=/home/$USER/ftp
We will limit the range of ports that can be used for passive FTP to ensure that enough connections are available:
pasv_min_port=40000
pasv_max_port=50000
**Note: **We pre-opened the ports we set here for the passive port range. If you change the value, be sure to update the firewall settings.
Since we only intend to allow FTP access based on specific circumstances, we will set up the configuration so that users can only be accessed when they are explicitly added to the list and not by default:
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO
userlist_deny
can switch logic. When it is set to "YES", the users in the list are denied FTP access. When it is set to "NO", only users in the list are allowed to access. After making changes, save and exit the file.
Finally, we will create users and add them to the file. We will use the -a
flag to append to the file:
echo "sammy"| sudo tee -a /etc/vsftpd.userlist
Double check that it was added as expected:
cat /etc/vsftpd.userlist
sammy
Restart the daemon to load configuration changes:
sudo systemctl restart vsftpd
Now we are ready to test.
We have configured the server to only allow the user sammy
to connect via FTP. Let us make sure this is the case.
Anonymous users should not be able to connect: We have disabled anonymous access. Here, we will test by trying to connect anonymously. If we have done it correctly, we should deny access to anonymous users:
ftp -p 203.0.113.0
Connected to 203.0.113.0.220(vsFTPd 3.0.3)Name(203.0.113.0:default): anonymous
530 Permission denied.
ftp: Login failed.
ftp>
Close the connection:
bye
The other user sammy should not be able to connect: Next, we will try to connect as the sudo
user. They should also be denied access, and it should happen before they are allowed to enter the password.
ftp -p 203.0.113.0
Connected to 203.0.113.0.220(vsFTPd 3.0.3)Name(203.0.113.0:default): sudo_user
530 Permission denied.
ftp: Login failed.
ftp>
Close the connection:
bye
sammy should be able to connect, as well as read and write files: Here, we will ensure that our designated users can connect:
ftp -p 203.0.113.0
Connected to 203.0.113.0.220(vsFTPd 3.0.3)Name(203.0.113.0:default): sammy
331 Please specify the password.
Password: your_user's_password
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
We will change to the files
directory, and then use the get
command to transfer the test file we created earlier to the local computer:
cd files
get test.txt
227 Entering Passive Mode(203,0,113,0,169,12).150 Opening BINARY mode data connection for test.txt(16 bytes).226 Transfer complete.16 bytes received in0.0101seconds(1588 bytes/s)
ftp>
We will turn right and try to upload a file with a new name to test write access:
put test.txt upload.txt
227 Entering Passive Mode(203,0,113,0,164,71).150 Ok to send data.226 Transfer complete.16 bytes sent in0.000894seconds(17897 bytes/s)
Close the connection:
bye
Now that we have tested our configuration, we will take steps to further protect our server.
Because FTP does not encrypt any data during transmission, including user credentials, we will enable TTL/SSL to provide encryption. The first step is to create an SSL certificate for vsftpd.
We will use openssl
to create a new certificate and use the -days
flag to make it valid for one year. In the same command, we will add a private 2048-bit RSA key. Then by setting the -keyout
and -out
flags to the same value, the private key and certificate will be in the same file.
We will use the following command to do this:
sudo openssl req -x509 -nodes -days 365-newkey rsa:2048-keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem
You will be prompted to provide the address information of the certificate. Replace your own information with the following questions:
Generating a 2048 bit RSA private key
............................................................................+++...........+++
writing newprivate key to '/etc/ssl/private/vsftpd.pem'-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.-----
Country Name(2 letter code)[AU]:US
State or Province Name(full name)[Some-State]:NY
Locality Name(eg, city)[]:New York City
Organization Name(eg, company)[Internet Widgits Pty Ltd]:DigitalOcean
Organizational Unit Name(eg, section)[]:
Common Name(e.g. server FQDN or YOUR name)[]: your_IP_address
Email Address []:
For more detailed information about certificate signs, please refer to Tencent Cloud SSL Certificate Service
After creating the certificate, open the vsftpd
configuration file again:
sudo nano /etc/vsftpd.conf
At the bottom of the file, you should have two lines starting with rsa_
. Comments make them look like:
# rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
# rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
Below them, add the following lines, which point to the certificate and private key we just created:
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
After that, we will force the use of SSL, which will prevent client connections that cannot handle TLS. This is necessary to ensure that all traffic is encrypted, but may force your FTP users to change the client. Change ssl_enable
to YES
:
ssl_enable=YES
After that, add the following line to explicitly reject anonymous connections over SSL and require SSL for data transmission and login:
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
After this, we configure the server to use TLS, which is the preferred successor to SSL, adding the following line:
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
Finally, we will add two options. First of all, we will not require the reuse of SSL because it may break many FTP clients. We will need a "high" encryption cipher suite, which currently means that the key length is equal to or greater than 128 bits:
require_ssl_reuse=NO
ssl_ciphers=HIGH
When finished, save and close the file.
Now, we need to restart the server for the changes to take effect:
sudo systemctl restart vsftpd
At this point, we will no longer be able to connect using insecure command line clients. If we tried, we would see something like:
ftp -p 203.0.113.0
Connected to 203.0.113.0.220(vsFTPd 3.0.3)Name(203.0.113.0:default): sammy
530 Non-anonymous sessions must use encryption.
ftp: Login failed.421 Service not available, remote server has closed connection
ftp>
Next, we will verify whether we can connect using a client that supports TLS.
Most modern FTP clients can be configured to use TLS encryption. We will demonstrate how to connect using FileZilla because it supports cross-platform. Please refer to the documentation of other customers.
When opening FileZilla for the first time, find the "Site Manager" icon below the text, which is the leftmost icon on the top line. click it:
A new window will open. Click the "New Site" button in the lower right corner:
Under "My Site", a new icon with the words "New Site" will appear. You can name it now or go back later and use the "Rename" button.
You must fill in the "Host" field with a name or IP address. Under the "Encryption" drop-down menu, select "Require explicit FTP over TLS".
For "Login Type", select "Ask Password". Fill in the FTP user you created in the "User" field:
Click "Connect" at the bottom of the interface. The system will ask you to enter the user password:
Click "OK" to connect. You should now use TLS/SSL encryption to connect with your server.
After you accept the certificate, double-click the files
folder and drag upload.txt to the left to confirm that you can download the file.
When you are done, right-click on the local copy, rename it to upload-tls.txt` and drag it back to the server to confirm that you can upload the file.
You have now confirmed that you can safely and successfully transfer SSL/TLS-enabled files.
If TLS cannot be used due to client requirements, you can gain some security by disabling FTP users to log in in any other way. A relatively simple method is to prevent it by creating a custom shell. This will not provide any encryption, but will restrict the infected account's access to FTP-accessible files.
First, open the file named ftponly
in the bin directory:
sudo nano /bin/ftponly
We will add a message to tell users why they cannot log in. Paste as follows:
#! /bin/sh
echo "This account is limited to FTP access only."
Change permissions to make the file executable:
sudo chmod a+x /bin/ftponly
Open the list of valid shells:
sudo nano /etc/shells
At the bottom, add:
... /bin/ftponly
Update the user's shell with the following command:
sudo usermod sammy -s /bin/ftponly
Now try to log in as sammy:
ssh [email protected]
You should see something like:
This account is limited to FTP access only.
Connection to 203.0.113.0 closed.
This confirms that users can no longer use ssh
to access the server, only FTP access.
In this tutorial, we covered setting up FTP for users with local accounts. If you need to use an external authentication source, you may need to understand vsftpd's support for virtual users. This provides a wealth of options through the use of PAM (pluggable authentication module), which is a good choice if you manage users in other systems (such as LDAP or Kerberos).
For more Ubuntu tutorials, please go to [Tencent Cloud + Community] (https://cloud.tencent.com/developer?from=10680) to learn more.
Reference: "How To Set Up vsftpd for a User's Directory on Ubuntu 16.04"
Recommended Posts