Working with Vsftpd as FTPS server with virtual users and SSL certificates in Debian or Ubuntu

Working with Vsftpd as FTPS server with virtual users and SSL certificates in Debian or Ubuntu


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 pwdfile /etc/vsftpd/ftpd.passwd
account required

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

And than edit ftpd.passwd file manual

root@server1:/etc/vsftpd] cat /etc/vsftpd/ftpd.passwd

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

~] cat 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.

#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 

#Controls whether anonymous logins are permitted or not. If enabled, both the usernames ftp and anonymous are recognised as anonymous logins.

#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.

#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.

#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

#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

#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).

#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.

#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.

#This option represents a directory which vsftpd will try to change into after a local (i.e. non-anonymous) login. Failure is silently ignored.

#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.

# active ftp mode:
# connect_from_port_20=YES
# pasv_enable=NO

# passive ftp mode:

#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)

#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

#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

#When enabled, all FTP requests and responses are logged, providing the option xferlog_std_format is not enabled. Useful for debugging.
#Default: NO

#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)

### SSL Config ###

# If true, OpenSSL connection diagnostics are dumped to the vsftpd log file. (Added in v2.0.6).

# 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.

# 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.

# This option specifies the location of the RSA certificate to use for SSL encrypted connections.

# 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.

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/
(Your Private Key: your_domain_name.key) 
(Your Primary SSL certificate: your_domain_name.crt) 
(Your Intermediate certificate: DigiCertCA.crt) 
(Your Root certificate: TrustedRoot.crt) 

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


Now create the user file and enter the following line:

~] vi /etc/vsftpd/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


500 Illegal PORT command

When your log file contains this content:

Thu Dec 20 16:29:53 2018 [pid 31179] [user1] FTP command: Client "", "PORT 192,168,0,208,160,147"
Thu Dec 20 16:29:53 2018 [pid 31179] [user1] FTP response: Client "", "500 Illegal PORT command."
Thu Dec 20 16:29:53 2018 [pid 31179] [user1] FTP command: Client "", "PASV"
Thu Dec 20 16:29:53 2018 [pid 31179] [user1] FTP response: Client "", "550 Permission denied."

It means, that your FTP server support only active mode .

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](https://e in PORT command.



comments powered by Disqus