This has been tested on Debian Etch 4.0 and Debian Lenny 5.0, the procedure is the same in both versions. It should be roughly the same on Debian derived systems like Ubuntu.
Here we’ll learn how to set up a FTP server with virtual users, as opposed to real system users. This helps you to both secure your server better and manage multiple users. This is however a pretty basic setup, no user quota and so forth as I didn’t need it when I set up my system. However there are excellent information to be found on places like howtoforge.com if you are looking for a more in depth FTP solution.
Getting everything we need
Well be using VSFTPD and MySQL, we also need libpam-mysql to enable VSFTPD to check usernames and passwords from a MySQL database.
root@server:~# apt-get install vsftpd libpam-mysql mysql-server mysql-client
You’ll be asked to set up a MySQL root password during install, this is the root user for MySQL server and not the same as the system’s root.
Create a database and FTP-users
Log in with MySQL’s root user by typing:
root@server:~# mysql -u root -p
Create a database called vsftpd and a user called vsftpd that will have control over the database. Change somepassword to whatever you like.
mysql> create database vsftpd; mysql> GRANT ALL PRIVILEGES ON vsftpd.* TO 'vsftpd'@'localhost' IDENTIFIED BY 'somepassword'; mysql> GRANT ALL PRIVILEGES ON vsftpd.* TO 'vsftpd'@'localhost.localdomain' IDENTIFIED BY 'somepassword'; mysql> flush privileges;
Create a table called accounts that will hold the FTP users. We set the username to be unique so that we can’t create two users with the same username.
mysql> use vsftpd; mysql> CREATE TABLE accounts (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, username VARCHAR(20) NOT NULL, password VARCHAR(50) NOT NULL, UNIQUE(username));
Next we’ll add one or several users to the database with the following command:
mysql> INSERT INTO accounts (username,password) VALUES('somevirtualuser', PASSWORD('theuserpassword'));
The MySQL password() function makes sure we store the password as a MD5 hash and not in plain text.
Exit from MySQL by typing:
First we’ll create a system user that will hold all the virtual users home directories and run our FTP server.
root@server:~# useradd -m -s /bin/false vsftpd
You’ll also need to create the FTP home directory of the virtual user(s) you created earlier. There is a option in the VSFTPD config that supposedly should automate this but it doesn’t seem to be working. We also make sure the directory is owned by the system user vsftpd you created in the previous step. Repeat the following for every user you created.
root@server:~# mkdir /home/vsftpd/somevirtualuser;chown vsftpd:vsftpd /home/vsftpd/somevirtualuser
The configuration file is located at /etc/vsftpd.conf and is decently commented, you can back it up by writing:
root@server:~# cp /etc/vsftpd.conf /etc/vsftpd.conf.old
Edit the configuration file /etc/vsftpd.conf. You’ll need to change/uncomment the following:
anonymous_enable=NO local_enable=YES write_enable=YES nopriv_user=vsftpd chroot_local_user=YES local_umask=022
You’ll also need to add the following:
guest_enable=YES guest_username=vsftpd user_sub_token=$USER local_root=/home/vsftpd/$USER virtual_use_local_privs=YES
This might seem counter intuative (for example: why enable_local=YES if we are using virtual users?) so I’ll try to explain briefly.
When we enable local users we normally would enable useraccounts in /etc/passwd to log in to our ftp, however we will in the next section set up VSFTPD to check against our MySQL database instead. We also need to map our virtual users against a existing system user. We do this by classifying all non-anonymous logins as a guest login (by setting guest_enable=YES) and then map all logins to the user specified in guest_username, which in our case is the user vsftpd. We also set our virtual users to have the same rights as the local users (in other words the same umask as we set in local_umask).
Configure VSFTPD to use MySQL for authentication
VSFTPD uses PAM for authentication so we to edit the VSFTPD PAM config file. Back up the file then edit it using your editor of choice.
root@server:~# mv /etc/pam.d/vsftpd /etc/pam.d/vsftpd.old root@server:~# vim /etc/pam.d/vsftpd
Add the following to the new file. Replace “somepassword” with the password you chose for the MySQL user vsftpd when you created the MySQL database earlier. The crypt=2 line checks to makes sure that the password is stored as a MD5 hash. If we accidentally create a user with a plain text password (i.e. we forget to use the password() function in MySQL) they won’t be able to log in.
auth required pam_mysql.so user=vsftpd passwd=somepassword host=localhost db=vsftpd table=accounts usercolumn=username passwdcolumn=password crypt=2
account required pam_mysql.so user=vsftpd passwd=somepassword host=localhost db=vsftpd table=accounts usercolumn=username passwdcolumn=password crypt=2
That’s it. We are now ready to rock and roll. Make sure to restart VSFTPD to reload the changes we made.
root@server:~# /etc/init.d/vsftpd restart