ProFTPD and Virtual Servers


What is a virtual server?
A virtual server, also known as a virtual host (or vhost for short), refers to the practice of serving more than one address/site on a single host machine. The fact that these multiple sites are being served by the same physical machine is transparent to the end user.

The definition of the File Transfer Protocol, unfortunately, does not (currently) support name-based virtual hosts, as HTTP1.1 supports. All FTP virtual hosts are based on unique IP address/port combinations, not on DNS names. The similarity of ProFTPD's configuration file syntax to Apache's sometimes leads users to assuming that proftpd will handle these the same way -- but more on this later. The bottom line is that ProFTPD does not support name-based virtual hosts; not because they are not implemented, but simply because the protocol itself does not support them.

In some documents, one might see reference to both "daemon" and "server". Sometimes these words are used interchangeably; however, there is a slight difference. A "daemon" is a long-lived process on a host machine, and a "server" is a process that provides some service, typically to remote clients. A process, such as a standalone proftpd process, can be considered both a "daemon" and a "server". With this in mind, then, a "virtual server" is not a separate process itself; it just looks like one to the remote clients. Hence the "virtual".

There are three "server" contexts (sometimes also called sections) in the proftpd.conf configuration file: <VirtualHost>, <Global>, and "server config".

The <VirtualHost> context is used to define the configuration for a particular virtual host, bound to an IP address. For example:

  <VirtualHost 1.2.3.4>
    ...
  </VirtualHost>
defines a configuration for a virtual server that proftpd should use whenever a remote client connects to the IP address 1.2.3.4. DNS names, too, can be used with the <VirtualHost> configuration directive, and this is where some of the name-based vhost support confusion creeps in:
  <VirtualHost ftp.mydomain.com>
    ...
  </VirtualHost>
When proftpd parses this context on startup, it will resolve the given DNS name to its IP address and use that, just as if that IP address had been used in the first place. Use of DNS names like this, while convenient, can easily lead to confusion when multiple DNS names resolve to the same IP address. If this happens, proftpd will use the first context in the configuration file when serving that address.

The <Global> context is provided as a convenience. Imagine that the administrator has many <VirtualHost> contexts in her proftpd.conf, and yet has a lot of the same configuration for each virtual host, such as common <Directory> sections, DefaultRoot settings, etc. Rather than including the same configuration over and over, she could use the <Global> context:

  <Global>
    ...
  </Global>
Anything inside of a <Global> section is applied to every server configuration in the file, to every <VirtualHost> as well as the default "server config" server.

Which brings us to the "server config" context. The name is ill-suited, and is really borrowed directly from Apache's naming conventions. The "server config" context refers to anything not in a <VirtualHost> or <Global> context in the proftpd.conf file. Unlike Apache's httpd.conf, ProFTPD's configuration is designed such that one should be able to use the simplest file as possible. In fact, proftpd will start if the proftpd.conf is completely empty; try it! This will cause the daemon to use all of the default settings, which in most cases is not what is wanted, but it is possible. With this in mind, there is always at least one server configuration present: the default server context, and it is this context that is known as the "server config". Just like the <VirtualHost> context, any configuration directives inside the "server config" context do not apply outside of the context. Many administrators often assume that this is the case. It is not. This is what the <Global> context is for.

However, one particular drawback to the "server config" context was that it did not provide a way to specify to which IP address that configuration pertained. By default, when proftpd parses the proftpd.conf file, it will use the gethostname() function to determine the IP address to which the default server should listen. On a single address, single interface system, this default is fine. It is one a multiple address system that the default handling does not always work; the administrator may wish to explicitly specify to which address the default server should listen. This is what the DefaultAddress configuration directive provides: the ability to specify to which IP address the "server config" vhost should listen.

By default, every server will listen to port 21, the IANA standard port for FTP. If you want to have server react to a different port, use the Port directive to change the port. As might be mentioned elsewhere, if you have many different <VirtualHost> contexts using the same address but different ports, you'll want to make sure that you leave each Port-1 number empty. RFC 959 specifies that the source port for an active data transfer (read here) must be L-1, where L is the port on which your server listens. Also, as mentioned in the Port documentation, using:

  Port 0
in any server context will effectively "disable" that server. This is sometimes used to disable the "server config" configuration.

There is another configuration directive that comes into play in all of this : DefaultServer. Here is why: when a client contacts proftpd, the server has to determine which configuration to use for handling the client. To do this, it searches its list of configured vhosts, searching for a vhost whose IP address matches the IP address that the client contacted. If there's a matching vhost for that IP address, simple: use that configuration. If not, proftpd will then resort to using the configuration that bears the DefaultServer directive, which says that the server configuration in which it appers should be used in cases like this. If there is no DefaultServer directive in the proftpd.conf file, and no matching configuration can be found, then the client will see a message such as "no server available to service your request". The DefaultServer can be used to say that a <VirtualHost> should be the default, and not necessarily the "server config" context, as is common.

If you would like the same virtual host configuration to be used for multiple different IP addresses (or DNS names), the <VirtualHost> supports this:

  <VirtualHost 1.2.3.4 5.6.7.8>
    ...
  </VirtualHost>

If, however, you want to specific the address to which the configuration of the "server config" context, use DefaultAddress (mentioned above).

There is one last configuration directive about which an administrator should know: SocketBindTight. By default, the proftpd daemon will listen on all addresses, port 21, for the connection requests of remote clients. Sometimes, the administrator may wish to have the proftpd daemon listen only on the IP addresses for which it has been configured, and not every address. To accomplish this, simply use the SocketBindTight configuration directive:

  SocketBindTight on
This configures the daemon to "bind tightly" only to those IP addresses to which it has been configured to listen, rather than every address. By default, the proftpd daemon will listen to every address on the host machine.

Frequently Asked Questions

Question: Why do I see the following when I start proftpd?

- warning: "Virtual Server" address/port (1.2.3.4:21) already in use by "Main Server"
Answer: This happens when a <VirtualHost> section is "hidden" behind the default server in the "server config" section (i.e. the context that is outside of all <VirtualHost> and <Global> sections). It is "hidden" because both the <VirtualHost> section and the "server config" section are using the same IP address and port.

It is quite common to configure <VirtualHost> sections using DNS names, rather than IP addresses. And the "server config" section in the proftpd.conf file, by default, uses the IP address of the machine's hostname. This makes it quite easy to inadvertently have multiple sections trying to use the same IP address and port.

The quick-and-easy fix is to place the following your "server config" section in your proftpd.conf:

  Port 0
as mentioned above. You can also use the DefaultAddress directive in the "server config" section to explicitly tell the "server config" section to use a different IP address/DNS name.

Question: How can I have my "server config" section (or a <VirtualHost> section) listen for multiple IP addresses/DNS names?
Answer: In version 1.3.0rc1 and later, the <VirtualHost> configuration was enhanced so that it could handle multiple IP addresses/DNS names, e.g.:

  <VirtualHost 1.2.3.4 ftp.example.com>
    ...
  </VirtualHost>
And for the "server config" context, you would use the DefaultAddress directive, which can also handle multiple IP addresses/DNS names:
  DefaultAddress 1.2.3.4 ftp.example.com

Last Updated: $Date: 2009/01/12 23:41:26 $