Tuesday, December 5, 2006

FTP Server on Ubuntu

I have a couple of clients who will be uploading data packets to Pericles on a daily basis, so I decided to install vsftpd.

Using Synaptic Package Manager, I installed the latest version. The configuration file can be found and edited (as root, so use sudo) in /etc/vsftpd.conf but since FTP settings are so diverse depending on your needs, I am not going to go into the details of the conf file here, except to say that you should read and carefully select your options. I decided to set chroot_local_user=YES for security reasons, so that my authenticated users cannot browse files outside of their home directory, and I set pasv_enable=YES, pasv_min_port=62000 and pasv_max_port=64000 in order to match the iptables Firewall restrictions I had previously enabled.

NOTE: If you list pasv_min_port but forget pasv_enable=YES, vsftpd might give you the very unhelpful error message: "unrecognised variable in config file"

Since I have a few users who are allowed to do maintenance on their own websites, and I don't use ~/public_html since I don't allow shell access to these users, nor do I want to have to visit their home directory to do maintenance or backups myself, I will be needing to grant them access to specific folders in the system's /Web directory. My first thought was to do a symbolic link, but since they are in a chroot jail, the symbolic link can't get out of the jail either. Hard links would work, except that you can only hard link a file, not a whole directory. It looks like mount --bind is the answer. You can test out this arrangement by performing the following at a shell prompt, replacing jeffd with your own username and /Web/sample with the actual path to the path you are granting access to:

mkdir /home/jeffd/sample
sudo mount --bind /Web/sample /home/jeffd/sample

Now, list the files in the /home/jeffd/sample directory. You will see that it is equivalent to /Web/sample. To unmount:

sudo umount /home/jeffd/sample

Once you're satisfied with this arrangement, you can edit /etc/fstab (again, remember to use sudo) and append lines in the following format for each path you want to map:

/Web/sample  /home/jeffd/sample  none  bind 0 0

Now, reboot if you want to test it (sudo reboot now). Voila!

Now, lest you think yourself clever and try chrooting from a shell prompt to test the restricted environment, it will not work. You would need to have a copy of /bin/bash and some of its required libraries from /lib (or /lib64 as the case may be) residing within the target root in order to do so. Since you aren't going to be allowing shell access into the chroot area, but only FTP, this shouldn't be a problem so don't bother trying it. If you DO try it, and you've only copied /bin/bash, you'll get a misleading error that /bin/bash can't be found even if its there because it can't find the files it needs in /lib. If you DO copy /lib and get in, you won't be able to do anything fun anyway because you don't have the basic tools like ls in order to operate, so just don't try this.

Once you're up, FTP in and verify your chroot setup by trying to cd to the root or elsewhere that you are not allowed to go, and make sure your mount bind works by putting some files there.

1 comment:

Duncan said...

Nice tutorial, thanks. I have been having some problems with a setup the same as this. Running vsftpd with users in chroot and a web folder outside this chroot.

Followed your mount approach which enabled me to at least browse and see the folders, but I can't write/delete anything ...

I figure it's got to be a permissions problem, so if you have some time and the inclination I would love to hear if you have any suggestions to solving the problem.

Config as follows:
Ubuntu 7.10
Apache with sites in /var/www/www.domain.com/public_html

All these folders chowned by www-data:www-data which is what apache runs as under Ubuntu.

VSFTD running as vsftd user which is a member of the www-data group.