Oliver Nassar

VSFTPD setup for my AWS 11.04 Box

August 02, 2011

Following in the footsteps of my post AWS EC2 Micro Instance Setup, I wanted to devote a full-post to how I've setup my box's FTP server/service/daemon to allow for a pretty secure, decentralized, login system. Worth noting is that some commands are based on the post above being followed (eg. aliases were created to restart the ftp server, etc.), and this post is directly targeting some intricacies of AWS and how it manages it's firewall.

The premise behind my configuration is that each-and-every VirtualHost gets it's own virtual user with it's own unique password. The benefit behind this is two fold:

  1. SVN/Git pushing is done on a per-user basis, which means giving out those credentials limits a 3rd-parties access to one directory/virtual-host
  2. Easy to provide ftp-access to people who want to simply upload files

Although the purpose behind this is to create virtual-host-based users, one can simple create ftp-only accounts that are found in the /var/www directory, but don't correlate directly to a virtual-host.

While a public/private key system is also a solid option (and easy to coordinate with AWS), I didn't like the idea of a 3rd-party service having access to my entire filesystem, so I've opted for the process outlined in this guide.

VSFTP Configuration

The first step in this process is to configure the previously installed vsftp program.

sudo vi /etc/vsftpd.conf

The following needs to now happen:

One of the things that stands out here is the custom port that should be configured for listening. I change this just to mix things up, but if you do this, you'll need to open that port up in the AWS Security Group/firewall. Keep that in mind.

However in addition to this, AWS (versus some other providers like Slicehost) requires you to add in the following two directives:

In this case, PORT2 is a different port than what was setup earlier, and will also need to be opened up in the AWS security group/firewall.

While my understanding of passive vs. active mode is limited, I believe that in passive mode, setting a range (in this case equal to the same exact port; security issue?) instructs the ftp-server's data-port to fall somewhere in that range. At that point, AWS's firewall isn't an issue since it's already been instructed to open that port up specifically.

The article Active FTP vs. Passive FTP, a Definitive Explanation gives a pretty solid explanation. The VSFTPD Configuration Manual is also worth it's weight in gold.

Oh, and I can't forget about the tutorial Set up an FTP Server on Amazon EC2. Solid walkthrough, although the IP tables bit wasn't a requirement.

Now, let's complete the configuration setup by rebooting the server.

ftp-restart

Virtual User Setup

Now comes the "fun" part. We get to create and manage the virtual users for this box.

sudo apt-get -y install db4.8-util
cd
sudo vi vusers.txt

This opens up an empty txt file which should be filled in in the following format:

<directory in /var/www>
<password>

For example:

prod.olivernassar.com
kittens
dev.olivernassar.com
kittens

Although this file will temporarily contain plain-text passwords, it gets compiled and encrypted shortly, so don't be concerned about that. The next step is to compile this information down to a format that the ftp-daemon can understand/process:

sudo db4.8_load -T -t hash -f vusers.txt /etc/vsftpd.vusers.db
sudo chmod 600 /etc/vsftpd.vusers.db
sudo vi /etc/pam.d/vsftpd.virtual

In the file that opens, copy and paste the following:

#%PAM-1.0
auth required pam_userdb.so db=/etc/vsftpd.vusers
account required pam_userdb.so db=/etc/vsftpd.vusers
session required pam_loginuid.so

Now we just restart:

ftp-restart

And boom. We've created a set of virtual-users which can access only their associated /var/www directory.

To make changes (eg. add, remove, change) to the list of virtual-users, the process is a little long-winded. You need to recreate a vusers.txt file with all the logins and passwords, and then run the following:

cd
sudo vi vusers.txt
sudo db4.8_load -T -t hash -f vusers.txt /etc/vsftpd.vusers.db
sudo chmod 600 /etc/vsftpd.vusers.db
sudo rm vusers.txt
ftp-restart

Hopefully at some point I'll find a way to automate that. There we have it. Hope that helps.

Update

Ha, after all that, I couldn't get my FTP server working. And while I don't know why yet (Update: see passive port opening above), I found a pretty helpful logging snippet.

The log file located at /var/log/vsftpd.log is pretty sparse, showing basic entries like:

Wed Aug3 00:38:04 2011 [pid 2] CONNECT: Client "174.116.180.121"
Wed Aug3 00:38:04 2011 [pid 1] [prod.djkstyles.com] FAIL LOGIN: Client
"174.116.180.121"
...

This didn't help all that much, so I went back into my VSFTPD config file, and did the following:

Now, thanks to http://www.linuxquestions.org/questions/linux-newbie-8/vsftpd-and-log-files-can-i-up-the-log-level-to-see-login-attempts-632999/, the log file is a little more helpful :)