This chapter is provided on an “as is” basis as part of the Apress Beta Book Program. Please note that content is liable to
change before publication of the final book, and that neither the author(s) nor Apress will accept liability for any loss or
damage caused by information contained.
Copyright © 2004. For further information email
All rights reserved. No part of this work may be reproduced in any form or by any means, electronic or mechanical, including
photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the
copyright owner and the publisher.
Chapter 10
Securing an FTP Server
File Transfer Protocol or FTP is one of the original core protocols of the Internet and was
first documented in 1971. It was designed to provide the functionality to exchanges files over
the Internet and is specified in RFC 959.
1
It is still currently used for a number of purposes,
including running user and anonymously authenticated FTP servers for the provision of files
and applications for download. For example, it is utilized by software vendors to provide
updates or patches to clients. It is also used to transfer of files between disparate systems, for
example many non-Unix systems also support the FTP protocol. One of the most common
uses of FTP is by ISPs to provide customers with the ability to upload files to their web sites.
At first look FTP would seem to fulfill a useful and practical function. Unfortunately
FTP is also inherently insecure. The only security available to most FTP sessions is a
username and password combination. By default FTP transactions are conducted
unencrypted and all traffic is sent in clear-text across your network. This includes the
transmission of user names and passwords. This exposes you to a considerable level of risk
that is difficult to mitigate with available tools.
Due to the inner workings of FTP it is not possible to use tools such as Stunnel to secure
FTP traffic and we'll explain why this is so in the next section. Additionally many of the
available open source and commercial FTP servers have proven to be subject to
vulnerabilities. Many FTP servers are easily compromised and thus can provide a point of
access for an attacker into your system. Or they have vulnerabilities that could allow Denial
of Service (DoS) attacks on your systems. In addition to these other potential insecurities
FTP is also vulnerable to so-called 'man-in-the-middle' attacks where your data is intercepted
and then either stolen or altered and sent on. For example, this is one of the primary methods
hackers use to penetrate and hack web servers. New material is uploaded to a web server via
FTP. The hacker finds the IP address of the web server and sets up a sniffer to watch FTP's
TCP port 21. When next you update the site it grabs your username and password and this is
used to upload material of the hacker's choice to the system or to steal any valuable
information, such as credit card details, from your site.
Given the weaknesses of FTP we'd recommend you not run it at all as a production server
on any systems, unless you absolutely require the functionality. There are some commercial
secure FTP servers available on the market. But these usually require a client that is
compatible with the secure server. If you have a proprietary commercial FTP server running
with encryption or enhanced authentication then generally clients other than the proprietary
client designed for that server will not be able to connect or will only be able to connect to
the server using standard FTP without any additional security.
1
/>There are some alternatives to FTP. Indeed for the process of transferring files between
systems there are other mechanisms which are considerably more secure. These include sftp
or scp from the OpenSSH toolkit (as we discussed in Chapter 3). Indeed if the remote
systems are configured correctly then SSH can be used to upload files to remote systems such
as web servers without requiring an FTP port to be open on them. We'd recommend you look
at these options rather than use FTP.
If you must use FTP then in this we'll try to provide as secure as possible implementation
of an FTP server. We'll show you how FTP works and how best to firewall it. Additionally
we'll take you through installing a secure anonymous FTP server, a local user authenticated
FTP server, and examine support for FTP over SSL/TLS. As part of this we will also
demonstrate how to chroot your FTP server and mitigate the risk of DoS attacks.
How Does FTP work?
FTP has two key components - a client and a server. This chapter will focus on the server
component of FTP. FTP is a stateful protocol, meaning that connections between client and
server are created and kept open during an FTP session. Commands that are issued to the
FTP server, for example a file upload or a directory listing, are executed consecutively. If a
command arrives while another command is being executed then the new command is
queued and will execute when the current command has completed.
NOTE: FTP is a TCP only protocol. There are no UDP elements to FTP.
When making an FTP connection two types of connections are initiated. A control, also
called a 'command', connection and a data connection. When you connect an FTP client to an
FTP server a single control connection is established by default using the TCP port 21. This
connection is used for the authentication process, for sending commands and receiving
response messages from the remote server. It does not do the actual sending and receiving of
information or files. The sending and receiving of files is handled by the data connection. A
data connection is established only when a file needs to be transferred and is closed at the end
of the transfer.
There are two types of data connection, active mode connections and passive mode
connections. Active connections use the PORT command and are initiated by the remote
server and the client listens for the connection. Passive connections use the PASV command
and the client initiates the connection to the remote server and the server listens for the data
connections. When the client starts a transfer it tells the server what type of connection is
wishes to make. In modern FTP clients and servers the most common connection type is
passive connections.
In active mode the client connects from a random source port in the ephemeral port range
(see Chapter 2) to the FTP control port 21. All commands and response codes are sent on
this control connection. When you actually want to transfer a file the remote FTP server will
initiate a connection from the FTP data port 20 on the server system back to a destination port
in the ephemeral port range on the client. This destination port is negotiated by the port 21
control connection. Often the destination port used is one port number higher than the source
port on the client. You can see an illustration of an active mode connection in Figure 10-1.
Insert 4444ch10f1.tif
Figure 10-1 Active mode FTP connection
Active mode connections often have issues with firewalls. On the server-side with an active
mode connection you need to have the TCP ports 20 and 21 open on your firewall. On the
client side we need the range of ephemeral ports open. Often opening these ports is hard to
do if your FTP client is behind a firewall. In a secure firewall configuration these ports
should generally be closed. Additionally because the remote server initiates the connection
many firewalls will drop the connection because they are only designed to accept established
connections on specific limited ports. Finally if you are behind a firewall that uses many-to-
one Network Address Translation (NAT) it is often impossible for the firewall to determine
which internal IP address initiated the FTP connection. This is caused by the firewall's
inability to correlate the control and data connections.
As a result of the issues active mode connections have with firewalls, passive mode
connections were introduced. In passive mode the client initiates both sides of the
connection. Firstly the client initiates the control connection from a random ephemeral port
on the client to the destination port of 21 on the remote server. When it needs to make a data
connection the client will issue the PASV command. The server will respond by opening a
random ephemeral port on the server and pass this port number back to the client via the
control connection. The client will then open a random ephemeral source port on the client
and initiate a connection between that port and the destination remote port provided by the
FTP server.
Insert 4444ch10f2.tif
Figure 10-2 Passive mode FTP connection
Passive mode connections mitigate the issue of the remote server initiating the connection to
the client and being blocked by a firewall. This is because the client initiates both the control
and data connections. Thus firewalls see the outgoing FTP data connection as part of an
established connection. You still need to have ephemeral ports open on the server and client
side of the connection. But this too can be partially mitigated because many FTP servers
allow you to specify the range of ephemeral ports rather than using the entire ephemeral ports
range. But you still need to open a suitable range to allow your FTP server to function.
Overall the random ephemeral port selection, for both active and passive connections, is
one of the reasons why securing FTP is difficult. In order to achieve a secure connection the
securing application needs to know which ports to secure. As this port choice is random, the
securing application has not means of determining what port needs to be secured.
Firewalling your FTP server
There is a method of further locking down your FTP connections. To this we can use iptables
with a module called ip_conntrack_ftp. The ip_conntrack_ftp module uses connection state
tracking to correlate and track FTP transactions. We first introduced connection state
tracking in Chapter 2. Let's look at creating some iptables rules for our FTP server.
We have discussed in the How Does FTP Work? section that in order for the FTP server
to function you will need a combination of the ports 20, 21 and the range of ephemeral ports
open on both the client and server. This combination is partially dependant on the connection
mode we are running on our FTP server. We're going to assume we are creating firewall
rules for an FTP server running on interface eth0 and bound to IP Address, 192.168.0.1. We
will assume we only want FTP connections into the system and we don’t want to allow
outgoing FTP connections.
The first rules we are going to create are for the FTP server's control connection, which
uses TCP port 21. As these rules address the control connection they are identical for active
and passive mode FTP, as the control connection is required for both modes.
puppy# iptables –A INPUT –i eth0 –p tcp --dport 21 –d 192.168.0.1 –m state --state
NEW,ESTABLISHED,RELATED –j ACCEPT
puppy# iptables –A OUTPUT –o eth0 –p tcp --sport 21 –s 192.168.0.1 –m state --state
ESTABLISHED,RELATED –j ACCEPT
In the two rules we've just specified, incoming traffic on interface eth0 to IP Address
192.168.0.1 and TCP port 21 in the connection state of NEW, ESTABLISHED or RELATED
is allowed to enter the host. Outgoing traffic on the same interface, IP Address and port in
the connection states ESTABLISHED and RELATED is allowed to exit the host.
The control connection is not the whole story though. The FTP server also needs the data
connection opened in our firewall for the server to correctly function. As we have discussed
this data connection can run in two modes: active and passive. For example, the active mode
connection requires a substantial port range open. To function correctly the active mode
requires port 20 open on the FTP server and additionally on the server we need to accept
incoming connections from the ephemeral port range on the client host. The passive mode
connection requires ports in the ephemeral port range to be open on both the client and the
server. Both of these models pose security risks.
To help mitigate this security risk we are going to utilize the ip_conntrack_ftp module.
This module is an iptables kernel module that extends the functionality of the connection
state tracking that we discussed in Chapter 2. This module is provided with most
distributions and with all recent releases of iptables.
Firstly we need to load the required module like so,
puppy# insmod ip_conntrack_ftp
The module may be already loaded on your system and it will return an error message if this
is the case. You need to load the module each time your system restarts. It is recommended
you load this module when you start iptables.
The ip_conntrack_ftp module tracks FTP connections and watches for the use of the
PORT or PASV command on port 21 which indicates that a data connection is being
initiated. The module then makes note of and tracks the ports being used by the data
connection. This allows iptables to correlate and track the control and data connections for a
particular FTP transaction. The module allows iptables to reference the data connection as a
RELATED state. Thus we can use the RELATED connection state rather than the NEW
connection state in our INPUT chain. This means ports on our host only need to be open for
RELATED connections not NEW connections from ephemeral ports. This reduces the risk
posed by running an FTP server and allows us to more tightly firewall these connections.
We still need to approach rules for active and passive mode connections differently to
address their different port requirements but now we can specify a much tighter set of
iptables rules. In Example 10.1 we specify some rules for active mode data connections.
Example 10.1 Rules for active mode connections
puppy# iptables -A INPUT -i eth0 -p tcp --sport 1024: --dport 20 -d 192.168.0.1 -m state --state
ESTABLISHED,RELATED -j ACCEPT
puppy# iptables -A OUTPUT -o eth0 -p tcp --dport 1024: --sport 20 -s 192.168.0.1 -m state --
state ESTABLISHED -j ACCEPT
The first rule in Example 10.1 allows incoming traffic from source ports higher than 1024 on
interface eth0 to IP Address 192.168.0.1 and port 20 in the ESTABLISHED and RELATED
states. This prevents new connections being made to this port. The only incoming
connections should be the data connection portions of existing FTP connections. This
increases the level of security on your host firewall. The second rule allows outgoing traffic
in the ESTABLISHED and RELATED states outbound from the host to destination ports
higher than 1024.
Passive mode FTP is very similar. Using the ip_conntrack_ftp module we can track the
state of the connections and the port numbers used and thus can use the RELATED state for
our iptables rules. Example 10.2 shows an INPUT and OUTPUT rule for passive mode
connections.
Example 10.2 Rules for passive mode connections
puppy# iptables -A INPUT -i eth0 -p tcp --sport 1024: --dport 1024: -d 192.168.0.1 -m state --
state ESTABLISHED,RELATED -j ACCEPT
puppy# iptables -A OUTPUT -o eth0 -p tcp --sport 1024: --dport 1024: -s 192.168.0.1 -m state --
state ESTABLISHED -j ACCEPT
The first rule in Example 10.2 allows incoming traffic from the ephemeral ports (which we've
defined as all ports greater than 1024 in our rules) to interface eth0 and IP Address
192.168.0.1. The second rule provides the same functionality for outgoing traffic.
Neither Example 10.1 nor Example 10.2 are ideal solutions. These rules leave your
firewall comparatively quite open compared to the models we proposed in Chapter 2. But
they are the securest possible rules we can create on a host system for an FTP server. This
again highlights that there are risks involved in running an FTP server that simply cannot be
mitigated.
TIP: When we look at vsftpd we'll look at refining the range of ephemeral ports that
the FTP server can use. This can further limit the range of ports you need to open on
your host.
What FTP server to use?
There are a number of FTP servers available, both commercial and open source products.
We're going to look at vsftpd, which is an open source FTP server. The vsftpd package has a
reputation for security and is a compact but also fully featured and well performing
application. At the time of writing vsftpd had only one vulnerability listed at the Security
Focus' Bugtraq
2
site as opposed to multiple issues for other FTP server packages like
ProFTPD and WU-FTPD. It is regularly updated and maintained. It is also widely available
on most Linux distributions.
The vsftpd daemon has some good security features including:
* Can run as a non-privileged user with privilege separation.
* Supports SSL/TLS FTP transfers.
* Can chroot users into their home directories and chroot anonymous FTP
access to a particular directory.
2
/>* Can limit the FTP commands that a user can execute.
* Reduces the risk of DoS attacks with bandwidth and connection limits.
* It is coded to reduce the risk of buffer overflow attacks.
The vsftpd FTP server is both secure and high performance. It is used by a number of
organizations as a result of this, including Red Hat, Debian, OpenBSD.org, ftp.kernel.org,
ftp.isc.org. If you don’t use vsftpd we'd recommend you migrate to it. Especially if you are
using ProFTPD and WU-FTPD, both of which have been subject to a large number of easy to
exploit vulnerabilities. If you are going to take the risk of using an FTP server then we
recommend you chose the safest and most secure possible server.
Installing vsftpd
Many distributions come with vsftpd and it should be available through your package
management system. On a Debian system it is available as a package and we can use apt-get
to install vsftpd.
kitten# apt-get install vsftpd
Or it is available as an RPM for Red Hat and Mandrake. To get the most recent version of
vsftpd you can download the source package from />We're going to download the source package to ensure we are using the most up to date
version of the package.
puppy# wget />After downloading the package, unpack the source package and change into the resulting
directory. Vsftpd doesn't use a configure script but rather has a file called builddefs.h which
contains the compilation variables. Example 10.3 shows the contents of this file.
Example 10.3 Initial builddefs.h
#ifndef VSF_BUILDDEFS_H
#define VSF_BUILDDEFS_H
#undef VSF_BUILD_TCPWRAPPERS
#define VSF_BUILD_PAM
#undef VSF_BUILD_SSL
#endif /* VSF_BUILDDEFS_H */
You can enable SSL, PAM and TCP Wrappers in this file. To enable features in vsftpd you
need to change each definition line for the feature you wish to enable from,
#undef VSF_BUILD_SSL
to,
#define VSF_BUILD_SSL
We are going to enable SSL and PAM in vsftpd. Example 10.4 shows our final builddefs.h
file.
Example 10.4 Final builddefs.h
#ifndef VSF_BUILDDEFS_H
#define VSF_BUILDDEFS_H
#undef VSF_BUILD_TCPWRAPPERS
#define VSF_BUILD_PAM
#define VSF_BUILD_SSL
#endif /* VSF_BUILDDEFS_H */
Now you can make the vsftpd binary.
puppy$ make
This will create a binary called vsftpd in the package directory. You can then install vsftpd
using the command:
puppy# make install
Vsftpd requires that you create some supporting configuration items. First you need to create
a user for the vsftpd binary to run as. This allows the vsftpd binary to drop privileges and run
as a normal user thus providing more security against any compromise of the vsftpd daemon.
By default vsftpd runs as the user nobody. This user exists on most systems but may be
being used by a number of different daemons. It is safest to create another user for the vsftpd
daemon to run as. We have chosen to create a user called ftp_nopriv. You can create this
user with the command in the following example.
Example 10.5 Creating the ftp_nopriv user
puppy# useradd -d /dev/null -s /sbin/nologin ftp_nopriv
You also need to create the /usr/share/empty directory.
puppy$ mkdir /usr/share/empty
This directory may already exist on some systems. It is used by vsftpd as a chroot directory
when the daemon does not require file system access. You should ensure this directory is not
write-able by the ftp user and remains empty of all content.
If you wish to use anonymous FTP then you need to create a user called ftp. This user
needs to have a valid home directory that needs to be owned by the root user and has its
permissions set to 0755. The ftp user's home directory will be the root directory for
anonymous FTP access.
puppy# mkdir /var/ftp
puppy# useradd -s /sbin/nologin -d /var/ftp ftp
puppy# chown root:root /var/ftp
puppy# chmod 0755 /var/ftp
Lastly you need to copy the sample configuration file from the vsftpd package into the /etc
directory.
puppy# cp vsftpd.conf /etc
In the next section we will look at modifying this configuration file.
Configuring vsftpd for anonymous FTP
The vsftpd daemon is controlled by the vsftpd.conf file. The vsftpd binary has only one
command-line option, which allows you to specify the location of the vsftpd.conf
configuration file.