
Here I will show how to configure VSFTPD for basic authentication so that we have a base working daemon. Then we will build on that by implementing SSL and then virtual users.
Obviously first thing is first ;) If you haven't already, install vsftpd.
emerge -av vsftpd ... net-ftp/vsftpd-3.0.2-r1::gentoo USE="pam ssl tcpd -caps (-selinux) -xinetd"
We want to enable pam and ssl for later on. Once done, pop this into /etc/vsftpd/vsftpd.conf
################## # Basic Settings # ################## anonymous_enable=NO dirmessage_enable=YES xferlog_enable=YES vsftpd_log_file=/var/log/vsftpd.log connect_from_port_20=YES xferlog_file=/var/log/vsftpd.log data_connection_timeout=120 nopriv_user=ftp ftpd_banner=Insert Welcome Message listen=YES listen_address=<server IP> listen_port=21 ############### # Local Users # ############### local_enable=YES write_enable=YES chroot_local_user=YES passwd_chroot_enable=YES allow_writeable_chroot=NO userlist_enable=YES userlist_deny=NO userlist_file=/etc/vsftpd/vsftpd.user_list
The above will tell vsftpd to not allow any anonymous connections eg mandatory login. What and where to log. What IP and port to listen on. To lock users into their home directory (defined in /etc/passwd).
The bottom 3 lines userlist_* we define so we don't grant all local users ftp access. If you answer YES to userlist_deny, the user list will deny any users listed in the file and allow everything else.
cat /etc/vsftpd/vsftpd.user_list user1 user2 user3
Restart vsftpd to activate the new config.
Let's test and make sure everything is working.
$ ftp cdstealer.com Connected to cdstealer.com (<IP>). 220 (vsFTPd 3.0.2) Name (cdstealer.com:user1): 530 Please login with USER and PASS. SSL not available 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp>
SSL
So let's get some encryption so we aren't transmitting plain text credentials.
Generate a self signed cert.
# openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout /etc/ssl/apache2/vsftp.pem -out /etc/ssl/apache2/vsftp.pem Generating a 4096 bit RSA private key ..........................................................................................++ ....++ writing new private key to '/etc/ssl/apache2/vsftp.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]:GB State or Province Name (full name) [Some-State]:Somewhere nice Locality Name (eg, city) []:Leeds Organization Name (eg, company) [Internet Widgits Pty Ltd]:cdstealer.com Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:cdstealer.com Email Address []:
The openssl command I've used, generates a 4096bit encrypted cert (this is good) that is valid for 10 years. :)
Execute the following to remove unwanted access to the cert.
chmod 600 /etc/ssl/apache2/vsftp.pem
Add this section to your /etc/vsftpd/vsftpd.conf file.
##############
# Enable SSL #
##############
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
require_ssl_reuse=NO
ssl_tlsv1=NO
ssl_sslv2=NO
ssl_sslv3=NO
implicit_ssl=NO
ssl_ciphers=TLSv1.2+HIGH:TLSv1.3+HIGH:@STRENGTH:!eNULL:!aNULL
rsa_cert_file=/etc/letsencrypt/live/cdstealer.com/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/cdstealer.com/privkey.pem
Restart vsftpd to activate the new config.
Let's test and make sure everything is still working.
$ ftp cdstealer.com Connected to cdstealer.com (<IP>). 220 (vsFTPd 3.0.2) Name (cdstealer.com:user1): 234 Proceed with negotiation. [SSL Cipher AES128-SHA] 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp>
GREAT! So now we have a secure FTP service running.
Extra Options:
################## # Other Settings # ################## dirlist_enable=YES download_enable=YES force_dot_files=NO hide_ids=YES max_clients=2 max_per_ip=2 ####################### # Passive Connections # ####################### pasv_enable=YES pasv_address=<domainname> pasv_min_port=63899 pasv_max_port=63999 pasv_addr_resolve=YES
Virtual Users:
In the interest of security, I'm not comfortable having system user accounts, even though we have secured things with only specific users able to ftp. I believe that standard ftp authentication does not support encryption for system users, but does for virtual users?
This is a little more involved than having standard system users :(
So, add the following to your /etc/vsftpd/vsftpd.conf file.
################## ## Virtual Users # ################## virtual_use_local_privs=YES pam_service_name=vsftpd user_sub_token=$USER local_root=/FTP/$USER secure_chroot_dir=/var/run/vsftpd guest_enable=YES guest_username=ftp user_config_dir=/etc/vsftpd/virtualUsers
Here we define that virtual users get the same permissions as the ftp system user, are unable to browse outside their directory, use a PAM database for credentials and define custom settings per user.
Create the PAM config.
vi /etc/pam.d/vsftpd
Populate with the following.
auth required /lib/security/pam_userdb.so db=/etc/vsftpd/virtualUsers account required /lib/security/pam_userdb.so db=/etc/vsftpd/virtualUsers session required /lib/security/pam_loginuid.so
pam_userdb.so is part of pam, so nothing else to do.
Create user database.
cd /etc/vsftpd vi virtualUsers.txt
The format of this file is:
username password username password <empty line>
Execute the following to create the database.
db5.3_load -T -t hash -f /etc/vsftpd/virtualUsers.txt /etc/vsftpd/virtualUsers.db
Update the permissions.
chmod 600 virtualUsers.txt virtualUsers.db
NOTE: You may notice that the file extension is missing from the path in /etc/pam.d/vsftpd. This is intentional as PAM automatically adds the .db suffix.
You will need to add the users from the database to the access list file.
/etc/vsftpd/vsftpd.user_list
For your convenience, I've written a user management script, here :)
Define custom settings.
Create the directory which will store the configs. We defined this earlier as user_config_dir=/etc/vsftpd/virtualUsers.
mkdir /etc/vsftpd/virtualUsers
Create a user config.
vi /etc/vsftpd/virtualUsers/user1 write_enable=NO local_root=/FTP/user1 chroot_local_user=YES dirlist_enable=YES download_enable=YES
Here we set the users CHROOT directory, deny write permissions and allow downloading. Options here (not all) override specific options defined in the main config.
RTFM
NOTES:
If you get the following when logging in or listing a directory, it maybe due to the user directory not existing or not having permission.
ssl_getc: SSL_read failed -1 = 0 421 Service not available, remote server has closed connection Login failed. No control connection for command: Success
The following error may occur on ftp clients with vsftpd 3.0.x:
500 OOPS: priv_sock_get_cmd
This is caused by seccomp filter sanboxing, which is enabled by default on amd64. To workaround this issue, disable seccomp filter sanboxing:
Add the following line to /etc/vsftpd/vsftpd.conf.
seccomp_sandbox=NO
Don't forget to restart vsftpd :)