Setup vsftpd with virtual users using MySQL

I’d like to outline the procedure on how to setup an FTP server using vsftpd virtual users. Using a separate MySQL table to store the credentials of users provides a secure implementation without all the hassle of creating user accounts on your machine. A very detailed tutorial is provided here and is the basis for what follows. I’ve made some changes and added some important steps that will hopefully save you the several wonderful days I’ll never get back.

The main problem you will have is that it will vary per distribution. I’m using an Amazon Linux EC2 instance which is essentially based on CentOS and Red Hat Enterprise Linux. So I can’t verify how this will work on other distributions but hopefully you can find the similar packages.

1. Install and configure MySQL

yum install mysql-server

I won’t go through the MySQL setup. I already had a server running so I used that, but feel free to follow the tutorial for the details on how to create a username and password table to be used with vsftpd.

2. Install and configure vsftpd

 

yum install vsftpd

First I want to create a user called “vsftpd” that belongs to a group called users. Eventually I want to have all my “virtual” users to have accounts like /home/vsftpd/joe,/home/vsftpd/cathy, etc. The bottom line here is that everything will be stored under /home/vsftpd.

groupadd users (only if you don't have the users group already)
useradd -G users -s /sbin/nologin -d /home/vsftpd  vsftpd

By the way, the /sbin/nologin command politely refuses a login. It displays a message that an account is not available and exits non-zero. Now let’s make a backup copy of the default configuration file you need to edit and start from scratch.

cp -v /etc/vsftpd/vsftpd.conf   /etc/vsftpd/vsftpd.conf-orig
vim /etc/vsftpd/vsftpd.conf

It is really up to you on what you need to add but let me show some key ones. Here is the standard setup stuff:

#No ANONYMOUS users allowed
anonymous_enable=NO
# Allow 'local' users with WRITE permissions (0755)
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
pasv_enable=YES
pasv_min_port=14000
pasv_max_port=14100


Here are a number of options specific to our vsftpd user:

nopriv_user=vsftpd
chroot_local_user=YES
listen=YES
 
# here we use the authentication module for vsftpd to check users name and passw
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES
 
# here the vsftpd will allow the 'vsftpd' user to login into '/home/vsftpd/$USER directory
guest_enable=YES
guest_username=vsftpd
local_root=/home/vsftpd/$USER
user_sub_token=$USER
virtual_use_local_privs=YES

I won’t go into each one but for an exhaustive list of options see the vsftpd configuration options.

3. Configure PAM

Now that we have vsftpd and MySQL setup we can now configure PAM (Password Authentication) so that it uses the MySQL database to authenticate with our virtual FTP users. We will make a backup of the file and edit to replace with these lines:

 

cp /etc/pam.d/vsftpd /etc/pam.d/vsftpd-orig
vim /etc/pam.d/vsftpd

 

#%PAM-1.0
session    optional     pam_keyinit.so    force revoke
auth required pam_mysql.so verbose=1 user=mydbusername passwd=mydbpass host=localhost db=mydb table=mydb_table usercolumn=username passwdcolumn=password crypt=3
account required pam_mysql.so verbose=1 user=mydbusername passwd=mydbpass host=localhost db=mydb table=mydb_table usercolumn=username passwdcolumn=password crypt=3


Just fill in your username/password for your database above along with the database name and table. In addition make sure the parameters for “usercolumn” and “passwdcolumn” match what column names you gave in your MySQL table. I’m using crypt=3 here, this represents MD5 hashing. But I could have gone with SHA1 with crypt=4. Those are really the only 2 secure(ish) options in my opinion.

4. Install Pam for MySQL

I’ve found 2 options to make this work. The easy way, and the pull my hair out and scream way. Take your pick.

a) The easy way
First of all check if you have pam_mysql available with:

yum install pam_mysql


Probably not. BUT you can install the Fedora EPEL repo (in my case I selected version 6):

 

rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
yum install pam_mysql

Now it should work. Easy right?

b) Pull my hair out and scream way
I must admit this option blows chunks. If the easy way doesn’t work, I’m afraid this is your last resort. This requires you to install pam and configure it to work. Easy right? First get pam_mysql source here.

tar xvfz pam_mysql0.7RC1.tar.gz
cd pam_mysql0.7RC1
./configure --with-openssl=/usr
make
make install


At this point we are not even close to done. When you try to get this all working you will find out that there is an error from pam something about “make_scrambled_password”. Apparently this function is deprecated in the latest libmysql library. Fortunately I found a patch that fixes this. You need to download that patch (which is a source rpm), install the rpm and find the patch file that is part of it. Once you have the patch file (you might need the patching software like I did so you may need to run “yum install patch”):

 

cd pam_mysql0.7RC1
patch < pam_mysql0.7RC1-scrambled.patch
make clean
make
make install


See what I mean? Brutal.

5. Check everything is working

You will want to enter an account to test this all works. Depending on how you setup the DB, something like:

 

INSERT INTO accounts (username, password) VALUES('joe', md5('secret'));

Now you have to create the user home directory:

mkdir /home/vsftpd/joe
chown vsftpd:users /home/vsftpd/joe

Rejoice, that should be it! vsftpd is now working with virtual users right from the MySQL DB.

No comments yet.

HAVE SOMETHING TO SAY?