vsftpd

vsftpd a GPL licensed FTP server for UNIX systems, including Linux. It is secure, extremely fast and stable.

Prerequisites
CentOS should be installed as per the instructions here.

yum -y install libcap-devel

Installation
Create a directory to hold the source files:

mkdir -p /extra/src
cd /extra/src

Download the latest version of vsftpd source tarball. At the time of writing, it was 2.3.2 but check the home page for updates.

wget ftp://vsftpd.beasts.org/users/cevans/vsftpd-2.3.2.tar.gz
tar zxf vsftpd-2.3.2.tar.gz
cd vsftpd-2.3.2

We are going to enable SSL on this FTP server, so edit builddefs.h and change:

#undef VSF_BUILD_SSL

to:

#define VSF_BUILD_SSL

Build the vsftpd binary:

make

On our CentOS system, the user "nobody" and the directory "/usr/share/empty" already exist, so we can install the binaries:

make install

The install command doesn't copy the default configuration file so do that manually:

cp vsftpd.conf /etc

Automatic Startup
Rather than xinetd or inetd, we're going to use daemontools to control vsftpd startup. Install it per the instructions if it is not already on your system.
We'll use some tcpserver rules to control access to our FTP server. Install it,
then create /etc/tcp/vsftpd with some basic rules in it:

127.:allow
192.168.0.:allow

Build a CDB file from the rules file with:

tcprules /etc/tcp/vsftpd.cdb /etc/tcp/vsftpd.tmp < /etc/tcp/vsftpd
chmod 644 /etc/tcp/vsftpd.cdb

Change the location of the log file in /etc/vsftpd.conf so that multilog gets the error messages:

xferlog_file=/dev/stdout

Create the directories to hold the service scripts:

mkdir -m 1755 /var/service/vsftpd
cd /var/service/vsftpd

Then create the service run script, /var/service/vsftpd/run:

#!/bin/sh
exec 2>&1
exec /usr/local/sbin/vsftpd
#exec tcpserver -c30 -Xv -llocalhost \
#-x/etc/tcp/vsftpd.cdb -uvsftpd -gvsftpd 0 ftp \
#softlimit -d300000 /usr/local/sbin/vsftpd

Make the run script executable:

chmod 700 /var/service/vsftpd/run

Set up the logging script:

mkdir -m 755 log
cd log
wget http://qmail.jms1.net/scripts/run.log
mv run.log run
chmod 700 run

Start the service by creating the symbolic link in /service:

ln -s /var/service/vsftpd /service/

After a few seconds, confirm that it is running:

svstat /service/vsftpd

Custom Configuration
Anonymous FTP access - CentOS already has an "ftp" user so we'll need to create a directory for the anonymous FTP login:

mkdir /var/ftp
chown root.root /var/ftp
chmod og-w /var/ftp

Want to enable file upload for the anonymous user? Edit /etc/vsftpd.conf:

write_enable=YES
anon_upload_enable=YES

Then allow write access an "upload" directory:

mkdir /var/ftp/upload
chmod go+w /var/ftp/upload

Virtual Users
These instructions use PAM for virtual user support.
First, add the "virtual" user:

useradd -d /var/ftp vsftp

Edit /etc/vsftpd.conf file and add the following options:

chroot_local_user=YES
guest_enable=YES
guest_username=vsftp
pam_service_name=vsftpd
cd /extra/src
wget http://www.kernel.org/pub/linux/libs/pam/pre/library/Linux-PAM-0.77.tar.bz2
bunzip2 -c Linux-PAM-0.77.tar.bz2 | tar -xvf -
cd Linux-PAM-0.77/modules
wget http://cpbotha.net/files/pam_pwdfile/pam_pwdfile-0.99.tar.gz
tar zxvf pam_pwdfile-0.99.tar.gz
cd ..
rm default.defs
ln -s defs/redhat.defs default.defs
make all
cp modules/pam_pwdfile-0.99/pam_pwdfile.so /lib/security
vi /etc/pam.d/vsftpd
#%PAM-1.0
# Standard behaviour for ftpd(8).
auth   required        pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
auth   required      pam_pwdfile.so pwdfile /etc/vsftpd/passwd_ftp
# pam_pwdfile doesn't come with account, so we just permit, on success:
account        required        pam_permit.so
mkdir /etc/vsftpd
cd /etc/vsftpd
vi filter.pl
#! /usr/bin/perl -w
   use strict;
   # filter "user:cleartext" lines into "user:md5_crypted"
   # probably requires glibc
   while (<>) {
       chomp;
       (my $user, my $pass) = split /:/, $_, 2;
       my $crypt = crypt $pass, '$1$' . gensalt(8);
       print "$user:$crypt\n";
   }
   sub gensalt {
       my $count = shift;
       my @salt = ('.', '/', 0 .. 9, 'A' .. 'Z', 'a' .. 'z');
       my $s;
       $s .= $salt[rand @salt] for (1 .. $count);
       return $s;
   }

chmod ugo+x filter.pl

vi addFtpUser.sh
#!/bin/bash
   if [ $# != 2 ] ; then
       echo "Incorrect number args"
   else
       cd /etc/vsftpd
       touch cleartext
       chmod go= cleartext
       echo $1:$2 >> cleartext
       ./filter.pl cleartext > passwd_ftp
   fi
chmod +x addFtpUser.sh

Virtual User custom home directories

mkdir /etc/vsftpd/userConf
vi /etc/vsftpd.conf
user_config_dir=/etc/vsftpd/userConf
echo "local_root=/var/ftp/<username>" >> /etc/vsftpd/userConf/<username>

Resources
Build a Secure FTP Dropbox with vsftpd
http://ubuntuforums.org/showthread.php?t=518293
http://labs.erweb.it/pub/vsftp_with_virtual_users.php
http://linuxforfun.net/2008/04/05/vsftpd-virtual-users/

Recent Updates

  • 15 hours 6 min ago
    Switching to http://qmail.jms1.net/dspam method.
  • 15 hours 55 min ago
  • 16 hours 40 min ago
    PHP 5.3 adjustments to configure switches.
  • 19 hours 27 min ago
  • PHP
    21 hours 12 min ago
    Update from PHP 5.3 to 5.5