Monday, October 10, 2005

Mini HOWTO #1: chroot-ed FTP with wu-ftpd

Scenario: We have an Apache server whose DocumentRoot directory is /var/www/html. We have wu-ftpd running as the FTP server.

Goal: We want developers to be able to access /var/www/html via ftp, but we want to grant access only to that directory and below.

Solution: Set up a chroot-ed ftp environment

1. Create special 'ftpuser' user and group:

useradd ftpuser

2. Change /etc/passwd entry for user ftpuser to:

ftpuser:x:501:501::/var/www/html/.:/sbin/nologin

(note the dot after the chroot directory)

3. Add /sbin/nologin to /etc/shells.

4. Create and set permissions on the following directories under the chroot directory:

cd /var/www/html
mkdir -p bin dev etc usr/lib
chmod 0555 bin dev etc usr/lib

5. Copy ls and more binaries to the bin subdirectory:

cp /bin/ls bin
cp /bin/more bin
chmod 111 bin/ls bin/more

Also copy to usr/lib all libraries needed by ls and more. Do "ldd /bin/ls" to see the shared libraries you need to copy. For example:

-rwxr-xr-x 1 root root 495474 Jan 7 15:44 ld-linux.so.2
-rwxr-xr-x 1 root root 5797952 Jan 7 15:44 libc.so.6
-rwxr-xr-x 1 root root 11832 Jan 7 15:44 libtermcap.so.2

6. Create special "zero" file in dev subdirectory:

cd dev
mknod -m 666 zero c 1 5
chown root.mem zero

7. Create bare-bones passwd and group files in etc subdirectory:

passwd:

root:x:0:0:root:/root:/sbin/nologin
ftpuser:x:501:501::/var/www/html:/sbin/nologin

group:

root:x:0:root
ftpuser:x:501:

8. Edit /etc/ftpaccess and add following lines:

class all real,guest *

guestgroup ftpuser

chmod no guest,anonymous
umask no guest,anonymous
delete no anonymous
overwrite no anonymous
rename no anonymous

upload /var/www/html / yes root ftpuser 0664 dirs

9. Change group (via chgrp) for files under /var/www/html to ftpuser
  • also change permissions to 775 for directories and 664 for files
  • but be careful to exclude the bin, dev, etc and usr subdirectories

10. Modify httpd.conf so that access to special subdirectories is not allowed:

<Directory /var/www/html/bin>
order deny,allow
deny from all
</Directory>

<Directory /var/www/html/dev>
order deny,allow
deny from all
</Directory>

<Directory /var/www/html/etc>
order deny,allow
deny from all
</Directory>

<Directory /var/www/html/usr>
order deny,allow
deny from all
</Directory>



11. Restart Apache and wu-ftpd


12. Test by ftp-ing as user ftpuser
  • Verify that you can upload/delete files in /var/www/html and subdirectories
  • Verify that you can't access files outside of /var/www/html and subdirectories

2 comments:

rdk said...

Request for another scenario...

Scenario: We have 2 Apache virtual servers whose DocumentRoot directories are as follows:

/var/www/productionweb.net

and

/var/www/testingweb.net

We also keep files in the Subversion repository (actually both dirs are check-outs of the repo).

We have wu-ftpd running as the FTP server.

Some files (mostly html templates and easy errors) are changed on the production server directly.

Other files (bigger changes that require more testing and QA, or special debugging set on) are changed on the testing server.

Goals:

1. At the time the file on the production server is changed via ftp, we want to commit it to the repository. (Best would be if developer could commit his change to the repository [branch production?] and immediately the change would be updated on the production server file. Thus we could get rid of ftp.)

2. On the request we would like to automatically make testing environment. Ie. reflect the current state of the files from the production server on the testing server (but leaving config files for the DB access and Path settings). Also the testing DB should be recreated with the production data.

3. When testers say OK to bigger functionality change we want to deploy these changes on the production server (and to the repository). However we still need to have the chance of rollback.

Solutions: ???

Grig Gheorghiu said...

rdk,

Your scenario and goals are above and beyond what this humble mini HOWTO tried to achieve. I'll give some thought to your scenario and if I come up with anything I'll leave a comment on your blog.

Grig