Installing FTP Server (vsftp)

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.

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.

Configuring vsftp

We have some options we must pay special attention. Let’s edit /etc/vsftpd.conf

Change FTP port:

listen_port=221

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.

Write Enable:

#write_enable=YES

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:

chroot_local_user=YES
allow_writeable_chroot=YES

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.

Clients allowed:

max_clients=20
max_per_ip=10

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@domain.ext), 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:

local_umask=022

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

pasv_enable=true
pasv_min_port=11111
pasv_max_port=11150

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:

pam_service_name=mysqlftp

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

Troubleshoot

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

Leave a Reply

Your email address will not be published. Required fields are marked *