HowTo.Gumph.Org

Step by step solutions to IT problems

Setup Virtual Users and Directories in VSFTPD

Setup virtual users instead of local users and configure user specific home directories for each user, or shared between a handful of users.

The reason for setting up virtual users, and different home directory for each user, was to allow ftp access to a web server running a number of different sites for different clients. Each client can have one or more login to the ftp server, and the usernames and passwords can be shared with the apache webserver, so you only need to store their passwords in one place.

I'm choosing vsftpd as the ftp server, as it seems to have the best reputation for being secure (and having the fewest security bugs)

Installing

Whilst each flavour of linux has it's own way of installing software, I'm going to run through using debian, so you will need to adapt it for whichever distro you use.

Firstly we need to download and install the ftp server VSFTPD

debian# apt-get install vsftpd
Most distros should have a compliled version of vsftpd available, but if you are compiling from source, then ensure you enable PAM support, as we will be using PAM to handle the virtual users.

If your disto doesn't come with PAM, then you'll need to grab a copy, as vsftpd uses PAM for authentication of virtual users.

Whilst you can use any of PAM's authentication methods, I'm going to use the pam_pwdfile module, so I can easily share the password file between the ftp server (via PAM) and the webserver (apache). You could use PAM for the apache authentication if you wanted to use a different authentication module.

There is a debian package for pam_pwdfile already available, alternatively, download and compile it, if your copy of linux doesn't come with it already

debian# apt-get install libpam-pwdfile

Configuration

In this example I want the ftp server to provide access various locally hosted websites, which I'm running from /var/www/sites/site1 etc so I don't want anonymous access or for users to be able to access other sites.

Firstly we need to create a password file for the users. You can use the htpasswd utility that comes with apache, but in it's normal use, it only supports passwords up to 8 characters long. If you want to support longer passwords, either use a different PAM module, or use md5-crypt passwords.

I'm going to assume you've got apache installed already, so first create a password file for the first user (called bob)

debian# htpasswd -c /etc/vsftpd/passwd bob
for subsequent users just use
debian# htpasswd /etc/vsftpd/passwd alice

Next we need to edit the vsftpd configuration file /etc/vsftpd.conf

listen=YES
anonymous_enable=NO
local_enable=YES
virtual_use_local_privs=YES
write_enable=YES
connect_from_port_20=YES
secure_chroot_dir=/var/run/vsftpd
pam_service_name=vsftpd
guest_enable=YES
user_sub_token=$USER
local_root=/var/www/sites/$USER
chroot_local_user=YES
hide_ids=YES

We've turned anonymous access off, and enabled local access which we need for virtual users, and we've specified that each user will be chrooted to their own web directory, so user bob will be chrooted to /var/www/sites/bob. Although the manual says that local_root will fail silently if the folder doesn't exist, that will not happen as we've turned on chrooting, so in the event of a folder error, the user will get a 500 error from the ftp server.

Finally we need to configure PAM to use the password file, so edit /etc/pam.d/vsftpd

# Customized login using htpasswd file
auth    required pam_pwdfile.so pwdfile /etc/vsftpd/passwd
account required pam_permit.so

You need the account line as vsftpd requires both auth and account to work, so as we are using virtual users without any account expiry information, we use the default pam_permit module for account authentication.

Testing

Restart the vsftpd process to pick up the new settings
debian# /etc/init.d/vsftpd stop
debian# /etc/init.d/vsftpd start
and try logging on via ftp.
debian# ftp 127.0.0.1
Connected to 127.0.0.1.
220 (vsFTPd 2.0.3)
Name (127.0.0.1:root): bob
331 Please specify the password.
Password:
500 OOPS: cannot change directory:/var/www/sites/bob
Login failed.
421 Service not available, remote server has closed connection
ftp> quit 
debian#

Now create Bob's home folder, and set permissions up correctly.

debian# mkdir /var/www/sites/bob
chmod +w /var/www/sites/bob
and try ftping in again
debian# ftp 127.0.0.1
Connected to 127.0.0.1.
220 (vsFTPd 2.0.3)
Name (127.0.0.1:root): bob
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> 
Success !

Extra Options

If you need to have multiple logins for the same folder, such as for a client who wants each developer to have their own login, then add the following line to the /etc/vsftpd.conf file
 user_config_dir=/var/www/users 
It's easiest if each virtual user for a client has a login that starts with that clients name, so alice working for client1 would be client1-alice. Add their username and password to the password file, and then create a file in the user config folder /var/www/users called client1-alice with the single line
local_root=/var/www/sites/client1

If you are offering multiple logins to lots of clients then it's easiest to create a file for each client eg /var/www/users/client1 would contain the single line

local_root=/var/www/sites/client1
and then each for user for that client would just create a symbolic link instead
debian# cd /var/www/users
debian# ln -s client1 client1-alice
as you are less likely to make mistakes if each user points to the same file.
Submit to     del.icio.us    digg    reddit    simpy