Linux Server Security (2nd Edition( [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Linux Server Security (2nd Edition( [Electronic resources] - نسخه متنی

Michael D. Bauer

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







11.1. FTP Security


What would we do
without FTP? You can use FTP to install Linux, download software from
public archives, and share files with friends and colleagues.
It's both venerable and ubiquitous. Most major sites
on the Internet offer some level of public FTP access.

But like many other Internet applications, FTP is showing its age.
Designed for a simpler era, FTP is gradually going the way of Telnet:
it's still useful for
"anonymous" (public) access, but
its cleartext login makes it too dangerous for use with important
user accounts.

Anonymous FTP, though, will probably remain with us for some time, so
let's discuss FTP security, both in general and with
specific regard to my preferred FTP servers, ProFTPD and vsftpd.


11.1.1. Principles of FTP Security


With FTP, we have several major threat
models. The first concerns anonymous access: anonymous users
shouldn't be able to do anything but list and
download public files and maybe upload files to a single
"incoming" directory. Needless to
say, we don't want them to
"escalate" their privileges to
those of a more trusted user.

Another important FTP threat model involves local user accounts. If a
local user logs in via FTP to upload or download something to or from
his home directory, we don't want that session
hijacked or eavesdropped on by anybody else, or the
user's credentials may be stolen and used with other
services such as telnet, SSH, etc.

The third threat model worth considering involves confidentiality. At
the very least, login credentials must be protected from disclosure,
as should any other sensitive data that is transmitted.

Unfortunately, by its very design FTP fails miserably in addressing
any but the first of these threat models: a good FTP server package
that is carefully configured can protect against privilege
escalation, but like telnet, the FTP protocol as
described in RFC 959 (

11.1.1.1 Active mode versus passive mode FTP


To make matters worse,
FTP's use of TCP ports is, to put it charitably,
inopportune. You may have already learned that FTP servers listen on
TCP port 21. However, when an FTP client connects to an FTP server on
TCP port 21, only part of the transaction uses this initial
"control" connection.


FTP Server Packages Compared



For some time,
WU-FTPD has been the
most popular FTP server for Unix and Unix-like platforms. This is
probably because, compared to the traditional BSD
ftpd from which it evolved, WU-FTPD is very rich
in features, very stable, and theoretically, more securable. I say
"theoretically" with a bit of irony
because in recent years, WU-FTPD itself has been vulnerable to a
series of buffer overflows that, since WU-FTPD runs as
root, have led to many servers being
compromised. While its developers have been quick to provide patches,
I personally avoid WU-FTPD since these bugs crop up with more
regularity than I'm comfortable with.

ProFTPD, a
"written-from-scratch" package with
Apache-like configuration syntax and modularity, claims security as
one of its fundamental design goals. Despite the fact that it, too,
has had some serious vulnerabilities (though fewer than WU-FTPD),
it's become quite popular. One of its better
features is support for "virtual
servers," in which multiple FTP sites hosted on the
same system appear to be on separate systems.

Rapidly gaining ground in the FTP world is Chris
Evans's vsftpd, the "Very Secure
FTP Daemon." vsftpd has fewer features than ProFTPD,
but a better security track record so far: its
primary design goal is security, with
performance a close second. vsftpd is my personal favorite FTP server
nowadays.

D. J.
Bernstein's package publicfile is designed to be a
bare-bones, ultra-secure daemon for serving up public datafiles and
simple web pages to anonymous users. (By not even supporting logins
to local user accounts, says Bernstein, it's easier
to prevent those accounts from being compromised).
It's undoubtedly more secure than WU-FTPD, ProFTPD,
and probably vsftpd, but by far has the fewest features of these.
Also, publicfile requires you to install and run
Bernstein's daemon tools and
ucspi-tcp packages, which can take some getting
used to (though to me, this is merely an annoyance and not a
huge reason not to run publicfilesee the
"djbdns" section in Chapter 6).

I'm covering ProFTPD and vsftpd in this chapter
because of their popularity, security (compared to WU-FPTD), and rich
feature sets, especially security features. But if your FTP-server
needs (or, for that matter, web-server needs) are very basic and
limited to anonymous access, you should check out publicfile. D. J.
Bernstein's publicfile web site is http://cr.yp.to/publicfilel.

By default, whenever an FTP client wishes to download a file or
directory listing, the FTP server initiates a new
connection back to the client using an arbitrary high TCP
port. This new connection is used for transmitting data, as opposed
to the FTP commands and messages carried over the control connection.
FTP with server-initiated data channels is called active
mode FTP.

If you think allowing externally initiated (i.e., inbound) data
connections in through your firewall is a really bad idea,
you're right. Networks protected by simple packet
filters (such as router ACLs) are often vulnerable to
PORT theft attacks.
In these attacks, an attacker opens a data channel (requested by a
legitimate user's PORT command)
to the user's system before the intended server
responds.

PORT commands can also be used in
FTP
Bounce attacks, in which an attacking FTP client sends a
PORT command requesting that the server open a
data port to a different host than that from which the command
originated. FTP Bounce attacks are used to scan networks for active
hosts, to subvert firewalls, and to mask the true origin of FTP
client requests (e.g., to skirt export restrictions).

The only widely supported (RFC-compliant) alternative to active mode
FTP is passive mode FTP, in which the client rather than the
server opens data connections. That mitigates the
"new inbound connection" problem,
but passive FTP still uses a separate connection to a random high
port, making passive FTP only slightly easier to deal with from a
firewall-engineering perspective. (Many firewalls, including Linux
iptables, now support FTP connection tracking of passive mode FTP; a
few can track active mode as well.) There are two main lessons to take from this discussion of active
versus passive FTP. First, of the two, passive is preferable since
all connections are initiated by the client, making it somewhat
easier to regulate and harder to subvert than active mode FTP.
Second, FTP is an excellent candidate for proxying at the firewall,
even if your firewall is otherwise set up as a packet filter.

SUSE's Proxy Suite,
which can be run on any Linux distribution (not just SUSE), contains
an FTP proxy that interoperates well with iptables and ipchains. This
proxy, ftp-proxy, can broker all FTP
transactions passing through your firewall in either direction (in or
out). In this way, you can control at the firewall which commands may
be used in FTP sessions. You can also prevent buffer-overrun attempts
and other anomalies from reaching either your FTP servers or
clients.[1] [1] The HTTP proxy Squid can also proxy FTP
connections but is a general-purpose caching proxy, whereas
ftp-proxy is specifically designed as a security
proxy.


Using an FTP proxy
will require your users to configure their FTP software accordingly,
unless you've configured your firewall to act as a
transparent proxyi.e., to redirect
automatically all outbound and/or inbound FTP connections to its
local proxy. (To use a Linux 2.4 iptables firewall for transparent
proxying, you'll first need to load the module
ipt_REDIRECT.) See Chapter 2 for a detailed explanation of proxies and
application gateways and what they do.

Additionally, iptables includes the kernel module
ip_conntrack_ftp for
tracking FTP connections. While this module doesn't
provide as much granular control as ftp-proxy,
it effectively tracks PORT requests (active FTP
transactions), passive FTP data requests, and their respective new
data channels, and it is intelligent enough to deny spoofed data
connections. ip_conntrack_ftp can be used with
or without an FTP proxy such as ftp-proxy.

11.1.1.2 The case against nonanonymous FTP


As I mentioned earlier, the FTP protocol transmits logon credentials in
cleartext over the network, making it unsuitable for Internet use by
accounts whose integrity you wish to protect. Why, you may wonder, is
that so?


Can't You Encrypt FTP?


"Surely," you may ask,
"by now someone's figured out how
to combine FTP with SSL?" Indeed they have, three
times over!

The FTPS protocol adds SSL (TLS) encryption to the
FTP
protocol, adding both encryption and, optionally,
X.509-certificate-based authentication to your FTP experience. But
I'm not covering FTPS here (and in fact steadfastly
insist that the only good FTP is anonymous FTP) for a very simple
reason: there's never been widespread agreement on
just how FTPS should work. There are
three different implementations of FTPS.

This isn't really that surprising: as
I've shown, FTP is a complicated protocol to begin
with, so it follows that combining it with encryption, which never
simplifies anything, would be a dicey
proposition. Still, people are continuing to work on this problem,
and various FTP client and server applications that support one or
more versions of FTPS are available.

For more information, Paul Ford-Hutchinson has an FTPS page at
http://www.ford-hutchinson.com/~fh-1-pfh/ftps-extl#bad
that provides summaries of the three different FTPS implementations,
and charts showing which applications support which implementations
(including handy links to all those applications'
web sites).

Admittedly, it's unlikely that a given Internet FTP
session will be eavesdropped on by, say, an evil system administrator
at an ISP somewhere on that data's path. The problem
is that it's trivially easy for
such a person to eavesdrop if she's so inclined.

For the most part, this means that FTP constitutes an unacceptable
risk, except when you don't care whether the logon
session is eavesdropped on (as in anonymous FTP) and whether the
subsequent data transfers are eavesdropped on.

Therefore, I'm not going to elaborate here on how to
tighten nonanonymous FTP security: I feel strongly that this is a
losing proposition and that the only good FTP is anonymous FTP. If
remote users need to read or write data to nonpublic areas, use one
of the tools described later in this chapter (i.e.,
rsync, scp, and
sftp).

11.1.1.3 Tips for securing anonymous FTP


My tips on securing anonymous FTP can be summarized as follows:

Run your FTP daemon as an unprivileged user/group if possible.

Make sure your anonymous FTP account uses a bogus shell.

Create a restricted chroot jail, owned by root,
in which anonymous users may operate.

Don't allow anonymous users to upload files unless
you have very good reasons, plus the time and motivation to watch
publicly writable directories very closely.


Let's examine these tips in depth and then look at
how to implement them using two different FTP servers,
ProFTPD and
vsftpd.

First, run the FTP daemon as an unprivileged user and group: this
sounds like and is common sense, but it may or may not be possible
with your chosen FTP server package. The problem is that FTP servers
are expected to listen for incoming connections on TCP port 21 and,
in some circumstances, to send data from TCP port 20. These are both
privileged ports, and any process that needs to bind to them must run
as root (at least initially).

ProFTPD and vsftpd both by default start as
root, bind to TCP 21, and promptly demote
themselves to the user nobody and, in the case
of ProFTPD, the group nogroup. (This behavior is
customizable if you have a different user or group
you'd like ProFTPD to run as.) D. J.
Bernstein's minimalist FTP/www server,
publicfile, also starts as
root and immediately demotes itself. WU-FTPD,
however, does not appear to support this feature; as best as I can
determine, it runs as root at all times.

My second tip, to make sure that your anonymous FTP account (usually
ftp) specifies a bogus shell, should also be
obvious, but is extremely important. /bin/false
and /bin/true are both popular choices for this
purpose. You don't want an anonymous FTP user to
somehow execute and use a normal shell such as
/bin/sh, nor do you want anyone to trick some
other process into letting them run a shell as the user
ftp. Note that by
"bogus," I do
not mean
"invalid": any shell specified in
any line of /etc/passwd should be listed in
/etc/shells, regardless of whether
it's a real shell, though some FTP server
applications are more forgiving of this than others.

A related tip is to make sure in both
/etc/passwd and /etc/shadow
(if your system uses shadowed passwords) that the password-hash for
your anonymous user account is set to *. This
prevents the account from being usable for login via any service
other than FTP.

Next, build an appropriate chroot jail for anonymous FTP users.
Obviously, this directory hierarchy must contain all the things you
want those users to be able to download. Be careful not to create any
links from within the jail to files outside of it: symbolic links
that point outside of the jail will simply not work, but hard links
will, and thus they will present attackers with
a way out of the chroot jail.

Historically, this chroot jail has needed to contain not only the
actual download directory, pub/, but also a
bin/ directory with its own copy of
ls, an etc/ directory
containing passwd, group,
and localtime, and sometimes copies of other
system directories and files.
WU-FTPD requires
some of these, but ProFTPD, vsftpd, and publicfile do not: the latter
three use their own internal versions of ls
rather than the system's, and function without their
own versions of /etc/passwd, etc.

The chroot directory itself and every directory within
it should be owned by root, not by
your anonymous FTP account (e.g., ftp) or the
daemon's "run-as"
account (e.g., nobody). A common configuration
error on anonymous-FTP servers is for the FTP root to be owned by the
FTP account, which constitutes a major exposure, since an anonymous
FTP user could write a .rhosts or
.forward file to it that extends the
user's access to the system.

Proper FTP root (chroot jail) ownerships and permissions are
illustrated in Example 11-1, which shows a recursive
listing of a sample FTP
chroot jail in /var/ftp/.

Example 11-1. ls -lR of an FTP chroot jail


/var/ftp:
total 12
d--x--x--x 2 root root 4096 Apr 16 00:19 bin
dr--r--r-- 2 root root 4096 Apr 16 00:27 etc
drwxr-xr-x 2 root wheel 4096 Apr 16 06:56 pub
/var/ftp/bin:
total 44
---x--x--x 1 root root 43740 Apr 16 00:19 ls
/var/ftp/etc:
total 12
-r--r--r-- 1 root root 63 Apr 16 00:26 group
-r--r--r-- 1 root root 1262 Apr 16 00:19 localtime
-r--r--r-- 1 root root 106 Apr 16 00:27 passwd
/var/ftp/pub:
total 1216
-rw-r--r-- 1 root root 713756 Apr 16 06:56 hijinks.tar.gz
-rw-r--r-- 1 root root 512540 Apr 16 06:56 hoohaw.tar.gz
-rw-r--r-- 1 root root 568 Apr 16 06:43 welcome.msg The directory /var/ftp itself is set up like
this:

drwxr-xr-x 2 root root 4096 Apr 16 00:06 ftp If your FTP server is to be maintained by a
non-root user, or if you wish to add files to
the pub/ directory without being
root, it's okay to make the
pub/ group writable and owned by a group to
which your non-root account belongs. Since the
group wheel is used on many systems to define
which user accounts may perform su root, and
it's a group to which you or your subadministrators
probably already belong, it's a logical choice for
this purpose.

If you make pub/ or any of its subdirectories
group writable, however, in no circumstances should their group ID be
equal to that of the anonymous user account!

My final general guideline for anonymous FTP is
not to allow anonymous uploads unless you know
exactly what you're doing, and if you do, to
configure and monitor such directories very carefully. According to
CERT, publicly writable FTP directories are a common avenue of abuse
(e.g., for sharing pornography and pirated software) and even for
Denial of Service attacks (e.g.,
by filling up disk volumes).

If you decide to create such an FTP drop-off directory
(conventionally named incoming), there are a
number of things you can do to make it harder to abuse:

As with the FTP chroot jail itself, make sure the writable directory
isn't owned by the anonymous user account.

Enable public write access (i.e., the FTP command
STOR), but disable public read access (i.e., the
FTP command RETR) to the
writable directory. This prevents uploaded files from being
downloaded by other anonymous users. Public execute access, which
allows users to change their working directory to
incoming/, is okay.

To prevent Denial of Service attacks that attempt to stop the FTP
server by filling its filesystems, consider limiting the maximum
uploadable file size, setting the anonymous FTP user
account's disk quota, or mounting the writable
directory to its own disk volume.

Don't allow uploaded files to remain in the writable
directory indefinitely: write a script to run as a cron job that
emails you when files have been uploaded or that automatically moves
uploaded files to a nonpublic part of the filesystem.

In general, monitor this directory carefully. If your FTP server can
be configured to log all file uploads, do so and keep an eye on these
log entries (Swatch, covered in Chapter 12, is
useful for this).



11.1.2. Using ProFTPD for Anonymous FTP


That's
how you secure anonymous FTP in a general sense. But what about
actual configuration settings on an actual FTP server?
Let's examine two popular FTP servers: the powerful
ProFTPD package and the arguably more secure vsftpd.

11.1.2.1 Getting ProFTPD


ProFTPD
is included in binary form in some Linux distributions, such as
Debian, though it appears to have been supplanted by vsftpd in others
(e.g., Fedora and SUSE). Make sure that your
distribution's version is no older than 1.2.9rc2,
due to known vulnerabilities in prior versions. As of this writing,
the most current stable version of ProFTPD is 1.2.9.

If your distribution of choice provides a ProFTPD package older than
1.2.9rc2 and doesn't have an updated
version[2] on
its "updates" or
"errata" web site (see Chapter 3), you can get ProFTPD from the official
ProFTPD download
site, ftp://ftp.proftpd.org. Source code is
located at this site (and its mirrors) in the
/distrib/source/ directory; RPM and SRPM
packages are located in /distrib/packages/.

[2] Note that in many Linux distributions,
it's common practice to patch older versions of
software packagesi.e., to issue updates that do not result in
higher version numbers of installed packages.


11.1.2.1.1 inetd/xinetd versus standalone mode


On a lightweight, multipurpose system on which you
don't anticipate large numbers of concurrent FTP
users, you may want to run ProFTPD from inetd or
xinetd:
in this way, the FTP daemon will be started only when an FTP user
tries to connect. This means that ProFTPD won't
consume system resources except when being used.

Also, whenever you edit
/etc/proftpd.conf, the changes will be applied the next time
a user connects without further administrative intervention, since
the daemon reads its configuration file each time
it's invoked by inetd or
xinetd. The other advantage of this startup
method is that you can use TCPwrappers with ProFTPD, leveraging the
enhanced logging and access controls TCPwrappers provides.

The disadvantages of
starting ProFTPD from an Internet superserver such as
inetd or xinetd are
twofold. The first is performance: ProFTPD's full
startup procedure is carried out each time it's
invoked this wayi.e., ProFTPD reads and processes its entire
configuration file. This is inefficient if the daemon is started
repeatedly in a short period of time, and users will notice a delay
when trying to connect. The second disadvantage is that some of
ProFTPD's best features, such as virtual servers,
are available only in standalone mode.

On a dedicated FTP system, therefore, or any other on which you
expect frequent or numerous FTP connections, standalone mode is
better. When run as a persistent daemon, ProFTPD reads its
configuration only once (you can force ProFTPD to reread it later by
issuing a kill -HUP command to its
lowest-numbered process), which means that whenever a new child
process is spawned by ProFTPD to accept a new connection, the new
process will get to work more quickly than an
inetd-triggered process.

11.1.2.2 ProFTPD modules


Like Apache,
ProFTPD
supports many of its features via source-code modules. If you install
ProFTPD from binary packages, the choice of which modules to compile
in ProFTPD has already been made for you (which is why you have
multiple RPMs from which to choose when downloading Red Hat ProFTPD
packages).

Some modules are included automatically in all ProFTPD builds (and
thus all binary packages): mod_auth,
mod_core, mod_log,
mod_ls, mod_site,
mod_unixpw, mod_xfer, and,
if applicable to your platform, mod_pam. These
modules provide ProFTPD's core functionality,
including such essentials as authentication, syslog logging, and FTP
command parsers.

Optional and contributed modules, which you generally must compile
into ProFTPD yourself, include mod_quota, which
provides support for putting capacity limits on directory trees, and
mod_wrap, which provides support for
TCPwrappers-style access control (i.e., via
/etc/hosts.allow and
/etc/hosts.deny). There are many other ProFTPD
modules: see the file README.modules in the
ProFTPD source code for a complete list.

Compiling
ProFTPD is simple using the conventional ./configure
&& make && make install
method. You can
tell the configure script which
optional/contributed modules to include via the
--with-modules flag, e.g.:

[root@myron proftpd-1.2.4]# ./configure --with-modules=mod_readme:mod_quota It isn't necessary to specify the automatically
included modules mod_auth,
mod_core, etc.

11.1.2.3 Setting up the anonymous FTP account and its chroot jail


Once ProFTPD
is in place, it's time to set it up. You should
begin by creating or configuring the anonymous FTP user account, which is
usually called ftp. Check your
system's /etc/passwd file to
see whether your system already has this account defined. If
it's there already, make sure its entry in
/etc/passwd looks like the one in Example 11-2.

Example 11-2. An /etc/passwd entry for the user ftp


ftp:x:14:50:FTP User:/home/ftp:/bin/true Make sure of the following:

The group ID is set to an unprivileged group such as
ftp (in the case of Example 11-2, you'll need to look up GID
50 in /etc/group to determine this).

The home directory is set to the directory you wish to use as an
anonymous FTP chroot jail.

The shell is set to a bogus, noninteractive shell such as
/bin/true or /bin/false.


If you don't already have the account
ftp, first create a group for it by adding a
line like this to /etc/group:

ftp:x:50:

(Alternatively, you can use an existing unprivileged group such as
nobody or nogroup.) Then,
add the user ftp using the useradd
command:

[root@myron etc]# useradd -g ftp -s /bin/true ftp Fedora's and Red Hat Enterprise Linux's
useradd behaves differently from
SUSE's, Debian's, and probably that
of most other (non-Red Hat-derived) distributions: on a Red Hat
system, useradd automatically creates the
user's home directory under
/home and copies the contents of
/etc/skel into it, using the specified username
as the directory's name (e.g.,
/home/ftp). Clearly, you don't
want the FTP user account to be loaded down with all this garbage.

Be sure, therefore, to specify the home directory with the
-d directive, which will
cause Fedora's or Red Hat's
useradd to behave
"normally." That is, it will list
the specified directory in the new user's
/etc/passwd entry, but will not create or
populate the home directory (unless the -m flag is
also present).

If useradd didn't create your
FTP user's home directory (i.e., the chroot jail),
do so manually. In either case, make sure this
directory's user ID is root and
its group ID is either root or some other
privileged group to which your anonymous FTP account does
not belong.

If useradd did create your FTP
user's home directory, either because you passed
useradd the -m flag or
because you run Red Hat, remove the dot
(".") files and
anything else in this directory copied over from
/etc/skel. ProFTPD won't let
anonymous users see such
"invisible" files, but the fact
that they aren't needed is reason enough to delete
them if present.

With ProFTPD it's also unnecessary for this
directory to contain any copies of system files or directories.
(ProFTPD doesn't rely on external binaries such as
ls.) Thus, all you need to do is create the jail
directory itself, populate it with the things you intend to make
available to the world, and set appropriate ownerships and
permissions on the jail and its contents, as described earlier in
Section 11.1.1.3 and illustrated in
Example 11-1.

Continuing our sample
ProFTPD setup, suppose you want the
jail to be group writable for your system administrators, who all
belong to the group wheel. Suppose further that
you need to accept files from anonymous users and will therefore
allow write access to the directory incoming.
Example 11-3 shows a recursive listing on our example
anonymous FTP chroot jail, /home/ftp.

Example 11-3. Example ProFTPD chroot jail


/home:
drwxrwxr-x 2 root wheel 4096 Apr 21 16:56 ftp
/home/ftp:
total 12
-rwxrwx-wx 1 root wheel 145 Apr 21 16:48 incoming
-rwxrwxr-x 1 root wheel 145 Apr 21 16:48 pub
-rw-rw-r-- 1 root wheel 145 Apr 21 16:48 welcome.msg
/home/ftp/incoming:
total 0
/home/ftp/pub:
total 8
-rw-rw-r-- 1 root wheel 145 Apr 21 16:48 hotdish_recipe_no6132.txt
-rw-rw-r-- 1 root wheel 1235 Apr 21 16:48 pretty_good_stuff.tgz As you can see, most of Example 11-3 is consistent
with Example 11-1. Notable differences include the
absence of etc/ and bin/
and the fact that everything is writable by its group owner,
wheel.

Also, in Example 11-3 there's a
world-writable but non-world-readable incoming
directory, to which all the warnings offered earlier under Section 11.1.1.3 are emphatically
applicable. (Make sure this directory has a quota set or is mounted
as a discrete filesystem, and move anything uploaded there into a
privileged directory as soon as possible.)

11.1.2.4 General ProFTPD configuration


Now that we've built the restaurant,
it's time to train the staff. In the case of
ProFTPD,
the staff is pretty bright and acclimates quickly. All we need to do
is set some rules in /etc/proftpd.conf.

As I stated earlier, ProFTPD has an intentionally Apache-like
configuration syntax. Personally, I consider this to be not only a
convenience but also, in a modest way, a security feature. Confusion
leads to oversights, which nearly always result in bad security;
ergo, when applications use consistent interfaces, allowing their
administrators to transfer knowledge between them, this ultimately
enhances security. (This, and not mental laziness, is the main reason
I hate sendmail.cf's needlessly
arcane syntaxsee Chapter 9.) The /etc/proftpd.conf file installed by default
requires only a little customization to provide reasonably secure
anonymous FTP services. However, for our purposes here, I think
it's more useful to start fresh.
You'll understand ProFTPD configuration better this
way than if I were to explain the five or six lines in the default
configuration that may be the only ones you need to alter.

Conversely, if your needs are more sophisticated
than those addressed by the following examples, view the
documentation of the ProFTPD binary packages generally put under
/usr/share/doc/proftpd or
/usr/share/doc/packages/proftpd. Particularly
useful are the "ProFTPD Configuration
Directives" page
(Configurationl) and the sample
proftpd.conf files (in
the subdirectory named either examples/ or
sample-configurations/,
depending on your version of ProFTPD).

Before we dive into proftpd.conf, a word or two
about ProFTPD architecture is in order. Like Apache, ProFTPD supports
virtual servers, parallel FTP environments
physically located on the same system but that answer to different IP
addresses or ports. Unlike Apache, however, ProFTPD does
not support multiple virtual servers listening
on the same combination of IP address and port.

This is due to limitations of the FTP protocol. Whereas HTTP 1.1
requests contain the hostname of the server being queried (i.e., the
actual URL entered by the user), FTP requests do not. For this
reason, you must differentiate your ProFTPD virtual servers by IP
address (by assigning IP aliases if your system
has fewer Ethernet interfaces than virtual hosts) or by listening
port. The latter approach is seldom feasible for anonymous FTP, since
users generally expect FTP servers to be listening on TCP 21. (But
this is no big deal: under Linux, it's very easy to
assign multiple IP addresses to a single interface.)

11.1.2.5 Base-server and global settings


On to some actual configuration. The logical things to start with are
base-server settings and global settings. These are
not synonymous:
base-server (or
"primary-server") settings apply to
FTP connections to your server's primary IP address,
whereas global settings apply both to the base server and to all its
virtual servers.

You might be tempted in some cases to assume that base-server
settings are inherited by virtual servers, but resist this
temptation, as they usually
aren't. With regard to directives that
may be specified in both base-server and virtual-host configurations,
the base server is a peer to your virtual servers, not some sort of
master. Thus, you need both base-server and global settings (unless
you have no virtual serversin which case you can put
everything with your base-server settings).

There are some base-server settings that are
inherited by virtual hosts: most of these settings may
only be set in the base-server section. They
include ServerType,
MaxInstances, the Timeout...
directives, and the SQL... directives. See
ProFTPD's Configurationl
file for a complete reference, which includes each
directive's permitted contexts.

Example 11-4 contains settings that apply only to the
base server, plus some that apply globally because of their very
nature.

Example 11-4. Base-server settings in /etc/proftpd.conf


# Base Settings:
ServerType standalone
MaxInstances 30
TimeoutIdle 300
TimeoutNoTransfer 300
TimeoutStalled 300
UseReverseDNS no
LogFormat uploadz "%t %u\@*l \"%r\" %s %b bytes"
SyslogFacility LOCAL5
# Base-server settings (which can also be defined in <VirtualHost> blocks):
ServerName "FTP at Polkatistas.org"
Port 21
MasqueradeAddress firewall.polkatistas.org
<Limit LOGIN>
DenyAll
</Limit>

Let's step through the settings of Example 11-4 one by one, beginning with what I think of as
"base-server but actually global"
settings (settings that may only be specified in the base-server
section and that actually apply globally). Paradoxically, none of
these may be set in a <Global> configuration
block.

ServerType standalone



Lets you tell ProFTPD whether it's being invoked by
inetd (or xinetd, but
either way, the value of this directive would be
inetd) or as a standalone daemon.


MaxInstances 30



Limits the number of child processes the proftpd
daemon may spawn when running in standalone mode and is therefore an
upper limit on the number of concurrent connections. Unlike
MaxClients, attempted connections past this number
are dropped silentlyi.e., without any error message being
returned to the prospective client.

Setting this directive has ramifications not only for performance and
availability, but also for security, because it's
the most efficient means of handling the large number of simultaneous
connection attempts that are the hallmark of FTP Denial of Service
attacks.


TimeoutIdle 300



Specifies the number of seconds of idle time (during which no
commands are issued by the client) before the server closes the
connection. Set a value here, even a high one, to mitigate exposure
to Denial of Service attacks.


TimeoutNoTransfer 300



Specifies the maximum number of seconds the server will leave the
connection open without any requests from the user to upload or
download files or request directory listings. Setting this is another
means of limiting DoS opportunities.


TimeoutStalled 300



Specifies the number of seconds after which the server will close a
stalled data connection. Useful in mitigating certain PASV-based DoS
attacks.


UseReverseDNS no



Normally, ProFTPD attempts to resolve all client IP addresses before
writing log entries. This can impair performance under a heavy load,
however, and you can always perform reverse-DNS resolution later when
you analyze the logs. I therefore recommend setting this to
no.


LogFormat uploadz "%t %u\@*l \"%r\" %s %b bytes"



Lets you specify a custom log-message format that can be referenced
later in ExtendedLog
directives (see Example 11-6). Custom
formats make such messages more easy to monitor or process by tools
such as Swatch (covered in Chapter 12).


SyslogFacility LOCAL5



Specifies a Syslog facility other than the default combination of
AUTH and DAEMON to which ProFTPD's messages can be
written: in Example 11-4, all
ProFTPD's Syslog messages will go to
LOCAL5. See Chapter 12 for a
description of these facilities.



And this brings us to Example 11-4s
"plain vanilla" base-server
settings. These directives may be declared in either base-server or
virtual-server sections. None of these, however, may be declared in a
<Global> block (which, in this case, makes
sense).

ServerName "FTP at Polkatistas.org"



Naturally, each base/virtual server will print a brief greeting to
users. Set it here. Note that this
"name" bears no relation to DNS
whatsoeveri.e., it needn't contain the name
registered to the server's IP address in DNS. (In
that sense, the directive might have been more accurately named
ServerBanner.) Note also that this string will
not be displayed prior to login if
ServerIdent is set to off (see
Example 11-5).


Port 21



The TCP port on which this server will listen for FTP control
connections. Different base/virtual servers listening on the same IP
address must listen on different ports, so if
you're stingy with IP aliases (e.g., you want to
host multiple virtual servers but don't have more
than one routable IP to assign to your Ethernet interface),
you'll need to use this directive. The expected and
therefore default TCP port is, of course, 21.


MasqueradeAddress firewall.polkatistas.org



This is the IP address or FQDN that your server will display in
application-layer messages to clients. Your server knows its real
name and IP address, of course, but this directive substitutes the IP
address or hostname of a proxy or firewall from whom the
server's packets will appear
(to external hosts) to originate. The masquerade address/name will be
displayed prior to login unless ServerIdent is set
to off (see Example 11-5).



For a Network-Address-Translated (NAT-ed)
server to be reachable via its own DNS-registered name, your firewall
or proxy may need to have a static mapping from a virtual IP (IP
alias) on the outside interface of the firewall to the
server's actual (internal) IP address. If you have
multiple Internet-routable IP addresses at your disposal, this is the
best way to handle more than one or two different servers and/or
services: having one-to-one mappings of virtual (firewall) IP
addresses to publicly accessible servers minimizes confusion at all
levels.

If, however, you don't need more than one protected
server reachable via that port number, then you can simply register a
DNS CNAME record that resolves
ftp.yourdomain.com (or whatever you want your
server to be known as) to the name and thus the primary IP address of
the firewall. Then you can configure your firewall to forward all
incoming connections to that port to your server.


ProFTPD's MasqueradeAddress
directive is useful in either case.

<Limit LOGIN>



DenyAll
</Limit>


This configuration block is used to specify access controls on a
command or set of commands. In Example 11-5, ProFTPD
is configured to deny all attempts by all users (i.e.,
DenyAll) to execute the command
LOGIN (i.e., to log on). This may seem rather
extreme: surely you want to let somebody log on. Indeed you do, and
we'll therefore specify an exception to this
shortly. proftpd.conf
directives are hierarchical, with specific directives overriding more
general ones. Skip ahead to Example 11-6 if
you're curious to see how.




You can use <Limit> configuration blocks in
<Global> blocks, but other limits set in the
base-server and virtual-server settings may or may not take
precedence. Therefore, I recommend using
<Limit> in <Global>
blocks only for commands that aren't limited
elsewhere (i.e., when there are no exceptions to the defined limit).

After base-system settings, you should define global settings. This
is done via one or more <Global>
configuration blocks (multiple blocks will be combined into one by
proftpd's configuration
parser).

Example 11-5 lists our sample FTP
server's global settings. (That is, our
technically global settings, not our
"base-server-but-actually-global"
settings.)

Example 11-5. Global settings in /etc/proftpd.conf


# Global Settings: shared by base server AND virtual servers
<Global>
ServerIdent off
AllowRetrieveRestart on
MaxClients 20 "Sorry, all lines are busy (%m users max)."
MaxClientsPerHost 1 "Sorry, your system is already connected."
Umask 022
User nobody
Group nogroup
</Global>

Again, let's examine these directives:

ServerIdent off



If set to on (the default if empty or left out
altogether), this displays the server's software
name and version prior to prompting users for login. In the interests
of disclosing configuration details only when
necessary, I recommend you set this to
off. If some user's FTP client
software expects or requires server identification, you can always
set it back to on.


AllowRetrieveRestart on



I don't believe this directive has any impact on
security, but it's worth mentioning because
it's a feature many users want. Many Linux users use
the wget command to download files, and one of
wget's best features is the
ability to resume interrupted file transfers. Given the importance
and popularity of this feature, I recommend you set
AllowRetrieveRestart to
on so that your FTP server honors requests for
"download resumption." You can also enable upload resumption (e.g., file writes to
incoming/) by enabling the
AllowStoreRestart directive. But since uploading
is inherently more prone to abuse than downloading, I do not
recommend this even within a controlled incoming
directoryunless you have a compelling need for large file
uploads to succeed at all costs, or if the uploads in question are
performed by authenticated users. (But remember, I
don't believe in using FTP for anything that is that
important to begin withuse sftp or
scp instead!)

MaxClients 20



The MaxClients directive specifies the maximum
number of concurrent logins to a given base/virtual server,
irrespective of the number of active processesi.e., regardless
of whether ProFTPD is being run in standalone mode or from
inetd/xinetd. You may
specify an error message to return to attempted clients who exceed
this number, in which you may reference the "magic
string" %m (which is expanded to
the value of MaxClients).


MaxClientsPerHost 1



Use MaxClientsPerHost to limit the number of
concurrent connections originating from the same
host (based on IP address). On the face of it, this seems a good way
to mitigate DoS attacks and other abuses, except for two problems.

First, multiple users' connections originating from
behind the same firewall or proxy server will typically appear to
come from a single host (i.e., from the proxy or firewall). Second,
users connected to the same client system (such as an
ISP's
"shell-account" server) will
likewise share a single IP.

In short, the MaxClientsPerHost directive assumes
that legitimate users will tend to have unique IP addresses. If you
anticipate this not being the case, set this
directive to a relatively high number (say, 50) or
leave it unset for no limit at all.


Umask 022



As with the umask command in user shells, this
directive specifies hits in the file permissions that cannot be set.
The umask you set with this directive applies to any file or
directory created by a logged-in FTP user. You probably
don't need to set this if you don't
have any writable FTP directories, but then again, it
can't hurt (assuming, of course, you set a
restrictive umask such as 022).


User, Group


When specified in a server section (either base server or a
<Virtual> block), these
directives set the username and group name, respectively, under which
the daemon should run, except when performing privileged functions
such as binding to TCP Port 21 at startup (when ProFTPD must be
root, it will temporarily become
root). If you declare no User
or Group directives, by default ProFTPD will
always run as root, which is dangerous. In most
cases, it makes sense to declare them in a
<Global> block and additionally in
<Anonymous> configuration blocks (see Example 11-6).



11.1.2.6 Anonymous FTP setup


Now that your base-server and global-server options
are defined, it's time to tell your base server
whether and how to handle anonymous FTP
connections. Directives in an <Anonymous>
configuration block override any also set in its
parent configuration (the
base-, global-, or virtual-server section within which the
Anonymous block is nested). Since in Example 11-5 you disabled ordinary user logins (actually
all logins) in the base-server configuration,
you'll need to enable it here, and indeed you shall
(Example 11-6).


Example 11-6. Anonymous FTP settings in /etc/proftpd.conf


# Anonymous configuration, uploads permitted to "incoming"
<Anonymous ~ftp>
User ftp
Group ftp
UserAlias anonymous ftp
MaxClients 30
DisplayLogin welcome.msg
ExtendedLog /var/log/ftp_uploads WRITE uploadz
AllowFilter "^[a-zA-Z0-9 ,.+/_\-]*$"
<Limit LOGIN>
AllowAll
</Limit>
<Limit WRITE>
DenyAll
</Limit>
<Directory incoming/*>
<Limit READ DIRS CWD>
DenyAll
</Limit>
<Limit STOR>
AllowAll
</Limit>
</Directory>
</Anonymous>

And here's the blow-by-blow explanation of Example 11-6:

<Anonymous ~ftp>



In the <Anonymous> tag itself, we must
specify the home directory to be used and chrooted to by these
anonymous users. You can use a tilde (~) as
shorthand for "the home directory of the following
user account." In this example,
~ftp translates to /home/ftp.


User, Group



In the context of server configurations, recall that these directives
apply to the daemon itself. In the context of
<Anonymous> blocks, however, they apply to
the anonymous user in question, i.e., to the specific
proftpd child process handling the
user's connection. In this context, I recommend
setting these to a different username and group than those used by
the server's daemon to more easily differentiate the
restricted environment in which you wish to contain anonymous users.


UserAlias anonymous ftp


The UserAlias directive lets
you map one username to another. Since by convention both the
usernames ftp and anonymous
are allowed for anonymous FTP (and in fact, the original Unix
ftpd automatically accepted the username
anonymous as an alias for
ftp), in Example 11-6
anonymous is being explicitly mapped as an alias
for the real user account ftp.

Note that if the alias you map is an actual account on the server,
users logging in as that username will not have that actual
user's privileges; they'll have
those of the account to which the alias is mapped, which, of course,
is hopefully an unprivileged account. That might seem obvious, but
it's an important security feature (i.e.,
it's one less mistake you as an administrator can
make!). Thus, if I specify UserAlias wizzo ftp,
forgetting that wizzo is a privileged user on my
system, when I later connect as wizzo, I will
have ftp's privileges,
not
wizzo's.


MaxClients 30



This directive does the same thing here it does elsewhere (limits the
total connecting clients), but here it's
specifically for these particular anonymous users.




Which Commands Can ProFTPD Limit?


ProFTPD's configuration
directives, including the <Limit>
configuration block and the ExtendedLog directive,
accept FTP commands as arguments. It may be confusing to some users,
however, that these aren't end-user commands entered
into FTP client software; they're the FTP protocol
commands that the client software sends to the server over an FTP
control channel. Thus, put,
cd, get, et al are
not valid arguments to ProFTPD directives.
Instead, use the commands in Table 11-1.

Table 11-1. FTP commands that ProFTPD may limit

Command

Description

End-user equivalent

CWD

Change working directory.


cd

DELE file

Delete a file.


delete

MKD

Make a new directory.


mkdir

RMD

Remove a directory.


rmdir

RNFR RNTO

Space-separated pair of commands; rename a file or directory.


rename

SITE_CHMOD

Change the mode on a file or directory.


chmod

RETR

Retrieve (download) a file.


get

STOR

Store (upload) a file.


put

ALL

Not a command; wildcard referring to "all FTP
commands."

N/A

LOGIN

Not really a command; used by ProFTPD to limit login attempts.


N/A

DIRS

Not really a command; wildcard that refers to all
directory-list-related commands (e.g., LIST,
NLIST, etc.).


N/A

READ

Wildcard that refers to all file-reading commands but
not directory-listing commands.


N/A

WRITE

Wildcard that refers to all write/overwrite attempts by client
(STOR, MKD,
RMD, etc.).


N/A

DisplayLogin welcome.msg


DisplayLogin tells ProFTPD
to display the contents of the specified file (in this example,
welcome.msg) after a successful logon. This
directive may also be defined at the server level, not just in
<Anonymous> configuration blocks.


ExtendedLog /var/log/ftp_uploads WRITE uploadz



This directive lets you specify a special logfile
(/var/log/ftp_uploads in Example 11-6) to which messages will be written with the
specified format (e.g., uploadz) when the
specified command is executed (WRITE in Example 11-6). If no command is specified, all FTP actions
applicable to the command block or server configuration will be
logged, and if no custom format is specified, the default format will
be used.

This directive may be used for directories specified in
<Directory>
configuration blocks. It may also be used in broader
contexts, as is the case in Example 11-6, in which it
applies to all WRITE commands issued by all
anonymous users applicable to this block.


AllowFilter "^[a-zA-Z0-9 ,.+/_\-]*$"



This handy directive limits the allowable characters in FTP commands
to those contained in the specified regular expression. In Example 11-6, the regexp ("^[a-zA- Z0-9
,.+/_\-]*$
") tells ProFTPD to reject any command string
that contains anything except alphanumeric characters, whitespace,
and the few punctuation marks commonly found in legitimate filenames.
(Since commands' arguments are parsed, too,
it's important to make sure any characters contained
in files you wish to share are included in this regular expression.)
<Limit LOGIN>



AllowAll
</Limit>


Here, finally, we present the base-server configuration with an
exception to its "deny all logins"
policy. Limits specified within a nested configuration block apply
only to that block and to any additional blocks nested within it.
Thus, even though in Example 11-6 it appears as
though all logins will be permitted, in fact, only anonymous logins
to the server will work (i.e., logins to the account FTP or its alias
anonymous).


<Limit WRITE>



DenyAll
</Limit>


This <Limit> block says
that all applicable anonymous clients will be forbidden to write,
overwrite, or create any files or directories.


<Directory incoming/*>...


ProFTPD lets you apply groups of directives to a specific directory
or directory tree via the
<Directory> configuration block. In Example 11-6, the <Directory>
block applies to /home/ftp/incoming/
and its subdirectories: this is to be a publicly writable directory.


<Limit READ DIRS CWD>



DenyAll
</Limit>


First, we specify that the incoming directory
won't be readable, listable, or recurseable. We want
anonymous users to be able to write files into it, period. Letting
them do anything else opens the door for abuses such as sharing
pornography, pirated software, etc.


<Limit STOR>



AllowAll
</Limit>


Finally, in this <Limit> we explicitly allow
the writing of files to this directory. We could have instead used
the wildcard WRITE, but it would allow the
creation of directories, and all we want to allow is file uploads.



That may have seemed like a lot of work, but we've
got a lot to show for it: a hardened ProFTPD installation that allows
only anonymous logins to a restricted chroot environment, with a
special logfile for all attempted uploads.

Hopefully, you also now understand at least the basics of how to
configure ProFTPD. These examples are by no means all inclusive;
there are many other configuration directives you may use. See the
"ProFTPD Configuration Directives"
page (Configurationl) included with ProFTPD
packages and source code for a comprehensive reference for
proftpd.conf.

11.1.2.7 Virtual-server setup


Before
we move on to other things, there's one more type of
ProFTPD configuration we should examine due to its sheer usefulness:
virtual servers. I've alluded to these a couple of
times in the chapter, but to review, virtual-server definitions host
multiple FTP sites on the same host in such a way that they appear to
reside on separate hosts.

Let's look at one example that adds a virtual server
to the configuration file illustrated in Examples Example 11-4 through Example 11-6. Suppose
our FTP server has, in addition to its primary IP address
55.44.33.22, the IP alias 55.44.33.23 bound to the same interface. A
virtual-server definition for this second IP address might look like
Example 11-7.


Example 11-7. A virtual server definition in /etc/proftpd.conf


<VirtualHost 55.44.33.23>
Port 21
<Limit LOGIN>
DenyAll
</Limit>
<Anonymous /home/ftp_hohner>
User ftp
Group ftp
UserAlias anonymous ftp
MaxClients 30
DisplayLogin welcome_hohner.msg
AllowFilter "^[a-zA-Z0-9 ,]*$"
<Limit LOGIN>
AllowAll
</Limit>
<Limit WRITE>
DenyAll
</Limit>
</Anonymous>
</VirtualHost>

Besides the
<VirtualHost> configuration block itself,
whose syntax is fairly obvious (you must specify the IP address or
resolvable name of the virtual host), you've seen
all these directives in earlier examples. Even so, two things are
worth pointing out.

First, the IP specified in the <VirtualHost>
tag can be the host's primary addressi.e.,
the IP of the base server. However, if you do this, you must use the
Port directive to specify a different port from
the base server's in the virtual host setup. A
virtual server can have the same IP address or
the same listening port as the base server, but not
both.

Second, absent from this configuration block but implicit nonetheless
are the settings for ServerIdent,
AllowRetrieveRestart,
MaxClients, MaxClientsPerHost,
Umask, User, and
Group, defined earlier in the
<Global> definitions in Example 11-5 (so are the first eight directives listed in
Example 11-4).

By the way, you may have noticed that I didn't
bother specifying ServerName or
Masquerade
Address. Since the global
ServerIdent setting is off,
these wouldn't be displayed anyway.


Creating IP aliases in Linux is simple. The most
direct method is to use this form of ifconfig:

ifconfig ifacename:n alias where ifacename is the name of the
physical interface to which you wish to bind the alias,
n is an integer (use 0
for the interface's first alias and increment by 1
for each additional alias on the same interface), and
alias is the IP address you wish to add.
The command to create the IP alias used in Example 7-7 would look like this:

ifconfig eth0:0 55.44.33.23 You can add such a command to your /etc/init.d/network
startup script to make the IP alias persistent across
reboots. Alternatively, your Linux distribution may let you create IP
aliases in its network-configuration utility or GUI.


11.1.3. Using vsftpd for Anonymous FTP


ProFTPD is a
flexible and well-maintained FTP package, but it's
not the only good choice: vsftpd, the "Very Secure
FTP Daemon," is increasingly popular and is now
included with recent versions of Debian, SUSE, Fedora, Red Hat, and
other Linux distributions. This is probably because vsftpd provides a
unique combination of security and convenience. vsftpd is very easy
to get up and running in a hurry, without having to make ugly
security-versus-expedience tradeoffs.

Chris Evans
created vsftpd with security as a central design goal, and its track
record so far is impressive; in the three years or so
it's been available (as of this writing), vsftpd has
had zero significant security vulnerabilities.
Regardless of whether that's still true by the time
you read this book, it speaks to vsftpd's excellent
design philosophy, which borrows from OpenBSD's:
"Secure by default, extra features disabled by
default, minimal complexity overall."


How minimalist is vsftpd? Its entire source tree is just over 1 MB in
size (fully uncompressed), and the vsftpd
executable itself is 80 K!

11.1.3.1 Getting and installing vsftpd


As I mentioned,
vsftpd is now a standard package on
many Linux distributions. The usual advantages of binary packages
apply: convenience, easy patching, and minimal impact on other system
software. In Debian, SUSE, Fedora, and Red Hat, the package you need
is predictably named vsftpd. It has no
particularly exotic dependencies. Most users will probably be
perfectly happy with their distribution's stock
vsftpd package.

If your distribution of choice doesn't provide a
binary package for vsftpd, or if you need a later version of vsftpd
than the one your distribution does provide, you'll
need to compile vsftpd from its source code tarball, which is
available at http://vsftpd.beasts.org. The build process
is decidedly old-school:

If you aren't already, become
root.

Unpack the tarball and change your working directory to its root, e.g:

/usr/src-# tar -xf vsftpd-1.2.1.tar.gz; cd vsftpd-1.2.1 Enter the command make without arguments; if it
succeeds, ls -l ./vsftpd should yield something
like this:

-rwxr-xr-x 1 root root 80420 Apr 7 16:43 vsftpd Make sure the user nobody exists; if it
doesn't, create it. This is the account
vsftpd will normally run as.

Create the directory /usr/share/empty if it
doesn't exist already. It should be owned by
root, and neither group- nor
world-writableit will be used as the default vsftpd
chroot[3] jail.

[3] vsftpd, unlike other service daemons such as
Sendmail and BIND, doesn't require an elaborate
chroot jail containing copied parts of the
"real" system file hierarchy.
Rather, all vsftpd needs is an empty directory in which to park
itself when not accessing the local filesystem. Anonymous users are
automatically chrooted to the anonymous user
account's home directory, and if you configure
vsftpd to support nonanonymous users, you can tell vsftpd to chroot
them to their home directories, too. This is yet another example of
vsftpd's providing advanced security features
without requiring lots of work on your part.

Create a home directory for the anonymous ftp user. SUSE
conventionally uses /srv/ftp, and other
distributions use /var/ftp, but it can be
whatever you like. Again, this directory should be owned by
root and not writable by anyone else.

Create an anonymous-ftp user account (e.g., ftp)
and make sure its home directory is set to the one you created in the
previous step.

Now you're ready to copy vsftpd
and the vsftpd(8) and
vsftpd.conf(5) manpages into more useful
locations: enter the command make install.

Manually copy the sample vsftpd.conf file into
/etc.

If you wish to run vsftpd as a standalone daemon, create a startup
script for vsftpd in /etc/init.d. Otherwise,
configure either inetd or
xinetd to start it up as needed (see the
section, Section 11.1.3.3).

If you're running vsftpd as a standalone daemon,
enable the startup script via chkconfig if you
use an RPM-based Linux distribution, or via
update-rc.d if you run Debian GNU/Linux Alternatively, if you install vsftpd from an RPM or deb package, all
these steps will be executed automatically, with the probable
exception of the last one. (Did I mention that binary packages are
much more convenient?) Some distributions require manual intervention
to enable newly installed packages: for example, on my SUSE 9.0
system, although the SUSE vsftpd RPM automatically installed
/etc/init.d/vsftpd for me, I had to issue the
commands chkconfig --add vsftpd and
chkconfig --level 35 vsftpd on to actually enable
the script.

At this point you're ready to configure your shiny
new vsftpd!

11.1.3.2 vsftpd's documentation


Before I begin a discussion of
vsftpd
that is rather narrowly focused on running it as a standalone daemon
serving up only anonymous FTP, I should point out some valuable, much
more complete sources of vsftpd documentation. First, vsftpd comes
with an EXAMPLE directory containing sample
configurations for a variety of FTP scenarios (running standalone,
running with xinetd, serving anonymous users
only, serving local users, etc.).

If you installed vsftpd from source code,
EXAMPLE is a subdirectory of your vsftpd source
code tarballe.g., vsftpd-1.2.1/EXAMPLE.
If you installed vsftpd from a binary package, it's
probably been copied to your system somewhere under
/user/share/doce.g.,
/usr/share/doc/packages/vsftpd/EXAMPLE on SUSE
systems.

As I mentioned in the previous section, vsftpd has manpages, too:
vsftpd(8) and
vsftpd.conf(5). Finally, the default (sample)
vsftpd.conf file itself is well commented. While
it doesn't contain all vsftpd options (even
commented-out), it does contain the most commonly used ones, and
I've successfully gotten vstpd working several times
with only minimal tweaking to the sample
vsftpd.conf file.

11.1.3.3 Standalone daemon versus inetd/xinetd


Before configuring
vsftpd itself, you must
decide whether to run it as a standalone daemon or via a
"super-server"
(inetd or xinetd). With
previous versions of vsftpd, its developer, Chris Evans, recommended
using it with xinetd due to
xinetd's logging and
access-control features. However, vsftpd Versions 1.2 and later have
native support for most of those features. For this reason, Mr. Evans
now recommends that vsftpd be run as a standalone daemon.

In addition, the pros and cons I discussed earlier in the section
Section 11.1.2.1.1 all apply here. The
most important of these is that there's a
performance cost associated with using inetd or
xinetd, a cost that isn't
warranted if your system is to be a dedicated FTP server (or if you
anticipate FTP comprising a significant percentage of your
system's activity).

Because this book is about bastion servers, as with ProFTPD,
I'm going to take the liberty of using
standalone-daemon examples for the remainder of this section.
vsftpd's documentation amply describes how to use
vsftpd with inetd and
xinetd: see the example configurations included
in vsftpd's EXAMPLE directory.

Interestingly, the vsftpd package that comes with SUSE 9 is
preconfigured to be run from xinetd, and Debian
3.0's runs from inetd. This is
especially logical in the latter case, since Debian 3.0 comes with an
older version of vsftpd (1.0.0), but SUSE 9.0 provides vsftpd 1.2.
(The vsftpd RPMs that come with Fedora and Red Hat install
vsftpd as a standalone daemon.) At any rate,
there are two steps to converting vsftpd from
inet/xinetd startup to
standalone startup.

First, as I mentioned under Section 11.1.3.1, you must make sure
you've got an enabled startup script for vsftpd in
/etc/init.d. The Fedora Core 2 and SUSE 9.0
packages both provide and install one (in SUSE's
case it's present but disabled by default, in favor
of xinetd). If you used Debian
3.0's vsftpd package, or
installed vsftpd from source, however, you'll need
to create your own startup script and create the corresponding links
in rc3.d, rc5.d, etc.,
preferably automatically (i.e., via chkconfig or
update-rc.d).

Second, you'll need to either disable
vsftpd's xinetd file (by
setting disable = yes in the file
/etc/xinetd.d/vsftpd
) or comment out
vsftpd's line in
/etc/inetd.conf. Alternatively, you can disable
inetd or xinetd altogether,
if vsftpd was the only important thing it was starting.


Arguably, it's irresponsible of me to recommend that
you enable an application's startup script before
you've fine-tuned that
application's security. In my opinion, enabling is
one thing; you're fine so long as you follow through
and lock down the service before actually
starting it (or rebooting your system).

Third, you'll need to make sure that in
/etc/vsftpd.conf, the parameter
listen is set to YES. Which
brings us to vsftpd configuration proper.

11.1.3.4 Configuring vsftpd for anonymous FTP


Actually, you very well may not need
to do anything more to configure vsftpd for
secure anonymous FTP: its default configuration settings permit
only anonymous FTP! What's
more, no "write" commands of any
kind are enabled by default, and in recent versions of vsftpd, the
daemon chroots itself to the directory
/usr/share/empty whenever possible. This is one
of the things I love about vsftpd: it actually takes more
work to loosen its security than it does to tighten it
down!

Assuming your distribution hasn't altered this
default behavior, all you need to do now is populate your anonymous
FTP user account's home directory with FTP content
for people to download. On Debian 3.0, SUSE 9.0, and Fedora Core 1,
the anonymous FTP user is ftp by default, with a
home directory of /srv/ftp for Debian and SUSE
and /var/ftp in the case of Fedora. If you
installed vsftpd from source, the anonymous FTP directory is whatever
home directory you assigned to the anonymous FTP user account you
created.


Pay special attention to ownership and permissions when populating
your FTP directories. Defaults may or may not be appropriate, but at
least do a quick ls -al now and then to see for
yourself!

Even though their default settings suffice for many users,
let's take a closer look at the
vsftpd.conf parameters most relevant to
anonymous FTP. (By default, this file resides in
/etc, but on Red Hat and Fedora systems it
resides in /etc/vsftpd/). Example 11-8 shows a sample
vsftpd.conf file.

Example 11-8. vsftpd.conf settings for anonymous FTP


listen=YES
# listen_address=
anonymous_enable=YES
ftp_username=ftp
# anon_root=[$ftp_username's home directory]
write_enable=NO
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO
anon_world_readable_only=YES
anon_max_rate=0
idle_session_timeout=300
ascii_download_enable=NO
ascii_upload_enable=NO
connect_from_port_20=NO
port_enable=YES
hide_ids=NO
log_ftp_protocol=NO
syslog_enable=NO
max_per_ip=0
# cmds_allowed=
local_root=/usr/share/empty
nopriv_user=nobody
ftpd_banner=(vsFTPd 1.2.0) In practice, you'd never use a
vsftpd.conf file exactly like Example 11-8: all parameters in it are, in fact, set to
their default values. Rather, this listing is meant as a quick
reference. Let's discuss its parameters in turn:

listen



Tells vsftpd to run as a daemon rather than as a
"per-connection" process invoked as
needed by inetd or xinetd.
Default value is NO.


listen_address



Specifies which local IP address vsftpd should listen for connections
to. The default is " (null), signifying
"all local IP addresses," but if
you wish to run multiple "virtual FTP
servers," you'll need to set this
parameter in each virtual server's configuration
file (see the next section, "Virtual
servers").


anonymous_enable



This parameter, whose default is YES, determines
whether vsftpd will accept anonymous logins. If set to
YES (or not set at all), vsftpd will accept
connections from the users anonymous and
ftp (the two are equivalent) without requiring a
real password.


ftp_username



The name of the user account used for anonymous logins, i.e., FTP
logins as anonymous and
ftp. This account must exist in
/etc/passwd and should have a valid home
directory that is not owned by the user account.


anon_root



The directory vsftpd should chroot into for anonymous logins. This
defaults to the home directory of the anonymous FTP user account (see
ftp_username), but you can use this parameter to
set a different anonymous FTP root. Either way, this directory should
not be owned by the anonymous FTP user.


write_enable



Unless this parameter is set to YES, no user may
upload any files under any circumstances, regardless of other
settings in vsftpd.conf.


anon_upload_enable



If this parameter and write_enable are both set to
YES, anonymous users will be permitted to upload
files into directories for which the anonymous user account has
write permission.


anon_mkdir_write_enable



If this parameter and write_enable are both set to
YES, anonymous users will be permitted to create
new directories within directories to which the anonymous user
account has write permission.


anon_other_write_enable



If this parameter and write_enable are both set to
YES, anonymous users will be permitted to delete
and rename directories within directories to which the anonymous user
account has write permission.


anon_world_readable_only



If set to YES, this parameter forbids anonymous
users from downloading any non-world-readable file. Most useful if
anonymous users are able to upload files that you
don't want other anonymous users to download.


anon_max_rate



Specifies the maximum data-transfer rate, in bytes per second, that
anonymous users may use. The default value is 0,
which means "unlimited."

idle_session_timeout



The maximum amount of time, in seconds, allowed to transpire between
FTP commands until a session is forcibly closed by the server.
Default value is 300, but if
you're worried about Denial of Service attacks you
may wish to set this lower.


ascii_download_enable



If set to YES, this allows users to perform
ASCII-mode downloads (as opposed to binary-mode downloads). The
default is NO because (a) ASCII mode is seldom, if
ever, really necessary, and (b) it's much less
efficient, so much so as to represent a potential vector for Denial
of Service attacks.


ascii_upload_enable



ASCII-mode uploads, on the other hand, are sometimes necessary for
things like scripts. This parameter's default value
is, nonetheless, NO.


connect_from_port_20



In active-mode FTP sessions, whenever a user downloads anything
(including directory listings), the server initiates a new connection
back to the client, conventionally originating from the
server's TCP port 20. By default, however, vsftpd
originates such connections from a higher (nonprivileged) port, in
order to avoid having to run as root. To change
this default behavior (e.g., if your FTP users connect from behind
proxies or firewalls that don't expect such
behavior), set this parameter to YES.


port_enable



Set this to NO to disable PORT
commands, which will effectively disable active-mode FTP altogether.
Default is YES.


hide_ids



If set to YES, replaces the owner and group fields
in all directory-listing output to ftp and
ftp, respectively. Personally, I think this can be
a useful bit of obscurity when used on public FTP servers, but the
default is NO.


log_ftp_protocol



If set to YES, turns on per-command logging (the
FTP protocol commands listed in Table 11-1, which
are triggered by, but distinct from, FTP user-space commands).
Invaluable for troubleshooting.


syslog_enable



Normally vsftpd writes log messages to
/var/log/vsftpd.log. Setting this parameter to
YES (its default is NO) sends
those messages instead to the system's syslog
service, using the FTPD facility.


max_per_ip



Specifies the maximum number of concurrent connections permitted from
a single source-IP address. Note that limiting this may seem like a
good idea (the default is 0, which means
unlimited), but it will have a disproportionate effect on users
connecting from behind NAT firewalls (which can cause multiple users
to appear to originate from the same source-IP address).


cmds_allowed



Specifies a comma-separated list of allowed FTP commands; default
value is " (null), which means
"unlimited." Note that only FTP
protocol-level commands such as those listed in Table 11-1 may be specified, not the
commands commonly accepted by FTP client software packages. For
example, to allow clients only to list files, change working
directories, and download files, you'd use
cmds_allowed=USER,LIST,NLST,CWD,RETR,PORT,QUIT.
The web site http://www.nsftools.com/tips/RawFTP is a
useful reference for these commands.


local_root



This specifies an empty,
root-owned directory in which
vsftpd chroots itself any time it doesn't need
access to other parts of the filesystem. Default value is
/usr/share/empty.


nopriv_user



Specifies the nonprivileged user vsftpd runs as whenever possible.
Obviously vsftpd needs to be root when doing
things like binding to TCP port 21, but it demotes itself as soon as
it can, in order to lessen the chance of a buffer-overflow
vulnerability or other
"process-hijacking" event leading
to root compromise.


ftpd_banner



Banner message to display when FTP clients attempt to connect.
Default message is hardcoded into vsftpdin v1.2.0,
it's simply "(vsFTPd
1.2.0)." Alternatively, you can use the parameter
banner_file to specify a text file containing your
banner message.



The vsftpd.conf(5) manpage explains these and
many other parameters you can use; believe it or not,
I've only scratched the surface here.

11.1.3.5 Virtual servers


If you wish to have multiple
"virtual FTP servers"
residing on the same physical host (i.e., one with multiple IP
addresses), this is very easy to do with vsftpd. All you need to do
is run multiple instances of the vsftpd daemon,
each with its own vsftpd.conf file specifying
which IP address to listen on, which directory to use as its
anonymous root, etc.

For example, suppose I've got two IP addresses
assigned to my machine, 1.2.3.4 and 1.2.3.5, registered in DNS to the
names knusper and rover,
respectively. In that case, I could have two configuration files for
vsftpd, say, /etc/vsftpd.knusper and
/etc/vsftpd.rover. Examples Example 11-9 and Example 11-10 show these
files.

Example 11-9. Virtual FTP server configuration file /etc/vsftpd.knusper


listen=YES
listen_on=1.2.3.4
connect_from_port_20=YES
anonymous_enable=YES
anon_root=/srv/ftp/knusper
ftpd_banner=Welcome to FTP at knusper.wiremonkeys.org. Behave!

Example 11-10. Virtual FTP server configuration file /etc/vsftpd.rover


listen=YES
listen_on=1.2.3.5
connect_from_port_20=YES
anonymous_enable=NO
ftpd_banner=Private FTP at rover.wiremonkeys.org. Strangers-B-gone.
# DANGER: don't use the following unless you know what you're doing
local_enable=YES Note my possibly foolish use of the local_enable
parameter in Example 11-10. It's
dangerous to set this to YES, since FTP logon
credentials are sent in cleartext; you never want to expose real
system credentials to eavesdropping, especially if your server is
Internet-connected.

The real reason I show it here is to illustrate that since each
virtual server uses its own configuration file, you can specify
completely different behaviors for different servers. For instance,
one virtual server may have a public uploads
directory that anonymous users may write to, whereas another may be a
strictly read-only FTP site. Conversely, you need to take care that
settings you consider to be important in preserving overall system
security are set consistently on different virtual servers running on
the same machine.

Besides creating different configuration files for each virtual FTP
server you wish vsftpd to serve up, you also need to alter your
startup script accordingly. The startup script on my sample server
represented by Examples Example 11-9 and Example 11-10 would need something equivalent to these two
lines:

vsftpd /etc/vsftpd.knusper
vsftpd /etc/vsftpd.rover If you run Red Hat or Fedora, this has already been taken care of for
you: the /etc/init.d/vsftpd script included with
those distributions' vsftpd RPM packages
automatically parses the directory /etc/vsftpd
for as many configuration files as you care to put there, so long as
the filename of each ends in .conf. This strikes
me as an excellent bit of foresight on the part of the Red Hat team.

That's all you need to know about setting up a
simple and secure anonymous FTP server with vsftpd. But as I
mentioned, I've covered only a subset of what vsftpd
is capable of doing; despite its minimalist design philosophy, this
is a powerful FTP server indeed. Fortunately, it's
also very well documented, so it's really no cop-out
for me to refer you to the vsftpd.conf(5)
manpage and the EXAMPLE directory for
information on the many other uses of vsftpd.


/ 94