How To Configure vsftpd to Use SSL/TLS and virtual users
Introdution
This tutorial covers the steps for installing and configuring vsftpd with virtual users, including enabling TLS encryption.
- What is the difference between FTP , FTPS and SFTP we learned in the last article Understanding Key Differences Between FTP, FTPS and SFTP
- We also need to recognize the difference between active and passive ftp connections
Configure VSFTPd server
Install vsftpd server and pam service
First you need vsftp and PAM with htpasswd utility support installed
~] apt-get install vsftpd libpam-pwdfile apache2-utils
Configure pam for vsftpd
Linux Pluggable Authentication Modules (PAM) provide dynamic authentication support for applications and services in a Linux or GNU/kFreeBSD system.
We need to modify PAM to support login virtual users in vsftpd server. Open /etc/pam.d/vsftpd file and remove everything inside this file and replace with the following:
~] vi /etc/pam.d/vsftpd
# first, remove all content and add this config:
auth required pam_pwdfile.so pwdfile /etc/vsftpd/ftpd.passwd
account required pam_permit.so
What is virtual user
A virtual user is, quite simply, a user that is not defined in the system /etc/passwd file. The /etc/passwd file is a text-based database of information about users that may log into the system and contain unique ID for each user. Virtual users are defined in e.g. another file, or in database or ldap server.
Defining users outside of /etc/passwd means that system utilities like ls and chown do not work as expected. When the administrator lists the files uploaded by virtual users, those files will have the wrong owner names or show only UID number.
By default, ls lists the names of file owners by looking up those names in /etc/passwd . This is why listing files of virtual users will often show incorrect names; ls has no knowledge of virtual user names. When working with files created by virtual users, use ls -n so that you can see the UIDs , not the names, associated with those files. You will then need to manually make sure those UIDs are the correct ones for the file.
Which UIDs
should I use for my virtual users? It does not matter. The only UID
and GID
which are special are UID 0 (zero) and GID 0 (zero). These UID
is used for user root
and group root
; do not assign these UID
to your virtual users unless you absolutely trust those users.
Other than that, you are free to use any UIDs you like. It is generally a good idea to use UIDs for your virtual users that are not already in use in /etc/passwd , in order to keep the privileges of your system users separate from the privileges of your virtual users; privileges are determined by UIDs . However, in some cases (such as using ProFTPd for FTP access to websites), you may want all of your virtual users to run as the web server user, e.g. user "www-data" or user "http". Use the UIDs that make the most sense for your site needs.
One related question often asked is "Can I have my virtual users have the same UIDs?" Yes, you can. This means that all of those virtual users would have the exact same privileges. If you use this approach, make sure those virtual users are all confined to separate home (or web site) directories by using DefaultRoot ~
in your proftpd.conf
. This means that even though those virtual users would all have the same privileges, they would be unable to see and affect each others' files since they would all be separated in different directories.
Configure virtual users
make a directory to store your users:
~] mkdir /etc/vsftpd
and create first user with name user1:
root@server1:~] cd /etc/vsftpd
root@server1:/etc/vsftpd] htpasswd -cd /etc/vsftpd/ftpd.passwd user1
adding additional users just omit the -c
root@server1:/etc/vsftpd] htpasswd -d /etc/vsftpd/ftpd.passwd user2
I've only managed to get it to work using CRYPT which limits to 8 chars to use more than 8 chars use openssl to generate a compatible hash and pipe directly into htpasswd
htpasswd -c -p -b /etc/vsftpd/ftpd.passwd user1 $(openssl passwd -1 -noverify password)
or create password hash manual with openssl passwd command with password writing to console stdin:
~] openssl passwd -1 -noverify -stdin
password
$1$cqBxTqpx$qv35PObXRQmmGFcTODUAd0
And than edit ftpd.passwd file manual
root@server1:/etc/vsftpd] cat /etc/vsftpd/ftpd.passwd
user1:$1$squU2udc$eD/FoLKBxizDZXns5SIfl.
user2:$1$3AHhdjzS$knEihwU7gjnI2OtZE5BiT1
Configure vsftpd virtual users home directory
You must setup a home directory for all virtual users. Create file with name as virtual username and write full path with local_root=
prefix to home directory for such user.
~] ls -alFh /etc/vsftpd
-rw-r--r-- 1 root root 39 Jul 13 14:10 user1
-rw-r--r-- 1 root root 39 Jul 13 14:15 user2
-rw-r--r-- 1 root root 49 Jul 13 13:59 ftpd.passwd
~] cat user1
local_root=/var/www/html/user1
~] cat user2
local_root=/var/www/html/user2
When your user1 file has local_root=/var/www/html/user1
content, change ownership /var/www/html/user1 directory to e.g. root user and check user1 has not write access. Then create e.g. data directory and change ownership to www-data user and setup write access to data directory.
# create user home directories
~] mkdir /var/www/html/user1
~] mkdir /var/www/html/user2
# change ownership user home directories to root
~] chown root:root /var/www/html/user1
~] chown root:root /var/www/html/user2
# change home directory rights
~] chmod 755 /var/www/html/user1
~] chmod 755 /var/www/html/user1
# create data dirs for write for all users
~] mkdir /var/www/html/user1/data
~] mkdir /var/www/html/user2/data
# change ownership to www-data user for data dirs
~] chown www-data:www-data /var/www/html/user1/data
~] chown www-data:www-data /var/www/html/user2/data
setup control:
~] ls -alFh /var/www/html/
drwxr-xr-x 3 root root 4.0K Jul 13 14:15 user1/
drwxr-xr-x 3 root root 4.0K Jul 13 14:16 user2/
~] ls -alFh /var/www/html/user1
drwxr-xr-x 2 www-data www-data 4.0K Jul 13 14:11 data/
~] ls -alFh /var/www/html/user2
drwxr-xr-x 2 www-data www-data 4.0K Jul 13 14:11 data/
Configure vsftpd server
Edit your /etc/vsftpd.conf file:
#If enabled, vsftpd will run in standalone mode. This means that vsftpd must not be run from an inetd of some kind.
#Instead, the vsftpd executable is run once directly. vsftpd itself will then take care of listening for and handling incoming connections.
listen=YES
#If enabled, and vsftpd was compiled with tcp_wrappers support, incoming connections will be fed through tcp_wrappers access control.
#Furthermore, there is a mechanism for per-IP based configuration. If tcp_wrappers sets the VSFTPD_LOAD_CONF environment variable, then the vsftpd session will try and load the vsftpd configuration file specified in this variable.
#Default: NO
#tcp_wrappers=YES
#Controls whether anonymous logins are permitted or not. If enabled, both the usernames ftp and anonymous are recognised as anonymous logins.
anonymous_enable=NO
#Controls whether local logins are permitted or not. If enabled, normal user accounts in /etc/passwd (or wherever your PAM config references) may be used to log in.
#This must be enable for any non-anonymous login to work, including virtual users.
local_enable=YES
#This controls whether any FTP commands which change the filesystem are allowed or not. These commands are: STOR, DELE, RNFR, RNTO, MKD, RMD, APPE and SITE.
write_enable=YES
#The value that the umask for file creation is set to for local users. NOTE! If you want to specify octal values, remember the "0" prefix otherwise the value will be treated as a base 10 integer!
#Default: 077
local_umask=022
#This is the name of the user that is used by vsftpd when it wants to be totally unprivileged. Note that this should be a dedicated user, rather than nobody.
#The user nobody tends to be used for rather a lot of important things on most machines.
#Default: nobody
nopriv_user=www-data
#If enabled, virtual users will use the same privileges as local users. By default, virtual users will use the same privileges as anonymous users, which tends to be more restrictive (especially in terms of write access).
virtual_use_local_privs=YES
#If enabled, all non-anonymous logins are classed as "guest" logins. A guest login is remapped to the user specified in the guest_username setting.
guest_enable=YES
#This option is useful is conjunction with virtual users. It is used to automatically generate a home directory for each virtual user, based on a template.
#For example, if the home directory of the real user specified via guest_username is /home/virtual/$USER, and user_sub_token is set to $USER,
#then when virtual user fred logs in, he will end up (usually chroot()'ed) in the directory /home/virtual/fred. This option also takes affect if local_root contains user_sub_token.
#user_sub_token=$USER
#This option represents a directory which vsftpd will try to change into after a local (i.e. non-anonymous) login. Failure is silently ignored.
#local_root=/var/www/$USER
#if set to YES, local users will be (by default) placed in a chroot() jail in their home directory after login. Warning: This option has security implications, especially if the users have upload permission, or shell access.
#Only enable if you know what you are doing. Note that these security implications are not vsftpd specific. They apply to all FTP daemons which offer to put local users in chroot() jails.
chroot_local_user=YES
hide_ids=YES
guest_username=www-data
# active ftp mode:
# connect_from_port_20=YES
# pasv_enable=NO
# passive ftp mode:
connect_from_port_20=NO
pasv_enable=Yes
pasv_min_port=30000
pasv_max_port=30100
#If enabled, a log file will be maintained detailling uploads and downloads. By default, this file will be placed at /var/log/vsftpd.log, but this location may be overridden using the configuration setting vsftpd_log_file.
#Default: NO (but the sample config file enables it)
xferlog_enable=YES
#This option is the name of the file to which we write the vsftpd style log file. This log is only written if the option xferlog_enable is set, and xferlog_std_format is NOT set.
#Alternatively, it is written if you have set the option dual_log_enable. One further complication - if you have set syslog_enable, then this file is not written and output is sent to the system log instead.
#Default: /var/log/vsftpd.log
vsftpd_log_file=/var/log/vsftpd/vsftpd.log
#This option is the name of the file to which we write the wu-ftpd style transfer log. The transfer log is only written if the option xferlog_enable is set, along with xferlog_std_format.
#Alternatively, it is written if you have set the option dual_log_enable.
#Default: /var/log/xferlog
xferlog_file=/var/log/vsftpd/vsftpd-xfer.log
#When enabled, all FTP requests and responses are logged, providing the option xferlog_std_format is not enabled. Useful for debugging.
#Default: NO
log_ftp_protocol=YES
#This powerful option allows the override of any config option specified in the manual page, on a per-user basis. Usage is simple, and is best illustrated with an example.
#If you set user_config_dir to be /etc/vsftpd_user_conf and then log on as the user "chris", then vsftpd will apply the settings in the file /etc/vsftpd_user_conf/chris for the duration of the session.
#The format of this file is as detailed in this manual page! PLEASE NOTE that not all settings are effective on a per-user basis. For example, many settings only prior to the user's session being started.
#Examples of settings which will not affect any behviour on a per-user basis include listen_address, banner_file, max_per_ip, max_clients, xferlog_file, etc.
#Default: (none)
user_config_dir=/etc/vsftpd
### SSL Config ###
# If true, OpenSSL connection diagnostics are dumped to the vsftpd log file. (Added in v2.0.6).
debug_ssl=YES
# If enabled, an SSL handshake is the first thing expect on all connections (the FTPS protocol). To support explicit SSL and/or plain text too, a separate vsftpd listener process should be run.
#implicit_ssl=YES
# If enabled, and vsftpd was compiled against OpenSSL, vsftpd will support secure connections via SSL. This applies to the control connection (including login) and also data connections. You'll need a client with SSL support too.
ssl_enable=YES
# This option specifies the location of the RSA certificate to use for SSL encrypted connections.
rsa_cert_file=/etc/ssl/wildcard.secar.cz.pem
# This option specifies the location of the RSA private key to use for SSL encrypted connections. If this option is not set, the private key is expected to be in the same file as the certificate.
rsa_private_key_file=/etc/ssl/wildcard.secar.cz.pem
In SSL section, our configuration must specify the paths to our certificates (include intermediates certificates) and the SSL key. Certificates and keys are together in one file in pem format.
~] cat /etc/ssl/wildcard.secar.cz.pem
—–BEGIN RSA PRIVATE KEY—–
(Your Private Key: your_domain_name.key)
—–END RSA PRIVATE KEY—–
—–BEGIN CERTIFICATE—–
(Your Primary SSL certificate: your_domain_name.crt)
—–END CERTIFICATE—–
—–BEGIN CERTIFICATE—–
(Your Intermediate certificate: DigiCertCA.crt)
—–END CERTIFICATE—–
—–BEGIN CERTIFICATE—–
(Your Root certificate: TrustedRoot.crt)
—–END CERTIFICATE—–
The important line here is the following user_config_dir=/etc/vsftpd
. This means that when user1 logs in it will look for the following file
/etc/vsftpd/user1
Now create the user file and enter the following line:
~] vi /etc/vsftpd/user1
local_root=/var/www/html/user1
Change permissions to user directory and create user data directory:
~] chown root:root /var/www/html/user1
~] mkdir /var/www/html/user1/data
~] chown www-data:www-data /var/www/html/user1/data
~] cd /var/www/html
root@server1:/var/www/html] tree -L 2 -df -ug
├── [root root ] ./user1
│ └── [www-data www-data] ./user1/data
Now restart vsftp
~] systemctl restart vsftpd.service
Troubleshooting
500 Illegal PORT command
When your log file contains this content:
Thu Dec 20 16:29:53 2018 [pid 31179] [user1] FTP command: Client "212.158.133.35", "PORT 192,168,0,208,160,147"
Thu Dec 20 16:29:53 2018 [pid 31179] [user1] FTP response: Client "212.158.133.35", "500 Illegal PORT command."
Thu Dec 20 16:29:53 2018 [pid 31179] [user1] FTP command: Client "212.158.133.35", "PASV"
Thu Dec 20 16:29:53 2018 [pid 31179] [user1] FTP response: Client "212.158.133.35", "550 Permission denied."
It means, that your FTP server support only active mode .
FTPS in active mode
Using FTPS server in active mode is impossible due to Network address translation (NAT) .There is no way to send ftp PORT command with right IP address in any FTPS server behind NAT . When you are behind Network address translation (NAT) you send a probably your private ip address in PORT command.
Notes