## FTP and SSL/TLS

RFC 4217 defines FTP over SSL/TLS:

      http://www.faqs.org/rfcs/rfc4217.html

The `mod_tls` module for `proftpd` is an implementation of RFC 4217.

RFC 2228 defines FTP Security Extensions, of which `mod_tls` is one implementation: http://www.faqs.org/rfcs/rfc2228.html Another such RFC 2228 implementation is the `mod_gss` module, available from SourceForge.

Example `mod_tls` configuration:

      <IfModule mod_tls.c>
        TLSEngine on
        TLSLog /var/ftpd/tls.log
        TLSProtocol TLSv1

        # Are clients required to use FTP over TLS when talking to this server?
        TLSRequired off

        # Server's certificate
        TLSRSACertificateFile /etc/ftpd/server.cert.pem
        TLSRSACertificateKeyFile /etc/ftpd/server.key.pem

        # CA the server trusts
        TLSCACertificateFile /etc/ftpd/root.cert.pem

        # Authenticate clients that want to use FTP over TLS?
        TLSVerifyClient off

        # Allow SSL/TLS renegotiations when the client requests them, but
        # do not force the renegotations.  Some clients do not support
        # SSL/TLS renegotiations; when mod_tls forces a renegotiation, these
        # clients will close the data connection, or there will be a timeout
        # on an idle data connection.
        TLSRenegotiate required off

      </IfModule>

Debugging
`ssldump`

Frequently Asked Questions

Question: How do I generate the certificate files used by `mod_tls`?
Answer: The `mod_tls` module uses the same certificate files as Apache's `mod_ssl`. The `mod_ssl` documentation explains what the files are, how they are used, and how to generate your own:

      http://www.modssl.org/docs/2.7/ssl_faq.html

Question: Where can I find a list of clients that support FTPS?
Answer: This page is a good FTPS resource:

      http://www.ford-hutchinson.com/~fh-1-pfh/ftps-ext.html

including the list of FTPS clients. On a related note, there have been some reports that Debian's `ftp-ssl` client has a few bugs; using Peter Runestig's `ftp-tls` is known to work.

Note, though, that there are known issues with some FTPS clients:

      http://www.runestig.com/osp.html#NOTE1

Question: How come `mod_tls` does not support "implicit" FTPS (i.e. automatically encrypting sessions on port 990)?
Answer: The short answer is because the Draft no longer specifies support for such a mode. Here is a description of why the alternatives to the current mode (client-requested encryption using standard control channel) are "bad".

The long answer is covered in Eric Rescorla's excellent book, "SSL and TLS". There tend to be two different strategies used when adding new features to a protocol: separate ports for protocol variants, or upward negotiation. Port 443 for HTTPS is an example of the separate ports strategy. The drawback to the separate ports approach is that there is a finite number of ports available, and so this approach does not scale well. The benefit is that use of separate ports tends to require smaller changes to client and server code. Upward negotiation is more flexible, but requires that the protocol support some sort of feature negotiation or extension discovery, allowing clients and servers to easily agree to negotiate "upward" into a secure channel. The authors of the FTPS Draft felt that upward negotiation was the more appropriate of these two approaches for encrypting FTP channels.

Question: Can I require TLS on a per-user basis?
Answer: Prior to ProFTPD 1.2.10rc2, no. The IETF Draft specifying FTP over TLS requires that the TLS handshake occur before the client sends the `USER` command. This means that the server does not know the name of the user that the client will be using when the TLS session is established. It is possible that the client's certificate, if one is even presented, may contain information the server may use to map that certificate to a user, but such mapping is not currently supported by `mod_tls`. Note that this is also the reason the `TLSRequired` directive cannot appear in the `<Anonymous>` context: anonymous logins are based on the `USER` command.

However, in 1.2.10rc2, the `mod_tls` module was modified to allow such per-user TLS requirements. To do this, the `AllowPerUser` parameter of the `TLSOptions` directive is used. For example, the following example `mod_tls` configuration allows non-SSL anonymous sessions, but requires SSL/TLS for all other sessions:

      <IfModule mod_tls.c>
        TLSEngine on
        TLSRSACertificateFile ...
        TLSCACertificateFile ...
        TLSOptions AllowPerUser
        TLSRequired on

        <Anonymous ~ftp>
          User ftp
          Group ftp
          UserAlias anonymous ftp

          RequireValidShell off

          # Note how TLSRequired is set to off here in the <Anonymous> context
          TLSRequired off
        </Anonymous>
      </IfModule>

The modification also allows `mod_ifsession`-based conditions, so that one can have settings like:

      <IfGroup trusted>
        TLSRequired off
      </IfGroup>

However, there is a risk involved in using the `AllowPerUser` option: it causes `mod_tls` not to enforce `TLSRequired` until after the potentially sensitive USER and PASS commands have been sent by the client. This allows clients, even when `TLSRequired on` or `TLSRequired ctrl` are in effect, to send the USER and PASS commands unencrypted. Depending on your site's security needs, the ability to require SSL/TLS on a per-user basis may or may not be worth the ability to require SSL/TLS for the USER and PASS commands.

Question: Why does `mod_tls` break FXP transfers?
Answer: The Draft specifying FTP over SSL explicitly omits site-to-site transfers. A TLS session is established between the client and the server on the control channel and, to save on the expensive overhead of TLS handshake, that session is reused for encrypting traffic on the data channel. In a site-to-site transfer, the client opens two control channels, one with each server, and then arranges for those servers to open a data channel between themselves. However, since the servers have not established a TLS session between themselves, that opening of the data channel fails.

Note that the above happens only if the server requires that TLS be used on data connections (e.g. `TLSRequired` is either on or data), of if the client tells the server that the client will be using TLS on the data connections (e.g. when it sends the `AUTH` command with an argument of `TLS-P`). Without these conditions, site-to-site transfers can occur normally, albeit unencrypted. Encrypted site-to-site transfers are not supported.

Question: How come `mod_tls` does not support SSLv2?
Answer: Various defects have been found in the SSLv2 protocol. Some legacy sites need to support SSLv2 for their HTTP traffic, in spite of its flaws. Use of FTP over TLS is fairly new, however, and there is not much "legacy" in that regard; it was felt that, as `mod_tls` aims to provide strong cryptographic security, supporting a known bad protocol is a Bad Idea.

Question: Using `mod_tls`, FTP sessions through my firewall now no longer work. What's going on?
Answer: The short answer is that FTPS and firewalls (and devices performing NAT) do not interact well. The control connection happens on a well-known port, and has no issues; it is the data connection that poses problems for FTP-aware firewalls. In a non-FTPS session, the firewall can inspect the FTP server's responses on the control connection to a client's `PASV` or `PORT` command, and thus know which on which ports/addresses the data connection will be established. In an FTPS session, though, those control connection messages are encrypted (that is the point of using FTPS, right?), and so the FTP-aware firewall cannot peek. Hence, it cannot know which on which ports the data connection will be established. For firewalls that are configured to always allow a certain range of ports (such as might be configured using the `PassivePorts` directive), FTPS should function without issue.

Unfortunately, this is a rather intractable--and known--issue. Earlier versions of the Draft defining FTPS used to allow something known as "implicit" FTPS, by which a client could contact a well-known port (akin to port 443 for HTTPS; FTPS used port 990) and the server, simply because the client contacted that certain port, would automatically encrypt the session. This approach has several drawbacks (the reason why it was removed from later versions of the Draft), but it did allow for simple TCP proxying.

To attempt to deal with the above issue, the RFC for FTP over SSL/TLS suggests using the `CCC` FTP command (Clear Command Channel). The `CCC` command makes an encrypted control channel revert back to an unencrypted channel. This helps to solve data connection problems in situations where network equipment (such as firewalls, routers, NAT) peek at the control channel in order to open ports. By sending the `CCC` command and unecrypting the control channel, the network equipment can once again peek at the commands (i.e. `PORT` and `EPRT`) in the control channel. Since the CCC command must come after the client has logged in, the `USER` and `PASS` commands on the control channel will still be protected by SSL/TLS.

Note that in order to configure the `mod_tls` module to allow use of the `CCC` command by clients, the following must appear in your `proftpd.conf`:

      TLSRequired auth+data

See the `TLSRequired` description for more details.

Question: Sometimes my encrypted transfers are slow. Is there a way to speed them up?
Answer: There have been reports that increasing the tunable buffer size (using the `--enable-buffer-size` option of the `configure` script) to 8192 increases transfer speeds, most notably on very high speed networks. Increasing the buffer size does not appear to affect normal FTP transfers (in fact, it may benefit them as well, depending on the client).

Question: I can login using FTPS, but I cannot see any directories. Why not?
Answer: You have most likely configured `mod_tls` to require SSL/TLS protection for data transfers as well as control commands, by using:

      TLSRequired on

However, if your FTPS client does not expect to handle encrypted data transfers (and directory listings count as data transfers, as they are sent over a data channel), you may see your client appear to hang, waiting for data it can read. Make sure your client is prepared to handle the security requirements you have configured on the server.

You may also see the following appear in the `TLSLog` on occasion:

      PROT: unwilling to accept security parameter (C), declining

The `PROT` FTP command is used to set the protection level to be used for data transfers. Some clients send a `PROT` command with a security parameter of `C`, meaning "Clear", which effectively tells the server not to protect data transfers. The `mod_tls` module will refuse the `C` security parameter if, like above, there is "TLSRequired on" in your `proftpd.conf`. This case also indicates a disagreement between the client's security expectations and the security policy you have configured on the server.

Question: Why would I see the following errors while attempting to build `proftpd` with `mod_tls`?

      /usr/local/ssl/lib/libcrypto.a(dso_dlfcn.o)(.text+0x35): In function `dlfcn_load': : undefined reference to `dlopen'
      /usr/local/ssl/lib/libcrypto.a(dso_dlfcn.o)(.text+0x95): In function `dlfcn_load': : undefined reference to `dlclose'
      /usr/local/ssl/lib/libcrypto.a(dso_dlfcn.o)(.text+0xbc): In function `dlfcn_load': : undefined reference to `dlerror'
      /usr/local/ssl/lib/libcrypto.a(dso_dlfcn.o)(.text+0x147): In function `dlfcn_bind_var': : undefined reference to `dlsym'
      /usr/local/ssl/lib/libcrypto.a(dso_dlfcn.o)(.text+0x172): In function `dlfcn_bind_var': : undefined reference to `dlerror'
      /usr/local/ssl/lib/libcrypto.a(dso_dlfcn.o)(.text+0x237): In function `dlfcn_bind_func': : undefined reference to `dlsym'
      /usr/local/ssl/lib/libcrypto.a(dso_dlfcn.o)(.text+0x262): In function `dlfcn_bind_func': : undefined reference to `dlerror'
      /usr/local/ssl/lib/libcrypto.a(dso_dlfcn.o)(.text+0x50b): In function `dlfcn_unload': : undefined reference to `dlclose'
      collect2: ld returned 1 exit status
      make: *** [proftpd] Error 1

Answer: Add `-ldl` to your configure command, for example:

      make clean
      ./configure LDFLAGS=-ldl ...
      make

This tells the `proftpd` build system to add `libdl`, an OS-specific library for handling dynamically loaded code, to the list of libraries used when linking `proftpd`. On some systems, the functions in the `libdl` library are part of `libc`, and are not in a separate library.

I suspect that the reason this build option may be necessary is that OpenSSL 0.9.8 contained changes regarding how OpenSSL loads "engines", software modules that talk to hardware devices that can do specialized cryptographic operations. These changes involve being able to dynamically load the "engine" software modules.

Question: Why would I see a "no shared cipher" error in the TLSLog when attempting to connect with my FTPS client?

      Jan 10 17:15:18 mod_tls/2.1.1[2212]: TLS/TLS-C requested, starting TLS handshake
      Jan 10 17:15:18 mod_tls/2.1.1[2212]: unable to accept TLS connection:
        (1) error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher
      Jan 10 17:15:18 mod_tls/2.1.1[2212]: TLS/TLS-C negotiation failed on control channel

Answer: There are two reasons this might happen.

The first is that there is indeed no ciphersuite in common between `mod_tls` and your FTPS client. The SSL/TLS ciphersuites used by `mod_tls` are configured using the `TLSCipherSuite` directive. If you have a complex or restrictive `TLSCipherSuite` configured, that could be the culprit. Try relaxing (or removing outright) your `TLSCipherSuite`, or try to configure your FTPS client to use the same SSL/TLS ciphersuites.

Another possibility is a misconfiguration. If your `TLSCACertificateFile` and `TLSRSACertificateFile` directives are in the "server config" context of the `proftpd.conf` file, and you have `>VirtualHost<` sections in your `proftpd.conf`, then you might see the "no shared cipher" error. The easiest thing is to move those `TLSCACertificateFile` and `TLSRSACertificateFile` directives into a `>Global<` section in your `proftpd.conf`, so that they apply to all vhosts configured. The virtual hosting howto describes this in more detail.

Question: My FTPS client sometimes times out after uploading/downloading more than 1 GB of data. When I turn off SSL/TLS, the upload/download works. Why?
Answer: The culprit behind this is most likely SSL/TLS renegotiations. By default, `mod_tls` uses SSL/TLS renegotiations to periodically update the session key which protects the data being transferred; see the `TLSRenegotiate` documentation for more details, particularly the time-based and bytes-based limits at which renegotations are forced.

Some FTPS clients, however, do not support server-initiated SSL/TLS renegotations. When the server does try to force a renegotiation, the client fails that new handshake, cannot upload/download any more data over the protected channel, and the transfer will eventually time out. Alternatively, the transfer could terminate strangely in the middle of the upload/download. Note, however, that not all transfer issues will be caused by SSL/TLS renegotiations. Bugs in firewalls and routers can also cause these symptoms.

Should you suspect that you are having issues with your FTPS client because of SSL/TLS renegotiations, you can configure `mod_tls` to accept renegotiations if the client requests one, but not to otherwise force them:

      TLSRenegotiate required off

Question: My FTPS client has trouble connecting to `proftpd` using SSL/TLS, with the following error appearing in the `TLSLog`:

      Sep 17 11:03:46 mod_tls/2.1.2[9628]: TLS/TLS-C requested, starting TLS handshake
      Sep 17 11:03:46 mod_tls/2.1.2[9628]: unable to accept TLS connection: received EOF that violates protocol
      Sep 17 11:03:46 mod_tls/2.1.2[9628]: TLS/TLS-C negotiation failed on control channel

Is this a bug in `mod_tls`, in the client, or something else?
Answer: There might be several different causes for this error. It could be a bug in the OpenSSL library, in `mod_tls`, in the FTPS client, or it could be a transient network issue.

Now, one possible thing to try is to use the following in your `proftpd.conf` file:

      TLSOptions NoCertRequest

This option tells the OpenSSL library to not include a message requesting the client's certificate in the SSL/TLS handshake messages. Some older SSL implementations seem to have trouble with this certificate request message, and react badly. This includes some Windows FTP clients, as well as some FTP clients for the Mac.

One user tried using both the Transmit and the Fetch applications for the Mac; both state that they can handle FTP over SSL/TLS. Using both of these applications, the user saw the above error. The user, when using Transmit, saw the following error message appear from the client:

      Server said:
      AUTH TLS successful
      error:00000000:lib(0):func(0):reason(0)

And when using Fetch, the error message displayed by that client was:

      SSL Error -9844
      Server responded: "AUTH TLS successful"

In both causes, using "TLSOptions NoCertRequest" appeared to make those clients happy.

Question: When `proftpd` starts up, I am prompted to enter the passphrases for my certificates. How can I get the daemon to start without having to enter passphrases?
Answer: You can either remove the passphrase from the certificate key file (as mentioned in the Apache `mod_ssl` FAQ), or you can use the `TLSPassPhraseProvider` directive to configure a program will which provide the passphrases to `proftpd` automatically.

Question: How can I configure `mod_tls` to use OpenSSL in FIPS mode?
Answer: Using OpenSSL in FIPS mode requires quite a few steps. First, you would configure `proftpd` to use the `mod_tls` module as normal, assuming your OpenSSL installation has been compiled with FIPS support:

      ./configure --with-modules=mod_tls ...

Compiling `proftpd` requires the following, for FIPS support to work properly:

      make CC=/path/to/openssl/bin/fipsld FIPSLD_CC=gcc

The `FIPSLD_CC` variable should point to your normal C compiler, e.g. `gcc`. The use of this `fipsld` program is mandatory. The FIPS standard requires that the linking process happen a very specific way, involving verification of calculated and expected checksums of compiled code, etc. The OpenSSL packages with FIPS support supply this `fipsld` program which will link the compiled code according to the FIPS specifications. If you do not use `fipsld`, then attempts to use OpenSSL in FIPS mode will fail. For example, you would see the following if starting a `proftpd` daemon which has not been linked using `fipsld` while requesting use of FIPS:

      - mod_tls/2.1.2: unable to use FIPS mode: (unknown)
      - Fatal: unable to load module 'mod_tls.c': Operation not permitted

Now, assuming you have compiled and installed your `proftpd` properly, e.g.:

      make CC=/path/to/openssl/bin/fipsld FIPSLD_CC=gcc
      make CC=/path/to/openssl/bin/fipsld FIPSLD_CC=gcc install

you will now be ready to start `proftpd`.

In order for FIPS mode to be effective, OpenSSL must be told to run in FIPS mode from the very beginning. The `mod_tls` module initializes the OpenSSL library when the `mod_tls` module is loaded, before the `proftpd.conf` file is parsed. Thus the requesting of FIPS mode cannot be done via a setting in `proftpd.conf`. (Annoying, I know.)

Instead, you must use the -D command-line parameter when starting `proftpd` (see the docs for the `<IfDefine>` and `Define` directives) to define a specific variable, which the `mod_tls` module will look for. Specifically, you will need to start `proftpd` like thus:

      /path/to/proftpd -DTLS_USE_FIPS ...

This will define the `TLS_USE_FIPS` variable; this tells `mod_tls` to initialize OpenSSL using FIPS mode. When this works, you will see the following when `proftpd` starts up:

      - mod_tls/2.1.2: FIPS mode enabled

For additional reading on OpenSSL and FIPS, see:

      http://www.openssl.org/docs/fips/SecurityPolicy-1.1.1.pdf
      http://www.openssl.org/docs/fips/UserGuide-1.1.1.pdf

Last Updated: $Date: 2008/03/08 05:12:38 $