Hacking Linux Exposed





previous article
next article
Creating an Anonymous FTP server with Publicfile
By Bri Hatch.

Summary: Step-by-step instructions that guide you through creating a secure anonymous ftp site.

Newsletter Subscription Note: This is the first issue of the Linux Security: Tips, Tricks, and Hackery newsletter. If you wish to subscribe and receive the newsletter each week in your email, go to http://lists.onsight.com.

For many moons I've meant to set up an FTP server for stunnel.org. Not because I like FTP[1], but because there are times even I find myself without a web browser of any kind. The server needs to support anonymous FTP (ftp without a password) and doesn't need to have the ability for anyone to have 'real' logins. The whole thing should be read-only, no write permissions. And as with everything I support, security is a must.

There are a boatload of FTP servers, almost all of which have had some vulnerability of some kind - in fact most have had bugs that lead to shell or root access. Many have added on additional security measures, such as the ability to chroot real users as well as anonymous users. However this FTP server's needs are so minimal, any FTP server software with boatloads of configuration options are just overkill.

So where do I turn? Publicfile. Another offering from Dan Bernstein, author of DJBDNS, another one of my favorite software packages. Publicfile offers both an FTP and HTTP server. I'll only concentrate on the FTP server in this article.[2]

Publicfile offers an anonymous-only FTP server. When users connect they must supply a username (this is an unavoidable assumption of FTP servers) but no password - not even an email address - is required. It supports both active and passive FTP, and is immune to ftp-bounce attacks. The server chroots to the ftp area and changes to a non-root user. You can easily limit how many users can connect using the power of tcpserver and softlimit. Any directories and files readable by that user are available via FTP.[3] All in all, perfectly paranoid.

Publicfile relies on two other DJB packages: ucspi-tcp and daemontools. If you don't have these installed (they certainly didn't come with your Linux distro) then you'll need to install them. You might want to refer to my previous DJBDNS[4] articles, where I describe how to install them and how they function.

So, onto the installation. It's so trivial it'll take you about two minutes:

  $ wget http://cr.yp.to/publicfile/publicfile-0.52.tar.gz
  $ tar xzvf publicfile-0.52.tar.gz
  $ cd publicfile-0.52
  $ make
  # make setup check

The 'make setup check' command is the part that does the installation, so it must be run as root. Once you've run those commands, the publicfile software will be installed in /usr/local/publicfile/bin/. There are three programs therein:

Sets up the supervise directories for the web and ftp server, as well as the directories for the content themselves.

The Publicfile FTP server

The Publicfile HTTP server

Before we set up Publicfile, we need to create the user that the server will run as, and the logging user account as well. DJB suggests using 'ftp' and 'ftplog'. Since various software packages may or may not muck with a unix account named 'ftp', I prefer to use 'pubfile' and 'publog' respectively.

  # for acct in pubfile publog
       groupadd $acct
       useradd -g $acct -s /bin/false -c "Publicfile $acct user" \
               -M -d /nada $acct

Now that our users are created, we need to set up our FTP server.

  # /usr/local/publicfile/bin/configure pubfile publog /public

This sets up the following directories:

/public/ftpd The FTP daemon directory for supervise
/public/ftpd/log The FTP daemon logging directory
/public/httpd The HTTP daemon directory for supervise
/public/httpd/log The HTTP daemon logging directory
/public/file/0 The anonymous FTP area[5]

Now, tell svscan to start up the ftp server:

  # ln -s /public/ftpd /service

In a few seconds you'll have an FTP server running. Copy all the files and directories you want available into /public/file/0. To test it out, simply connect:

  $ ftp my_ftp_server
  Name (my_ftp_server:jdoe): anonymous
  230 Hi. No need to log in; I'm an anonymous ftp server.
  Remote system type is UNIX.
  Using binary mode to transfer files.
  ftp> ls
  +i2054.507,m976862021,/,	file-tests
  ftp> cd file-tests
  200 Okay.
  150 Making transfer connection...
  +i2054.96042,m977254940,r,s108147,	file1.tgz
  +i2054.96092,m962174273,r,s8246,	file2
  +i2054.96093,m976767600,r,s105638,	file3.gif
  +i2054.96096,m1030736284,r,s254,	file4.tgz
  +i2054.506,m1033422657,/,	more-files
  226 Success.
  ftp> get file2
  200 Okay.
  150 Making transfer connection...
  226 Success.
  8246 bytes received in 0.00 secs (19127.6 kB/s)
  ftp> quit

Everything works fine, but you may note that the file listings seem weird. DJB uses his self-created EPLF (Easily Parsed List Format) to show the info about the file.[6] Several ftp clients such as ncftp, wget, and Mozilla support this format and can convert it to humanly readable text. However if you want to configure Pubicfile to show pretty file listings always, you can apply a patch available from www.publicfile.org. Instead of compiling as I outlined above, use the following procedure instead:

  $ wget http://cr.yp.to/publicfile/publicfile-0.52.tar.gz
  $ tar xzvf publicfile-0.52.tar.gz
  $ cd publicfile-0.52
  $ wget http://publicfile.org/ftp-ls-patch
  $ patch < ftp-ls-patch
  $ make
  # make setup check

The only additions are the wget and patch commands. This re-compiles publicfile and installs it over the old version. The new patched version will be available for all subsequent connections:

  $ ftp my_ftp_server
  Name (my_ftp_server:jdoe): anonymous
  230 Hi. No need to log in; I'm an anonymous ftp server.
  ftp> ls
  +i2054.507,m976862021,/,	file-tests
  ftp> cd file-tests
  200 Okay.
  150 Making transfer connection...
  150 Making transfer connection...
  dr-xr-xr-x  2 pub  pub       4096 Sep 30 21:50 file-tests

It shows all files as being owned by pub:pub, even if this user/group id don't exist, and shows all files as being world readable. However this output format is easier for humans to read, and is parseable by more FTP client software.

Logs are stored in /public/ftpd/log/main/ using multilog. The first element is the timestamp, the next is the client IP address, and the rest are pretty self explanatory:

  $ tail /public/ftpd/log/main/current
  @400000003d9041dc18579eec tcpserver: status: 3/40
  @400000003d9041dc1888a1cc tcpserver: pid 7699 from
  @400000003d9041dc1888e04c tcpserver: ok 7699 0:
  @400000003d9041de37c88674 dir ./0/: success
  @400000003d9041f438d66c34 dir ./0/file-tests/: success
  @400000003d9041861ac18a6c read ./0/file-tests/file2: success
  @400000003d90420230761314 tcpserver: end 7699 status 0
  @400000003d90420230763e0c tcpserver: status: 2/40

For more information about Publicfile, including patches that may be useful should you want to use it as your HTTP server, see http://www.publicfile.org/.


[1] I can't stand FTP. Most annoying is the fact that it requires two channels. The command channel over which you provide your 'get', 'ls', 'cd' and other commands, and then a data channel that's created dynamically for each data transfer -- and that includes 'ls' output. This was a historical leftover of network protocols created at the time. However we can certainly do better. FTP should be depreciated and/or burned at the stake.

[2] Publicfile's HTTP server is as streamlined (minimalistic) as all DJB software. However the webserver portion lacks many features that make it unappealing for those of us who have used Apache. For example the logging includes little more than the URL and IP, redirects and other non-html responses are not possible, you cannot enable any dynamic content, and file type configuration is weird. However there are various patches you can apply to make it more Apache-like if you wish.

[3] Since publicfile's FTP server runs as a dummy user, this essentially means that the files need to be world readable. Since they're available via anon-FTP, this isn't a problem.

[4] http://www.hackinglinuxexposed.com/articles/20020716.html

[5] If you set up the Publicfile HTTP server then you'd create different directories in /public/file for each virtual host you wish to support, such as /public/file/www.example.com and /public/file/images.my_domain.net. /public/file/0 is the root for the 'default' server (one that doesn't match one of the existing directories therein) and is also the FTP area.

[6] http://cr.yp.to/ftp/list/eplf.html. The fields are: device and inode (to provide a unique reference to the file), the modification time (seconds since the epoch) and the file size in bytes.

Bri Hatch is Chief Hacker at Onsight, Inc and author of Hacking Linux Exposed and Building Linux VPNs. He's not pleased about enabling FTP, but it beats the prefered file transfer method for many corporate individuals - email. Bri can be reached at bri@hackinglinuxexposed.com.

Copyright Bri Hatch, 2002

This is the October 01, 2002 issue of the Linux Security: Tips, Tricks, and Hackery newsletter. If you wish to subscribe, visit http://lists.onsight.com/ or send email to Linux_Security-request@lists.onsight.com.

previous article
next article