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:
- 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
- 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:
- Uncomment
write_enable=YES
- Uncomment
local_umask=022
- Add
virtual_use_local_privs=YES
- Switch
pam_service_name
tovsftpd.virtual
- Add
guest_enable=YES
- Add
guest_username=ubuntu
- Add
user_sub_token=$USER
- Add
local_root=/var/www/$USER
- Add
listen_port=PORT1
- Uncomment
chroot_local_user=YES
- Add
hide_ids=YES
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:
pasv_min_port=PORT2
pasv_max_port=PORT2
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:
- Uncomment
xferlog_std_format=YES
- Changed
xferlog_std_format=YES
toxferlog_std_format=NO
- Add
log_ftp_protocol=YES
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 :)