In this guide I will show you how I installed vsftp and configured it to fit my needs. I know FTP is very insecure and I don’t recommend it; but when hosting WordPress sites, some users want to install and update themes / plugins without complicating their lives and you are forced to install an FTP server and pray not to be compromised.
I will give many options through the installation so everyone can choose which one is best for your needs.
This guide is based in Ubuntu 14.04, but it may work in other Ubuntu/Debian/Mint versions or even other distributions. It’s also compatible with another Linux flavours with little changes.
- 1 Installing the software
- 2 Configuring vsftp
- 3 Anonymous FTP Server
- 4 Virtual users, not system users (with file database)
- 5 Changing group and permissions
- 6 Passive mode ports
- 7 Virtual Users with MySQL authentication
- 8 Making user stuff available to the users
- 9 Troubleshoot
Installing the software
This is the easies part, vsftp is already in our package manager so:
$ sudo apt-get install vsftp
We will now have the server ready to access by FTP, that’s it. If you try to access ftp://yourhost.ext it will asks you for username and password, that credentials will be system users, and each users may have access to their home directories. But they really have access to the entire system /read only access).
But, that’s for me a really bad idea. Let’s see some options.
We have some options we must pay special attention. Let’s edit /etc/vsftpd.conf
Change FTP port:
For example, port 221, not default one, this will increase a little bit our server security by adding a server in a non-obvious port. Also, some clients or routes will be more happy with that, because passive connections won’t be restricted, and sometimes that’s the best solution for writing problems.
Already commented, but uncomment this to allow users write permission. We will need it in order to let our users install stuff from WordPress.
If you want the users only access their homes, it’s recommended to chroot them, so enable these two options:
The first one enables chrooting, so the users will only access their homes, the second one overrides home directory writable check. This directory /home/myUser, must be non-writable in order to chroot into it, but this could be a bad idea, because some programs won’t be able to write into it. You can also skip the second line by removing write access to the home directory or by changing this home directory.
It restricts the number of clients at the same time and the max number of clients per ip.
Anonymous FTP Server
If you want to run an anonymous FTP server (user: anonymous, password: email@example.com), check out these options:
anonymous_enable=YES anon_upload_enable=YES anon_root=/var/ftp anon_mkdir_write_enable=YES
With these settings you enable anonymous users, anonymous upoad to /var/ftp and make users enable to create directories.
Virtual users, not system users (with file database)
To increase security, and because we not always want everyone to be a system user, just FTP users pointing at their web folders or WordPress installations (we may just have one system user, who will have ssh access, but many FTP users). We will do many changes, but they are worth it.
First, install the necessary packages:
$ sudo apt-get install db6.0-util
You may have to install a newer version, just search for the proper package.
Let’s edit /etc/vsftpd.conf and add:
pam_service_name=ftp user_sub_token=$USER local_root=/var/ftp/$USER virtual_use_local_privs=YES dirlist_enable=YES chroot_local_user=YES
Now create /etc/pam.d/ftp (as pam_service_name is ftp), and add:
auth required pam_userdb.so db=/etc/vsftpd.d/vsftpd_login account required pam_userdb.so db=/etc/vsftpd.d/vsftpd_login
Now, we’re going to create the users database, so, create the directory /etc/vsftp.d/ (where we said it’s located it /etc/pam.d/ftp), and create in there a text file where we’ll write usernames and passwords, this way:
user1 password1 user2 password2
This will be a text file showing everyone’s password, so let’s protect it with proper permissions, I mean, only root can access this file (chmod 0600 for example).
Now create the hash file:
$ sudo db6.0_load -T -t hash -f /etc/vsftpd.d/passwords /etc/vsftpd.d/vsftpd_login.db
and give 0600 permissions for root user. Visit TroubleShoot section if you are experiencing problems.
Restart the service and enjoy with our new virtual users.
Changing group and permissions
To change the group when uploading files, the easiest way is changing ftp user’s main group this way:
$ sudo usermod -g www-data ftp
With this command we are setting www-data as main group for the user ftp. We can change it to any group we need.
To change file permissions we must change the local_umask configuration in /etc/vsftpd.conf we can try something like:
and restart vsftp daemon.
Passive mode ports
When using a FTP it’s important to use passive mode. In the past, when the active mode was used, the clients had to accept incoming connections of the servers to transfer files. It’s so insecure, and difficult nowadays as many of us connect to Internet behind a router and there are many computers connected to it. We could use NAT to route several ports to our computer (we need the router’s administrator password). Or we can use passive mode. In this mode, the server opens new ports to the public, and the client, us, connect to any of these ports (if they are available).
To enable passive mode we must enter these lines ti /etc/vsftpd.conf
With these lines, after enabling passive mode, we set the server to use ports between 11111 and 11150 to passive connections. We can make this range bigger if we receive many FTP connections, or even smaller if we aren’t receiving many clients. We also must open these ports in our firewall configuration. If using UFW we can do it this way:
$ sudo ufw allow 11111:11150/tcp
Virtual Users with MySQL authentication
This is not working on some systems due to a shared library problem, it says you must have libgcc_s.so.1 but it is installed. stracing the problem you will find out a memory allocation problem, but the real problem seems to be it can’t find the proper methods in the library.
If not happy with the way above, using a password file (adding and removing users may be a bit unconfortable), let’s test it with mysql authentication. First, install libpam-mysql package:
$ sudo apt-get install libpam-mysql
And then, make little changes, very similar to the ones we’ve made to the file database, so the onle one we’ve got to change is:
Now, create the file /etc/pam.d/mysqlftp with these contents:
session optional pam_keyinit.so force revoke auth required pam_mysql.so user=vsftpd passwd=EI(7?l5bE(-F host=localhost db=myserver table=ftpusers usercolumn=username passwdcolumn=password crypt=3 account required pam_mysql.so user=vsftpd passwd=EI(7?l5bE(-F host=localhost db=myserver table=ftpusers usercolumn=username passwdcolumn=password crypt=3
Yes, my MySQL password is “EI(7?l5bE(-F”, so let’s use a secure one.
And now, access MySQL Server as root, create myserver schema, create ftpusers table:
mysql> CREATE SCHEMA myserver; Query OK, 1 row affected (0.00 sec) mysql> CREATE TABLE myserver.ftpusers ( > User_id BIGINT NOT NULL AUTO_INCREMENT, > Username VARCHAR(100) NOT NULL, > Realname VARCHAR(100), > Password VARCHAR(100) NOT NULL, > Active TINYINT, > Creation_dtm DATETIME, > Update_dtm DATETIME, > PRIMARY KEY (`User_id`), > UNIQUE (`Username`) > ) ENGINE=MyISAM DEFAULT CHARSET="UTF8"; Query OK, 0 rows affected (0.02 sec) -- Insert dummy user mysql> INSERT INTO myserver.ftpusers VALUES (NULL, 'gaspar', 'Gaspar', MD5('password'), 1, NOW(), NOW()); Query OK, 1 row affected (0.01 sec) mysql> GRANT ALL PRIVILEGES ON myserver.ftpusers TO 'vsftpd'@'localhost' IDENTIFIED BY 'EI(7?l5bE(-F'; Query OK, 0 rows affected (0.00 sec)
User_id, Realname, Creation_dtm and Updated_dtm will be columns for our server control. We can create a friendly web user interface to make users change their information and these fields could be useful to have a user profile.
And connect !!!
Making user stuff available to the users
In my server, some users have their stuff spreaded through the hard drive. One user may have two WordPress installs, another one has access to developers folders and so. But, as the users are chrooted, I can’t simply make links to the directories they must have access to.
So I created a bash script where every user stuff is binded to the user directory. As evey user must have a /var/ftp/$USER subdirectory, I did the following:
$ mount --bind /var/www/user1/ /var/ftp/user1/www $ mount --bind /home/server/devs /var/ftp/user1/devs
And everything will be binded to the correspondent user
Problems creating password db
You may see the following error:
db5.1_load: unexpected end of input data or key/data pair
db5.1_load: odd number of key/data pairs
It happens when there are a odd number of lines in passwords file. Remember, one line is user name, the other is password. But it also happens when you have an unscaped backslash (\). So if the password (or the username) has a \ in it, just put two (\\).
Unknown option allow_writeable_chroot
It happens when you have an old version of vsftpd. You can comment this line, but you may get this error when connecting:
500 OOPS: vsftpd: refusing to run with writable root inside chroot()
You must then, delete write permission to your user root directory. For example, if this directory is /var/root/myuser:
$ sudo chmod a-w /var/root/myuser