11.1. FTP SecurityWhat 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 SecurityWith 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 FTPTo 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.
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 FTPAs 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?
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 FTPMy 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 FTPThat'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 ProFTPDProFTPD 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 modeOn 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 modulesLike 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 jailOnce 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 ftpftp: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 configurationNow 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 settingsOn 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. 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.
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 setupNow 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: 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. 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> 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> 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> 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> 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 setupBefore 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.
11.1.3. Using vsftpd for Anonymous FTPProFTPD 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." 11.1.3.1 Getting and installing vsftpdAs 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 documentationBefore 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/xinetdBefore 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. 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 FTPActually, 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. 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 FTPlisten=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: 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.
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").
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.
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.
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.
Unless this parameter is set to YES, no user may upload any files under any circumstances, regardless of other settings in vsftpd.conf.
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.
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.
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.
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.
Specifies the maximum data-transfer rate, in bytes per second, that anonymous users may use. The default value is 0, which means "unlimited." 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.
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-mode uploads, on the other hand, are sometimes necessary for things like scripts. This parameter's default value is, nonetheless, NO.
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.
Set this to NO to disable PORT commands, which will effectively disable active-mode FTP altogether. Default is YES.
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.
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.
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.
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).
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.
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.
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.
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 serversIf 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.knusperlisten=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.roverlisten=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. |