In order to support TLS connections, RabbitMQ needs TLS and
crypto-related modules to be available in the Erlang/OTP
installation. The recommended Erlang/OTP version to use with
TLS is the most recent supported Erlang release.
Earlier versions, even if they are supported, may work for most certificates
but have known limitations (see below).

If Erlang/OTP is compiled from source, it is necessary to ensure that configure
finds OpenSSL and builds the above libraries.

When investigating TLS connectivity issues, please keep in mind that in the vast majority
of cases they are environment-specific (e.g. certificates are missing from the trusted certificate store)
and do not indicate a bug or limitation in Erlang/OTP's TLS implementation. Please go through the steps outlined
in the Troubleshooting TLS guide to gather
more information first.

TLS is a large and fairly complex topic. Before explaining how to enable TLS in RabbitMQ
it's worth briefly cover some of the concepts used in this guide. This section is intentionally brief and oversimplifies
some things. Its goal is to get the reader started with enabling TLS for RabbitMQ and applications.
A number of beginner-oriented primers on TLS are available elsewhere on the Web:
onetwo,
three,
four.

For a thorough understanding of
TLS and how to get the most out of it, we would recommend the use
of other resources, for example Network Security with
OpenSSL.

A PKI is based on the concept of digital identities that can be cryptographically (mathematically) verified. Those identities are called
certificates or more precisely, certificate/key pairs. Every TLS-enabled server usually has its own certificate/key
pair that it uses to compute a connection-specific key that will be used to encrypt traffic sent on the connection. Also, if asked, it can present its certificate
(public key) to the connection peer. clients may or may not have their own certificates. In the context of messaging and tools such as RabbitMQ it is quite common for
clients to also use certificate/key pairs so that servers can validate their identity.

Certificate/key pairs are generated by tools such as OpenSSL and signed by entities called Certificate Authorities (CA).
CAs issue certificates that users (applications or other CAs) use. When a certificate is signed by a CA, they form a chain of trust. Such chains can include
more than one CA but ultimately sign a certificate/key pair used by an applications (a leaf or end user certificate).
Chains of CA certificates are usually distributed together in a single file. Such file is called a CA bundle.

Here's an example of the most basic chain with one root CA and one leaf (server or client) certificate:

A chain with intermediate certificates might look like this:

There are organizations that sign and issue certificate/key pairs. Most of them are widely trusted CAs and charge a fee for their services.

A TLS-enabled RabbitMQ node must have a set of Certificate Authority certificates it considers to be trusted in a file (a CA bundle),
a certificate (public key) file and a private key file. The files will be read from the local filesystem. They must be readable by the effective user
of the RabbitMQ node process.

Both ends of a TLS-enabled connection can optionally verify
the other end of the connection. While doing so, they try to locate a trusted Certificate Authority in the certificate list
presented by the peer. More on this in the Peer Verification section.

This guides assumes the user has access to a Certificate Authority and two certificate/key pairs
in a number of formats for different client libraries to use.
This is best done using existing tools
but those looking to get more familiar with the topic and OpenSSL command line
tools there's a separate section.

In production environments certificates are generated by a commercial Certificate Authority
or a Certificate Authority issued by the internal security team. In those cases Certificate Authority
bundle files very likely will contain more than one certificate. This doesn't change how the bundle file
is used when configuration RabbitMQ as long as the same basic file and path requirements are met.
In other words, whether the certificates are self-signed or issued by a trusted CA, they are
configured the same way. The section on peer verification covers this in detail.

This guides assumes the user has access to a CA certifica bundle file and two certificate/key pairs.
The certificate/key pairs are used by RabbitMQ and clients that connect to the server on a
TLS-enabled port. The process of generating a Certificate Authority and two key pairs is fairly labourious
and can be error-prone. An easier way of generating all that
stuff on MacOS or Linux is with tls-gen:
you will need Python 3.5+, make and openssl
in PATH.

Note that tls-gen and the certificate/key pairs
it generates are self-signed and only suitable for development
and test environments. The vast majority of production environments
should use certificates and keys issued by a widely trusted commercial
CA.

To enable the TLS support in RabbitMQ, the node has to be configured
to know the location of the Certificate Authority
bundle (a file with one more CA certificates), the server's certificate file, and the server's
key. A TLS listener should also be enabled to know what port to listen on for TLS-enabled client connections.
More TLS-related things can be configured. Those are covered in the rest of this guide.

RabbitMQ must be able to read its configured CA certificate bundle, server certificate and private key. The files
must exist and have the appropriate permissions. When that's not the case the node will fail to start or fail to
accept TLS-enabled connections.

Note to Windows users: backslashes ("\") in the
configuration file are interpreted as escape sequences -
so for example to specify the
path c:\ca_certificate_bundle.pem for the CA certificate you
would need to use "c:\\ca_certificate_bundle.pem" or "c:/ca_certificate_bundle.pem".

As mentioned in the Certificates and Keys section, TLS has two
primary purposes: encrypting connection traffic and providing a way to verify
that the peer can be trusted (e.g. signed by a trusted Certificate Authority)
to mitigate against Man-in-the-Middle attacks,
a class of attacks where an attacker impersonates a legitimate trusted client. This section will focus
on the latter.

When a TLS connection is established client and server perform connection negotiation that takes several steps.
The first step is when the peers optionally exchange their
certificates.
Having exchanged certificates, the peers can optionally attempt
to establish a chain of trust between their CA
certificates and the certificates presented. This acts to verify that
the peer is who it claims to be (provided the private key hasn't been
stolen). The process is known as peer verification or peer validation
and follows an algorithm known as the Certification path validation algorithm.
Understanding the entire algorithm is not necessary in order to use peer verification,
so this section provides an oversimplified explanation of the key parts.

Each peer provides a chain of certificates that begins with a "leaf"
(client or server) certificate and continues with at least one Certificate Authority (CA) certificate. That
CA issued (signed) the leaf CA. If there are multiple CA certificates, they usually form a chain of signatures,
meaning that each CA certificate was signed by the next one. For example, if certificate B is signed by A and C is signed by B,
the chain is A, B, C (commas here are used for clarify). The "topmost" (first or only) CA is often referred
to as the root CA for the chain. Root CAs can be issued by well-known Certifica Authorities
(commercial vendors) or any other party (self-signed).

Here's an example of the most basic chain with one root CA and one leaf (server or client) certificate:

A chain with intermediate certificates might look like this:

During peer verification TLS connection client (or server) traverses
the chain of certificates presented by the peer
and if a trusted certificate is found, considers the peer trusted.
If no trusted and otherwise valid certificate is found, peer verification fails and client connection is closed
with an error ("alert" in OpenSSL parlance) that says "Unknown CA" or similar. The alert
will be logged by the server with a message similar to this:

The examples above demonstrate TLS alert messages logged by RabbitMQ running on Erlang/OTP 21.
Clients that perform peer verification will also raise alerts but may use different
error messages. RFC 8446 section 6.2
provides an overview of various alerts and what they mean.

Every TLS-enabled tool and TLS implementation, including Erlang/OTP and
RabbitMQ, has a way of marking a set of certificates as
trusted. On Linux and other UNIX-like systems this is
usually a directory administered by superusers. CA
certificates in that directory will be considered trusted,
and so are the certificates issued by them (such as those
presented by clients). Locations of the trusted certificate directory will varybetween distributions, operating systems and releases.

On Windows trusted certificates are managed using tools such as certmgr.

The certificates in the server's CA certificate bundle may be considered trusted.
We say "may" because it doesn't work the same way for all client libraries since this varies from TLS implementation
to implementation. Certificates in a CA certificate bundler won't be considered to be trusted in Python,
for example, unless explicitly added to the trust store.

When performing peer verification, RabbitMQ will only consider the root certificate (first certificate in the list) to be trusted.
Any intermediate certificates will be ignored. If it's desired that intermediate certificates
are also considered to be trusted they must be added to the trusted certificate store.

While it is possible to place final ("leaf") certificates
such as those used by servers and clients to the trusted certificate directory,
a much more common practice is to add CA certificates to the trusted certificate list.

The most common way of appending several certificates to one
another and use in a single Certificate Authority bundle file
is to simply concatenate them:

On the server end, peer verification is primarily controlled using two configuration
options: ssl_options.verify and ssl_options.fail_if_no_peer_cert.
Setting the ssl_options.fail_if_no_peer_cert option to false tells
the node to accept clients which don't present a certificate (for example, were not configured to use one).
When the ssl_options.verify option is set to verify_peer,
the client does send us a certificate, the node must perform peer verification.
When set to verify_none, peer verification will be disabled and certificate
exchange won't be performed.

For example, the following
config will perform peer verification and reject clients that do not provide
a certificate:

How exactly peer verification is configured in client libraries varies from library to library.
Java and .NET client sections cover peer
verification in those clients.

Peer verification is highly recommended in production environments. With careful consideration,
disabling it can make sense in certain environments (e.g. development).

Thus it is possible to create an encrypted TLS connection without having to
verify certificates. Client libraries usually support both modes of operation.

When peer verification is enabled, it is common for clients to also check whether the
the hostname of the server
they are connecting to matches one of two fields
in the server certificate: the SAN (Subject Alternative Name)
or CN (Common Name). When wildcard certificates are used,
the hostname is matched against a pattern. If there is no match, peer verification will also be
failed by the client. Hostname checks are also optional and generally orthogonal to certificate chain
verification performed by the client.

Because of this it is important to know what SAN (Subject Alternative Name) or CN (Common Name) values
were used when generating the certificate. If a certificate is generated on one host and used
on a different host then the $(hostname) value should be replaced with the correct hostname of the target server.

When using a client certificate signed by an intermediate CA, it may be necessary
to configure RabbitMQ server to use a higher verification depth.
The depth is the maximum number of non-self-issued intermediate certificates that
may follow the peer certificate in a valid certification path.
So if depth is 0 the peer (e.g. client) certificate must be signed by the trusted CA directly,
if 1 the path can be "peer, CA, trusted CA", if it is 2 "peer, CA, CA, trusted CA", and so on.
The following example demonstrates how to configure certificate validation depth for
RabbitMQ server:

A Key Manager is used by a peer (in this case, a client connection) to manage its certificates.
During TLS connection/session negotiation, the key manager will control which
certificates to send to the remote peer.

A Trust Manager is used by a peer to manage remote certificates.
During TLS connection/session negotiation, the trust manager will control which
certificates are trusted from a remote peer. Trust managers can be used
to implement any certificate chain verification logic

A Key Store is a Java encapsulation of the certificate store concept. All
certificates must either be stored into a Java-specific binary format (JKS)
or to be in the PKCS#12 format. These formats are managed using the
KeyStore class. In the below examples the JKS format is used to add the trusted (server) certificate(s)
to the store, while for the client key/certificate pair, the PKCS#12
key file generated by tls-gen will be used.

All TLS-related settings in the Java client
are configured via the ConnectionFactory.

This simple example is an echo client and server. It creates a channel
and publishes to the default direct exchange, then
fetches back what has been published and echoes it out. It uses
an exclusive, non-durable, auto-delete queue that will be deleted shortly
after the connection is closed.

For a Java client to trust a server, the server certificate must be added
to a trust store which will be used to instantiate a Trust Manager.
The JDK ships with a tool called keytool that manages certificate stores. To import a certificate to
a store use keytool -import:

The above command will import server/certificate.pem into the rabbitstore file
using the JKS format. The certificate will be referred to as server1 in the trust store.
All certificates and keys must have distinct name in their store.

keytool will confirm that the certificate is trusted and ask for a password.
The password protects the trust store from any tampering attempt.

The client certificate and key in a PKCS#12 file are then used. Note Java understands
natively the PKCS#12 format, no conversion is needed.

The below example demonstrates how the key store and the trust store are used with a
Key Manager
and Trust Manager, respectively.

This will verify
that the server certificate has been issued for the hostname the
client is connecting to. Unlike certificate chain verification, this feature
is client-specific (not usually performed by the server).

With JDK 6, it is necessary to add a dependency on
Apache Commons HttpClient for hostname verification to work, e.g. with Maven:

Just like RabbitMQ server can be configured to support only specific TLS versions,
it may be necessary to configure preferred TLS version in the Java client. This is done using
the ConnectionFactory#useSslProtocol overloads that accept a protocol version name
or a SSLContext:

For a server certificate to be understood on the .NET platform, they
can be in a number of formats including DER and PKCS#12 but
not PEM. For the DER format, .NET expects them to
be stored in files with .cer extension. tls-gen
generates both PEM and PKCS#12 files.

On the .NET platform, remote certificates are managed by putting them
into any of a number of Stores. All management of these stores is done
with the 'certmgr' tool which is available on both Microsoft's
.NET implementation and on Mono.

NB: On some flavours of Windows there are two versions of
the command: one that ships with the operating system and
provides a graphical interface only, and one that ships
with the Windows SDK and provides both a
graphical and command line interface. Either will do the
job, but the examples below are based on the latter.

For our case, because we're supplying the client certificate/key pair
in a separate PKCS#12 file, all we need to do is to import the
certificate of the root Certificate Authority into
the Root (Windows) or Trust (Mono) store.
All certificates signed by any certificate in that store are automatically trusted.

In contrast to the Java client, which is happy to use a
TLS connection without performing peer verification, the .NET client by default requires this
verification to succeed. To suppress verification, an applications can set
the System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable
and System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors
flags in SslOptions.

certmgr is a command line tool that manages certificates in a specified store, for example,
adds and deletes them. These stores can be per-user stores, or
system-wide. Only administrative users can have write access to the system-wide stores.

The following example adds a certificate to the store of user Root (also known as Trust in some .NET implementation)

# Windows
certmgr -add -all \path\to\cacert.cer -s Root

# Linux with Mono
certmgr -add -c Trust /path/to/cacert.cer

To add a certificate to the system-wide (machine) certificate store instead we
run

According to the above output there is one Self-signed X.509 v3 Certificate in the
trust store. The Unique Hash uniquely identifies this certificate in
this store. To delete this certificate, use the unique hash:

To create a TLS-enabled connection to RabbitMQ, we need to set some new
fields in the ConnectionFactory's Parameters field.
To make things
easier, there is a new Field Parameters.Ssl that acts like a namespace
for all the other fields that we need to set. The fields are:

Property

Description

Ssl.CertPath

This is the path to the client's certificate in
PKCS#12 format if your server expects client side verification. This
is optional.

Ssl.CertPassphrase

If you are using a client certificate in PKCS#12
format then it'll probably have a password, which you specify in
this field.

Ssl.Enabled

This is a boolean field that turns TLS support on or
off. It is off by default.

Ssl.ServerName

.NET expects this to match the Subject Alternative Namee (SAN) or Common Name (CN) on
the certificate that the server sends over.

This is a more or less direct port of the Java client example. It
creates a channel and publishes to
the default direct exchange, then reads back what has been
published and echoes it out. Note that we use an
exclusive, non-durable, auto-delete queue so we don't have
to worry about manually cleaning up after ourselves

TLS offers peer verification (validation), a way for client and server to
verify each other's identity based on peer's certificate information.
When peer verification is enabled, typically the hostname of the server
you're connecting to needs to match the CN (Common Name) field on
the server's certificate, otherwise the certificate will be
rejected. However, peer verification doesn't have to be limited to just CN
and hostname matching in general.

This is why the commands at the start of this guide specify
...-subj /CN=$(hostname)/... which dynamically looks up your
hostname. If you're generating certificates on one machine, and using
them on the other then be sure to swap out the $(hostname)
section, and replace it with the correct hostname for your server.

In RabbitMQ .NET client, RabbitMQ.client.SslOption.CertificatevalidationCallback
can be used to provide a RemoteCertificatevalidationCallback
delegate. The delegate will be used to verify peer (RabbitMQ node) identity using whatever logic fits
the applications.
If this is not specified, the default callback will be
used in conjunction with the AcceptablePolicyErrors
property to determine if the remote server certificate is
valid.
The System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch
flag in RabbitMQ.client.SslOption.AcceptablePolicyErrors
can be used to disable peer verification (not recommended in production environments!).

RabbitMQ.client.SslOption.CertificateSelectionCallback
can be used to provide
a LocalCertificateSelectionCallback
that will select the local certificate used for peer verification.

TLS (née SSL) has evolved over time and has multiple versions in use.
Each version builds on the shortcomings of previous versions. Most of the time
the shortcomings resulted in known attacks that affect specific
versions of TLS (and SSL). disabling older TLS versions is a way to mitigate
many of those attacks (another technique is to disable affected cipher suites).
It is common for environments with highest security requirements to only support TLSv1.2, for example.

It is possible to configure what cipher suites will be used by RabbitMQ. Note that not all
suites will be available on all systems. For example, to use Elliptic curve ciphers,
the most recent supported Erlang release is highly recommended.

To list cipher suites supported by the Erlang runtime of a running node, use rabbitmq-diagnostics cipher_suites --openssl-format:

rabbitmq-diagnostics cipher_suites --openssl-format -q

This will produce a list of cipher suites in the OpenSSL format.

Note that if --openssl-format is set to false:

rabbitmq-diagnostics cipher_suites -q --openssl-format=false

then rabbitmq-diagnostics cipher_suites will list cipher suites in the format
that's only accepted in the classic config format. The OpenSSL format is accepted
by both config formats. Note that cipher suites are not enquoted in the new style config format
but double quotes are required in the classic format.

During TLS connection negotiation, the server and the client negotiate
what cipher suite will be used. It is possible to force server's TLS
implementation to dictate its preference (cipher suite order) to avoid
malicious clients that intentionally negotiate weak cipher suites in
preparation for running an attack on them.
To do so, configure honor_cipher_order
and honor_ecc_order to true:

BEAST

Because TLS has many configurable parameters
and some of them have suboptimal defaults for historical
reasons, TLS setup evaluation is a recommended practice.
Multiple tools exist that perform various tests on TLS-enabled
server endpoints, for example, testing whether it is prone
to known attacks such as POODLE, BEAST, and others.

testssl.sh is a mature and extensive TLS endpoint testing
tool that can be used with protocol endpoints that do not serve HTTP.
Note that the tool performs many tests (for instance, on some machines it runs
over 350 cipher suite tests alone) and passing every single one may or may not
make sense for every environment. For example, many production deployments
do not use CRLs (Certificate Revocation lists); most development environments
use self-signed certificates and don't have to worry about
the most optimal set of cipher suites enabled; and so on.

Enabling TLS in the RabbitMQ Erlang client is similar to configuring other
settings related to networking. The #amqp_params_network record
provides a field, ssl_options, for all the standard Erlang TLS options.

The cacertfile option specifies the certificates of the root
Certificate Authorities that we wish to implicitly trust.

The certfile is the client's own certificate in PEM format

The keyfile is the client's private key file in PEM format

server_name_indication - set this option to the host name of the server
to which a TLS connection will be made to enable "Server Name Indication" verification
of the certificate presented by the server. This ensures that the server certificate's
CN= value will be verified during TLS connection establishment. You can
override this behavior by setting server_name_indication to a different
host name or to the special value disable to disable this
verification. Note that, by default, SNI is not enabled. This default
will change in a future RabbitMQ Erlang client release.

verify - set this option to verify_peer to enable X509
certificate chain verification. The depth option configures certificate
verification depth. Note that, by default, verify is set to
verify_none, which disables certificate chain verification. This default
will change in a future RabbitMQ Erlang client release.

SslOpts = [{cacertfile, "/path/to/testca/ca_certificate_bundle.pem"},
{certfile, "/path/to/client/certificate.pem"},
{keyfile, "/path/to/client/private_key.pem"},
%% only necessary with intermediate CAs
%% {depth, 2},
%% Note: it is recommended to set 'verify' to
%% to 'verify_peer' to ensure that X509
%% certificate chain validation is enabled
%%
%% Do not set 'verify' or set it to verify_none
%% if x509 certificate chain validation is
%% not desired
{verify, verify_peer},
%% If Server Name Indication validation is desired,
%% set the following option to the host name to which
%% the connection is made. If necessary, this option
%% may be set to another host name to match the server
%% certificate's CN= value.
%% Do not set this option or set it to the atom 'disable'
%% to disable SNI validation
{server_name_indication, "my.rmq-server.net"}],
Params = #amqp_params_network{host = "my.rmq-server.net",
port = 5671,
ssl_options = SslOpts}
{ok, Conn} = amqp_connection:start(Params),

This section of the guide explains how to generate a Certificate Authority and
use it to generate and sign two certificate/key pairs, one for the server and one for
client libraries. Note that the process can be automated using
existing tools, which is recommended. This section is intended for those who would like to improve their understanding
the process, OpenSSL command line tools and some important aspects OpenSSL configuration.

This guide assumes a UNIX-like operating system (Linux, MacOS, a BSD variant and so on)
and a recent version of OpenSSL available in

This is all that is needed to generate a test Certificate
Authority. The root certificate is in testca/ca_certificate_bundle.pem
and is also in testca/ca_certificate_bundle.cer. These two files contain the
same information, but in different formats, PEM and DER.
Most software uses the former but some tools require the latter.

Having set up our Certificate Authority, we now need to generate
private keys and certificates for the clients and the server.
RabbitMQ broker uses certificates and private keys in the PEM format.
Some client libraries use the PEM format, others will require conversion
to a different format (e.g. PKCS#12).

Java and .NET clients use a certificate format called PKCS#12 and custom certificate stores.
Certificate store contains both the client's certificate and key. The PKCS store is usually password protected, and so that
a password must be provided.

The process for creating server and client certificates is very
similar. First the server:

The two examples above generate private keys that are 2048 bits in size.
It is possible to use longer (and thus more secure but also slower to generate)
keys by providing a different value to openssl genrsa, e.g.: