RFC 4217 defines FTP over SSL/TLS:
http://www.faqs.org/rfcs/rfc4217.htmlThe
mod_tls
module for proftpd
is an implementation
of RFC 4217.
RFC 2228 defines FTP Security Extensions, of which mod_tls
is one implementation. Another
such RFC 2228 implementation is the mod_gss
module, available
from SourceForge.
Example mod_tls
configuration:
<IfModule mod_dso.c> # If mod_tls was built as a shared/DSO module, load it LoadModule mod_tls.c </IfModule> <IfModule mod_tls.c> TLSEngine on TLSLog /var/ftpd/tls.log # Support TLSv1, TLSv1.1, and TLSv1.2 TLSProtocol TLSv1 TLSv1.1 TLSv1.2 # Are clients required to use FTP over TLS when talking to this server? TLSRequired off # Server's RSA certificate TLSRSACertificateFile /etc/ftpd/server-rsa.cert.pem TLSRSACertificateKeyFile /etc/ftpd/server-rsa.key.pem # Server's EC certificate TLSECCertificateFile /etc/ftpd/server-ec.cert.pem TLSECCertificateKeyFile /etc/ftpd/server-ec.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 renegotiations. 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 none </IfModule>
Managing Certificates
Here are some widely used tools for generating and managing TLS certificates:
Debugging
There are a couple of tools available for debugging and analysing FTPS
traffic. One of the easiest to use is the s_client
application, part of OpenSSL.
The following examples assume that proftpd+mod_tls
is listening
on 127.0.0.1, port 21:
# openssl s_client -connect 127.0.0.1:21 -starttls ftp CONNECTED(00000003) depth=1 /CN=castaglia3-serverCA/C=US/emailAddress=tj@castaglia.org/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/ST=Washington verify error:num=20:unable to get local issuer certificate verify return:0 --- Certificate chain 0 s:/CN=castaglia3-server/C=US/emailAddress=tj@castaglia.org/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/ST=Washington i:/CN=castaglia3-serverCA/C=US/emailAddress=tj@castaglia.org/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/ST=Washington 1 s:/CN=castaglia3-serverCA/C=US/emailAddress=tj@castaglia.org/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/ST=Washington i:/CN=castaglia3/C=US/ST=Washington/L=Seattle/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/emailAddress=tj@castaglia.org --- Server certificate -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- subject=/CN=castaglia3-server/C=US/emailAddress=tj@castaglia.org/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/ST=Washington issuer=/CN=castaglia3-serverCA/C=US/emailAddress=tj@castaglia.org/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/ST=Washington --- Acceptable client certificate CA names /CN=castaglia3-clientCA/C=US/emailAddress=tj@castaglia.org/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/ST=Washington /CN=castaglia3/C=US/ST=Washington/L=Seattle/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/emailAddress=tj@castaglia.org /CN=castaglia3-clientCA/C=US/emailAddress=tj@castaglia.org/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/ST=Washington /CN=castaglia3/C=US/ST=Washington/L=Seattle/O=Castaglia/OU=Castaglia Research and Development/OU=TJ Saunders/emailAddress=tj@castaglia.org --- SSL handshake has read 3731 bytes and written 344 bytes --- New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA Server public key is 1024 bit Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : DHE-RSA-AES256-SHA Session-ID: D1F2E7C001BCFE57D797F34BD1518BDCC6160106D56A238CC0F957337C093435 Session-ID-ctx: Master-Key: F8EE2812270E8FCD87D1B26F20546EF9BABAE40F36BC6F8DF45B0E2F089571E731EAFAEA5E61BCA7D9D204BE06F28B21 Key-Arg : None Start Time: 1232997620 Timeout : 300 (sec) Verify return code: 20 (unable to get local issuer certificate) --- 220 ProFTPD 1.3.2rc4 Server (TJ's FTPS Server) [127.0.0.1] quit 221 Goodbye. read:errno=0Note that the "verify error" message is not of particular concern for us, since we are not using
s_client
to verify the server's
certificate in this example.
The parts of the s_client
output which are of particular interest
are the highlighted "Certificate chain" and "Acceptable client certificate CA
names" sections.
The "Certificate chain" section shows the certificate chain/trust path, from
the server's certificate up through the root CA for that certificate. Note
that this assumes the certificates in the trust path are available on the
server. By default, OpenSSL constructs this certificate chain using the
server's certificate (configured using TLSRSACertificateFile
or
TLSDSACertificateFile
) and the trusted CA certificates configured
using TLSCACertificateFile
and/or
TLSCACertificatePath
. See the TLSCertificateChainFile
FAQ for more details on how to influence
the constructed certificate chain.
The "Acceptable client certificate CA names" section contains the list of
CAs that can issue certificates that mod_tls
is willing to trust.
These CAs always come from the configured
TLSCACertificateFile
and/or TLSCACertificatePath
.
This list of acceptable client CAs is presented to the client whenever the
server is requesting the client's certificate (which is what
mod_tls
does by default). If you use:
TLSOptions NoCertRequestthen the server will not send this list of acceptable client CAs; using
s_client
in that case, you would see:
--- No client certificate CA names sent ---In case you're wondering, a list of CAs is sent to the client, rather than just a single CA, because this allows clients the ability to determine which certificate (as a client can have many) to use when talking to this particular server.
Another tool, slightly older, is ssldump
. This tool is more like ethereal
or
tcpdump
for any SSL/TLS traffic; it is deliberately modeled after
tcpdump
.
To use ssldump
for watching your FTPS traffic, you will need
the server key file (for decrypting), and possibly root privileges (for
listening on the network interface). Here is an example where
ssldump
is used to listen on the loopback interface
(lo0
), port 21:
# sudo ssldump -d -k server.pem -i lo0 port 21 New TCP connection #1: localhost(64148) <-> localhost(21) 0.0423 (0.0423) S>C --------------------------------------------------------------- 220 ProFTPD 1.3.2rc4 Server (TJ's FTPS Server) [127.0.0.1] --------------------------------------------------------------- 0.0427 (0.0004) C>S --------------------------------------------------------------- AUTH TLS --------------------------------------------------------------- 0.0430 (0.0002) S>C --------------------------------------------------------------- 234 AUTH TLS successful --------------------------------------------------------------- 1 1 0.0433 (0.0003) C>S SSLv2 compatible client hello Version 3.1 cipher suites Unknown value 0x39 Unknown value 0x38 Unknown value 0x35 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA TLS_RSA_WITH_3DES_EDE_CBC_SHA SSL2_CK_3DES Unknown value 0x33 Unknown value 0x32 Unknown value 0x2f TLS_RSA_WITH_IDEA_CBC_SHA SSL2_CK_IDEA SSL2_CK_RC2 TLS_RSA_WITH_RC4_128_SHA TLS_RSA_WITH_RC4_128_MD5 SSL2_CK_RC4 TLS_DHE_RSA_WITH_DES_CBC_SHA TLS_DHE_DSS_WITH_DES_CBC_SHA TLS_RSA_WITH_DES_CBC_SHA SSL2_CK_DES TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA TLS_RSA_EXPORT_WITH_DES40_CBC_SHA TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 SSL2_CK_RC2_EXPORT40 TLS_RSA_EXPORT_WITH_RC4_40_MD5 SSL2_CK_RC4_EXPORT40 1 2 0.0658 (0.0225) S>C Handshake ServerHello Version 3.1 session_id[32]= 09 25 df 7a a8 e8 71 a2 9f 56 a6 7b dd 95 ac 67 7d 2e 81 b2 1c ca b4 5f 1e 95 13 47 01 28 20 19 cipherSuite Unknown value 0x39 compressionMethod NULL 1 3 0.0658 (0.0000) S>C Handshake Certificate 1 4 0.0658 (0.0000) S>C Handshake ServerKeyExchange 1 5 0.0658 (0.0000) S>C Handshake CertificateRequest certificate_types rsa_fixed_dh certificate_types dss_fixed_dh certificate_types rsa_sign certificate_types dss_sign certificate_authority 30 81 b8 31 1c 30 1a 06 03 55 04 03 13 13 63 61 73 74 61 67 6c 69 61 33 2d 63 6c 69 65 6e 74 43 41 31 0b 30 09 06 03 55 04 06 13 02 55 53 31 1f 30 1d 06 09 2a 86 48 86 f7 0d 01 09 01 16 10 74 6a 40 63 61 73 74 61 67 6c 69 61 2e 6f 72 67 31 12 30 10 06 03 55 04 0a 13 09 43 61 73 74 61 67 6c 69 61 31 2b 30 29 06 03 55 04 0b 13 22 43 61 73 74 61 67 6c 69 61 20 52 65 73 65 61 72 63 68 20 61 6e 64 20 44 65 76 65 6c 6f 70 6d 65 6e 74 31 14 30 12 06 03 55 04 0b 13 0b 54 4a 20 53 61 75 6e 64 65 72 73 31 13 30 11 06 03 55 04 08 13 0a 57 61 73 68 69 6e 67 74 6f 6e certificate_authority 30 81 c1 31 13 30 11 06 03 55 04 03 13 0a 63 61 73 74 61 67 6c 69 61 33 31 0b 30 09 06 03 55 04 06 13 02 55 53 31 13 30 11 06 03 55 04 08 13 0a 57 61 73 68 69 6e 67 74 6f 6e 31 10 30 0e 06 03 55 04 07 13 07 53 65 61 74 74 6c 65 31 12 30 10 06 03 55 04 0a 13 09 43 61 73 74 61 67 6c 69 61 31 2b 30 29 06 03 55 04 0b 13 22 43 61 73 74 61 67 6c 69 61 20 52 65 73 65 61 72 63 68 20 61 6e 64 20 44 65 76 65 6c 6f 70 6d 65 6e 74 31 14 30 12 06 03 55 04 0b 13 0b 54 4a 20 53 61 75 6e 64 65 72 73 31 1f 30 1d 06 09 2a 86 48 86 f7 0d 01 09 01 16 10 74 6a 40 63 61 73 74 61 67 6c 69 61 2e 6f 72 67 certificate_authority 30 81 b8 31 1c 30 1a 06 03 55 04 03 13 13 63 61 73 74 61 67 6c 69 61 33 2d 63 6c 69 65 6e 74 43 41 31 0b 30 09 06 03 55 04 06 13 02 55 53 31 1f 30 1d 06 09 2a 86 48 86 f7 0d 01 09 01 16 10 74 6a 40 63 61 73 74 61 67 6c 69 61 2e 6f 72 67 31 12 30 10 06 03 55 04 0a 13 09 43 61 73 74 61 67 6c 69 61 31 2b 30 29 06 03 55 04 0b 13 22 43 61 73 74 61 67 6c 69 61 20 52 65 73 65 61 72 63 68 20 61 6e 64 20 44 65 76 65 6c 6f 70 6d 65 6e 74 31 14 30 12 06 03 55 04 0b 13 0b 54 4a 20 53 61 75 6e 64 65 72 73 31 13 30 11 06 03 55 04 08 13 0a 57 61 73 68 69 6e 67 74 6f 6e certificate_authority 30 81 c1 31 13 30 11 06 03 55 04 03 13 0a 63 61 73 74 61 67 6c 69 61 33 31 0b 30 09 06 03 55 04 06 13 02 55 53 31 13 30 11 06 03 55 04 08 13 0a 57 61 73 68 69 6e 67 74 6f 6e 31 10 30 0e 06 03 55 04 07 13 07 53 65 61 74 74 6c 65 31 12 30 10 06 03 55 04 0a 13 09 43 61 73 74 61 67 6c 69 61 31 2b 30 29 06 03 55 04 0b 13 22 43 61 73 74 61 67 6c 69 61 20 52 65 73 65 61 72 63 68 20 61 6e 64 20 44 65 76 65 6c 6f 70 6d 65 6e 74 31 14 30 12 06 03 55 04 0b 13 0b 54 4a 20 53 61 75 6e 64 65 72 73 31 1f 30 1d 06 09 2a 86 48 86 f7 0d 01 09 01 16 10 74 6a 40 63 61 73 74 61 67 6c 69 61 2e 6f 72 67 ServerHelloDone 1 6 0.1005 (0.0346) C>S Handshake Certificate 1 7 0.1005 (0.0000) C>S Handshake ClientKeyExchange 1 8 0.1005 (0.0000) C>S ChangeCipherSpec 1 9 0.1005 (0.0000) C>S Handshake 1 10 0.1164 (0.0159) S>C ChangeCipherSpec 1 11 0.1164 (0.0000) S>C Handshake 1 12 1.7856 (1.6692) C>S application_data 1 13 1.7856 (0.0000) C>S application_data 1 14 1.7861 (0.0004) S>C application_data 1 1.7866 (0.0004) S>C TCP FIN 1 15 1.7868 (0.0002) C>S Alert
As you can see, the level of granularity used by ssldump
is on
the level of each SSL/TLS packet; while useful in some cases, I suspect that
using openssl s_client
will provide most of the information you
will want in figuring out your certificate and verification issues.
TLS Client Auth/Mutual Auth
Like most web servers, when mod_tls
is used, it does not
require that the connecting client present a certificate for verification
by default. That is, mod_tls
does not require "client auth"
or "mutual auth" by default. To require that clients present a valid
certificate, you would use the TLSVerifyClient
directive like so:
<IfModule mod_tls.c> TLSEngine on ... # Verify clients that want to use FTP over TLS TLSVerifyClient on </IfModule>
With this directive enabled in your configuration, if a client connects and performs the SSL/TLS handshake but does not present a valid certificate, then the TLSLog would contain error messages like this:
mod_tls/2.4.3[12065]: TLS/TLS-C requested, starting TLS handshake mod_tls/2.4.3[12065]: unable to accept TLS connection: protocol error: (1) error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate mod_tls/2.4.3[12065]: TLS/TLS-C negotiation failed on control channelThe client failed to provide a valid certificate, and so the connection was rejected.
425 Unable to build data connection: Operation not permitted.Why?
mod_tls
requires
that the same SSL session be used data transfers (see
TLSOptions
),
which includes uploads, downloads, and directory listings. If your
data transfers are failing, you might look in your
TLSLog
, and see
a log message like this:
client did not reuse SSL session, rejecting data connection (see the NoSessionReuseRequired TLSOptions parameter)The workaround, then, is to add the TLSOption mentioned in the log message to your configuration, i.e.:
# Relax the requirement that the SSL session be reused for data transfers TLSOptions NoSessionReuseRequiredThen restart
proftpd
, and your data transfers should work.
http://www.modssl.org/docs/2.7/ssl_faq.html
TLSRequired onthen you are configuring
mod_tls
to require SSL/TLS
protection for both control connections (e.g. protecting the username
and password used to log in) and data connections. If you have:
TLSRequired offthen it is up to the FTPS client whether both control and data connections will be protected via SSL/TLS. Other
TLSRequired
settings
can be used to specify specific combinations: data connections only,
control connections only, authentication plus data data connections only,
etc. The TLSRequired
documentation has the
details.
http://www.ford-hutchinson.com/~fh-1-pfh/ftps-ext.htmlincluding 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 older versions of FTPS
clients, most notably SmartFTP and CuteFTP Pro. These clients had the following
behavior: RFC 2246 states
that, if a client receives a CertificateRequest
, and the client
has no certificate, it "should send a certificate message containing no
certificates" (Section 7.4.6). Instead, after negotiating to use TLS version 1,
these clients choke and break the connection (which is actually SSL version 2
behavior). The NoCertRequest
TLSOption
is designed for use for such clients.
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.
All that said, in ProFTPD 1.3.3rc2, the mod_tls
module was
enhanced to support implicit FTPS via the UseImplicitSSL
TLSOption
.
TLSProtocol TLSv1.2Note that if you have multiple
<VirtualHost>
sections in
your proftpd.conf
and you want this to apply to all of
those vhosts, then you should place the TLSProtocol
directive
in a <Global>
section, e.g.:
<Global> # Only allow TLSv1.2 for any of our FTPS vhosts TLSProtocol TLSv1.2 </Global>
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.
<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: When I use the following in my
proftpd.conf
:
TLSRequired on # or "TLSRequired auth", or "TLSRequired auth+data" TLSOptions AllowPerUserI get the following error when I try to start
proftpd
:
cannot enforce both 'TLSRequired auth' and 'TLSOptions AllowPerUser' at the same timeAnswer: The reason this error occurs is because you have a configuration which is impossible to support. The
TLSRequired
setting (e.g. "on", "auth", or "auth+data")
requires that SSL/TLS be in use during authentication. But in order to
support the TLSOption AllowPerUser
setting, the
mod_tls
cannot require that SSL/TLS be in use during
authentication, since it does not know the user until after
authentication has completed. The requested configuration cannot be supported,
and thus the server will refuse to start.
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 (FXP) 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 as of proftpd-1.3.5rc4
, encrypted site-to-site
(FXP) transfers are supported via the SSCN
FTP command. The
TLSVerifyServer
directive is also needed for secure FXP transfers.
TLSRequired auth+dataSee the
TLSRequired
description for more details.
TLSRequired onHowever, 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.
The following may also appear in the TLS
for any data
transfers (which include directory listings):
client did not reuse SSL session, rejecting data connection (see the NoSessionReuseRequired TLSOptions parameterThis message appears because an additional security restriction that was added in ProFTPD 1.3.3rc1. The
TLSOptions
documentation for this "NoSessionReuseRequired" option
describes the situation in more detail.
You may also see the following appear in the TLSLog
on occasion:
PROT: unwilling to accept security parameter (C), decliningThe
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.
In order to accept a "PROT C" FTP command, your mod_tls
configuration would need to use a TLSRequired
value other than
required, e.g. something like:
# We only require SSL/TLS protection during authentication TLSRequired auth # We will accept SSL/TLS protection for the control channel if the # client wants to use it, but NOT for data transfers TLSRequired !data
Question: Using FTPS, after uploading a very large file, my next directory listing fails:
425 Unable to build data connection: Operation not permittedThe
TLSLog
contains:
client did not reuse SSL session, rejecting data connection (see the NoSessionReuseRequired TLSOptions parameter)but I do not want to use that option, and would like to rely on the additional security protection provided by requring SSL session reuse. And my FTPS client is correctly reusing SSL session IDs (as earlier data transfers were working properly). So why is my data transfer failing after the upload of a very large file?
mod_tls
), cache timeouts, and
session renegotiations.
By default, mod_tls
uses OpenSSL's "internal" session cache,
which is an in-memory caching of SSL session IDs. And by default, OpenSSL's
internal session cache has a cache timeout of 5 minutes; after that amount
of time in the internal session cache, a cached SSL session ID is considered
stale and is available for reuse.
This means that 5 minutes or more into an FTPS session, even if your FTPS
client reused an SSL session ID, the OpenSSL internal session cache will
time out that SSL session ID. The next time your FTPS client goes to reuse
that session ID for a data transfer, mod_tls
won't find it in
the OpenSSL internal session cache, and will think that your FTPS client is
not reusing the SSL session ID as is required, and fail the transfer.
Fixing this situation requires two parts: a) the ability to change the cache timeout used for the OpenSSL internal session cache, and b) renegotiating the SSL session ID with the FTPS client periodically, to keep the SSL session ID up-to-date in the session cache.
The first part, configuring the session cache timeout for the OpenSSL internal
session cache, is only possible in ProFTPD 1.3.4rc2 and later (see
Bug#3580). The
TLSSessionCache
directive was modified to allow a configuration such as:
TLSSessionCache internal: 1800(Unfortunately, the ':' after "internal" is necessary.) This configures
mod_tls
such that the OpenSSL internal session cache uses
a cache timeout of 1800 seconds (30 minutes), rather than the default of 300
seconds (5 minutes).
No matter how long you configure the cache timeout, eventually you will have
a session which lasts longer than that timeout. Which brings us to the second
part of the solution: renegotiating a new SSL session ID periodically, which
keeps it fresh in the session cache. The
TLSRenegotiate
directive is needed for this. For example, the following configuration
should address the issue of failed data transfers after very large uploads:
TLSRenegotiate ctrl 1500 timeout 300 TLSSessionCache internal: 1800This tells
mod_tls
to request a renegotiation of the SSL session
on the control channel every 1500 seconds (25 minutes), and to allow
300 seconds (5 minutes) for the client to perform the renegotiation. It also
tells mod_tls
to cache the SSL session data for 1800 seconds
(30 minutes), i.e. longer than the renegotiation time of 1500 seconds.
This way, as long as your client supports renegotiations and is updating the SSL session ID properly for data transfers, when a data transfer is requested, the SSL session ID presented by the client should always be fresh and in the session cache.
2016-01-15 07:32:37,275 mod_tls/2.7[5072]: TLS/TLS-C requested, starting TLS handshake 2016-01-15 07:32:37,303 mod_tls/2.7[5072]: unable to accept TLS connection: protocol error: (1) error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol 2016-01-15 07:32:37,303 mod_tls/2.7[5072]: TLS/TLS-C negotiation failed on control channelWhy does this happen?
mod_tls
is
configured (e.g. using TLSProtocol
) to support specific
TLS versions, and the FTPS client is trying to use one of the unsupported
protocol versions. For example, if you use:
# Only support TLSv1.1 and TLSv1.2 TLSProtocol TLSv1.1 TLSv1.2And then connect with an FTPS client using TLSv1, like so:
$ openssl s_client -connect address:port -starttls ftp -tls1Then you would see the above error. Note that this same protocol mismatch issue can also manifest as the error message "wrong version number".
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 1Answer: Add
-ldl
to your configure command, for example:
make clean ./configure LDFLAGS=-ldl ... makeThis 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 channelAnswer: 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.
mod_tls/2.4.3[28786]: error: unable to verify certificate at depth 1 mod_tls/2.4.3[28786]: client certificate failed verification: certificate chain too longWhat causes this?
mod_tls
configured with a very small TLSVerifyDepth
value, e.g.:
TLSVerifyDepth 0Using small values, especially a value of 0, is a bad idea; most client certificate chains have a "depth" (or length) of 2-3, or perhaps longer. The default
TLSVerifyDepth
value of 10 is sufficient for
most cases; it allows for long certificate chains, but still guards against
chains which might be absurdly long.
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 renegotiations are forced.
Some FTPS clients, however, do not support server-initiated SSL/TLS renegotiations. 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
mod_tls/2.1.2[9628]: TLS/TLS-C requested, starting TLS handshake mod_tls/2.1.2[9628]: unable to accept TLS connection: received EOF that violates protocol mod_tls/2.1.2[9628]: TLS/TLS-C negotiation failed on control channelIs this a bug in
mod_tls
, in the client, or something else?mod_tls
,
in the FTPS client, or it could be a transient network issue.
The usual culprit for the above error is an FTP-aware network device such as a NAT, router, or firewall between the client and the server. Such network devices "peek" into the FTP control connection in order to dynamically open the necessary ports for data transfers. However, this "peeking" fails once an SSL/TLS handshake starts on that same control connection, and when that happens, these network devices usually terminate the control connection, resulting in the EOF ("end of file") error reported.
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.
./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=gccThe
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 installyou 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/fipsnotes.html
Question: Why do I see the following in my logs when
I start proftpd
using mod_tls
?
- mod_tls/2.2: compiled using OpenSSL version 'OpenSSL 0.9.7i 14 Oct 2005' headers, but linked to OpenSSL version 'OpenSSL 0.9.7l 28 Sep 2006' libraryWhat does this mean?
Some systems are badly maintained by their admins (and/or by the packages
installed on the systems), such that the OpenSSL headers can become quite badly
out of sync with the OpenSSL libraries. If this discrepancy becomes bad
enough, you can see strange behavior from OpenSSL, ranging from random behavior
to segfaults. So mod_tls
tries to let the admin know about the
system's mismatched OpenSSL header/library versions.
Usually a minor OpenSSL version difference like the example above is OK, but it really depends on exactly what changed in OpenSSL, and how.
If you see the above message, it is not a requirement that you recompile
proftpd
against the OpenSSL headers of the same version as the
OpenSSL libraries. However, the version discrepancy is a possible
source of trouble.
This header/library version check was added recently, hence why older
proftpd
releases do not log the warning.
Question: When should the TLSCertificateChainFile
directive be used?
Answer: Short answer: only in very specific
arrangements of CA hierarchies. Most of the time, you probably do not need
it.
The long explanation requires an illustration. Let's say we have a CA hierarchy that looks something like this:
MyRootCA TheirRootCA | | MyServerCA TheirClientCA | | +------+------+ +------+------+ | | | | | | certA certB certC cert1 cert2 cert3
Another way of asking the question thus is: "How to I send MyServerCA and MyRootCA to the client without having them in my trusted CA locations"?
We might configure mod_tls
to have "certA" as the server's
certificate, via TLSRSACertificateFile
. The "certA" certificate
is issued by MyServerCA. And let's assume that we do not want to verify
any client certificates issued by MyServerCA.
We do want to be able to verify client certs issued by a different CA,
say, TheirClientCA. We configure TheirClientCA in mod_tls
using
TLSCACertificateFile
or TLSCACertificatePath
.
The client connects to mod_tls
, and starts the SSL/TLS handshake.
mod_tls
sends its "certA" certificate, along with any certs that
may be needed on the client for verifying the server's certificate. (This
is what appears in the "Certificate chain" output from s_client
;
see SSL/TLS debugging above.) Perhaps the client
does not have MyServerCA present in the client certificate store. So we need
to tell mod_tls
to send the MyServerCA and MyRootCA certs, along
with "certA". We could place the MyServerCA and MyRootCA certs in
TLSCACertificatePath
, but then any client certs issued by
MyServerCA would be trusted as well (and that's not what we want for this
example).
The solution here is to use TLSCertificateChainFile
to supply the
MyServerCA and MyRootCA certs, as part of the server cert chain. The
configured TLSCertificateChainFile
would contain the PEM-formatted
MyServerCA and MyRootCA public certs. And although the
TLSCertificateChainFile
states that the certs contained in the
file should be in certificate chain order, this is not strictly necessary; the
OpenSSL library will adjust the ordering as appropriate.
Question: I am having trouble connecting to my
SSL/TLS-enabled proftpd
; my FTPS client shows this error:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failureWhat is wrong?
TLSLog
to see what errors, if any, are logged by the
mod_tls
module. For example, you might see:
Dec 14 10:47:58 mod_tls/2.4.1[13393]: unable to accept TLS connection: protocol error: (1) error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipherThe most common causes of these problems are: a) overly restrictive
TLSCipherSuite
configuration, or b) missing server
certificate (i.e. TLSRSACertificateFile
,
TLSDSACertificateFile
, or TLSPKCS12File
). The
file configured for the server certificate might also be badly formatted,
which would result in the same error.
Question: Is there a way to require TLS (FTPS) for
remote clients only, and allow simple FTP (without TLS) for local
clients (i.e. for clients in networks which we will be able to define
as "local")?
Answer: Yes.
To do this, you would use a combination of
<Class>
sections and
mod_ifsession's
<IfClass>
, e.g.:
<Class local> From ... </Class> <IfModule mod_tls.c> # Normal mod_tls configuration here <IfClass local> # Don't require FTPS from local clients TLSRequired off </IfClass> <IfClass !local> # Require FTPS from remote/non-local clients TLSRequired on </IfClass> </IfModule>
Question: I have configured my proftpd
server for FTPS. When I use FileZilla to try to connect to it, though, I
see one of these errors in the FileZilla logs:
GnuTLS error -8: A record packet with illegal version was received GnuTLS error -9: A TLS packet with unexpected length was receivedIs there a ProFTPD directive to fix this error?
SQLLogFile
if
you are using the mod_sql
module, etc.
Question: When I use FileZilla to connect to my
proftpd
server, it fails, and I see this error:
gnutls_handshake: An unexpected TLS packet was received.How to can I connect to my FTPS server using FileZilla?
proftpd
. Why? Using "ftpes://..." tells FileZilla
to use explicit TLS, which is what proftpd
implements,
as that is the RFC-mandated behavior. See:
https://wiki.filezilla-project.org/SSL/TLS#Explicit_vs_Implicit_FTPS
$ lftp ftps://pc -u myuserWhat is going wrong?
lftp
that
using SSL/TLS is allowed when talking to an FTP server:
$ lftp pc lftp> set ftp:ssl-allow yes lftp> user user ...or put the above setting in your
~/.lftprc
file.
Note that if you always want lftp
to use SSL/TLS for FTP
sessions, then you would use this setting:
set ftp:ssl-force yes
Question: What is the difference between the
mod_tls_shmcache
and mod_tls_memcache
modules?
Answer: Both of these modules are used to support
session caching/resumption in mod_tls
. The difference between
these modules is in where the SSL session data is cached/stored.
The mod_tls_shmcache
module stores SSL session data in a SysV shared memory ("shm") segment,
which can be accessed by the different proftpd processes on the same
machine. The mod_tls_memcache
module stores SSL session data in a memcached server (configured
using the mod_memcache
module); this allows different proftpd processes on different machines
to access/reuse the cached session data; this can be quite useful when operating
a pool of proftpd
servers e.g. behind a load balancer.
Jul 23 01:15:46 mod_tls/2.4.3[10481]: using default OpenSSL verification locations (see $SSL_CERT_DIR environment variable) Jul 23 01:15:46 mod_tls/2.4.3[10481]: error checking key from TLSRSACertificateKeyFile '/usr/local/etc/proftpd/ssl/proftpd.key.pem': (1) error:140A80B1:SSL routines:SSL_CTX_check_private_key:no certificate assigned Jul 23 01:15:46 mod_tls/2.4.3[10481]: error initializing OpenSSL context for this session Jul 23 01:15:46 mod_tls/2.4.3[10481]: TLS/TLS-C requested, starting TLS handshake Jul 23 01:15:47 mod_tls/2.4.3[10481]: unable to accept TLS connection: protocol error: (1) error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher Jul 23 01:15:47 mod_tls/2.4.3[10481]: TLS/TLS-C negotiation failed on control channelWhat does this mean?
mod_tls
like so:
#TLSRSACertificateFile /usr/local/etc/proftpd/ssl/server.cert.pem TLSRSACertificateKeyFile /usr/local/etc/proftpd/ssl/proftpd.key.pemthen you would see the above error.
This could also happen if, for some reason, the certificate and key in the configured files were not properly matched up.