Skip to content Skip to sidebar Skip to footer

Git Clone Error Reading X.509 Key or Certificate File: Error While Reading File.

TLS Support

Overview

RabbitMQ has inbuilt support for TLS. This includes client connections and pop plugins, where applicable, such as Federation links. It is likewise possible to utilise TLS to encrypt inter-node connections in clusters.

This guide covers various topics related to TLS in RabbitMQ, with a focus on client connections:

  • Two ways of using TLS for client connections: directly or via a TLS terminating proxy
  • Erlang/OTP requirements for TLS back up
  • Enabling TLS in RabbitMQ
  • How to generate self-signed certificates for development and QA environments with tls-gen or manually
  • TLS configuration in Java and .Internet clients
  • Peer (document chain) verification of client connections or mutual ("mTLS")
  • Public cardinal usage extensions relevant to RabbitMQ
  • How to control what TLS version and naught suite are enabled
  • TLSv1.three back up
  • Tools that can exist used to evaluate a TLS setup
  • Known attacks on TLS and their mitigation
  • How to use private key passwords

and more. Information technology tries to explicate the basics of TLS just non, however, a primer on TLS, encryption, public Cardinal Infrastructure and related topics, so the concepts are covered very briefly.

A number of beginner-oriented primers are available elsewhere on the Web: one two, three, four.

TLS tin can be enabled for all protocols supported past RabbitMQ, not merely AMQP 0-9-1, which this guide focuses on. HTTP API, inter-node and CLI tool traffic can be configured to apply TLS (HTTPS) also.

To configure TLS on Kubernetes using the RabbitMQ Cluster Operator, see the guide for Configuring TLS.

For an overview of common TLS troubleshooting techniques, encounter Troubleshooting TLS-related issues and Troubleshooting Networking.

Common Approaches to TLS for customer Connections with RabbitMQ

For client connections, at that place are two common approaches:

  • Configure RabbitMQ to handle TLS connections
  • Employ a proxy or load balancer (such as HAproxy) to perform TLS termination of client connections and use plain TCP connections to RabbitMQ nodes.

Both approaches are valid and take pros and cons. This guide volition focus on the first selection. Sure parts of this guide would however be relevant for environments that cull the 2d option.

Erlang/OTP Requirements for TLS Back up

In social club 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, fifty-fifty if they are supported, may work for virtually certificates only accept known limitations (run into beneath).

The Erlang asn1, crypto, public_key, and ssl libraries (applications) must be installed and functional. On Debian and Ubuntu this is provided by the erlang-asn1, erlang-crypto, erlang-public-key, and erlang-ssl packages, respectively. The zero dependency Erlang RPM for RabbitMQ includes the higher up modules.

If Erlang/OTP is compiled from source, information technology is necessary to ensure that configure finds OpenSSL and builds the to a higher place libraries.

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

Known Incompatibilities and Limitations

If Elliptic curve cryptography (ECC) cipher suites is expected to be used, a recent supported Erlang release is highly recommended. Before releases have known limitations around ECC support.

If you face the above limitations or any other incompatibilities, use the TLS termination selection (see above).

TLS Basics: Certificate Government, Certificates, Keys

TLS is a large and fairly complex topic. Before explaining how to enable TLS in RabbitMQ information technology's worth briefly cover some of the concepts used in this guide. This section is intentionally cursory 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: one 2, three, four.

For a thorough agreement of TLS and how to get the near out of it, nosotros would recommend the use of other resource, for case Network Security with OpenSSL.

TLS has ii principal purposes: encrypting connection traffic and providing a mode to cosign (verify) the peer to mitigate against Man-in-the-Middle attacks. Both are achieved using a fix of roles, policies and procedures known equally Public Primal Infrastructure (PKI).

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/fundamental pairs. Every TLS-enabled server usually has its own document/cardinal pair that information technology uses to compute a connectedness-specific primal that volition exist used to encrypt traffic sent on the connexion. Also, if asked, it can present its document (public key) to the connection peer. Clients may or may not take their ain certificates. In the context of messaging and tools such as RabbitMQ it is quite mutual for clients to also utilize certificate/fundamental pairs so that servers can validate their identity.

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

Here's an example of the almost basic chain with i root CA and 1 leaf (server or customer) certificate:

Root CA and leaf certificates

A chain with intermediate certificates might await similar this:

Root CA, intermediate and leaf certificates

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

A TLS-enabled RabbitMQ node must have a set of Document Authorisation certificates information technology considers to be trusted in a file (a CA packet), a certificate (public primal) file and a private key file. The files will be read from the local filesystem. They must exist readable past the effective user of the RabbitMQ node procedure.

Both ends of a TLS-enabled connexion can optionally verify the other end of the connexion. While doing and so, they try to locate a trusted Document Authority in the certificate list presented past the peer. When both sides perform this verification procedure, this is known as mutual TLS authentication or mTLS. More than on this in the Peer Verification section.

This guides assumes the user has access to a Document Authorization and two certificate/key pairs in a number of formats for different customer libraries to use. This is all-time washed using existing tools only those looking to get more familiar with the topic and OpenSSL control line tools there's a carve up section.

In production environments certificates are generated past a commercial Certificate Authorisation or a Certificate Authority issued by the internal security team. In those cases Certificate Potency package files very likely will contain more than one certificate. This doesn't change how the package 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 manner. The section on peer verification covers this in item.

The Short Route to Generating a CA, Certificates, and Keys

This guides assumes the user has access to a CA certificate bundle file and two document/key pairs. The certificate/central 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 adequately labourious and can be error-prone. An easier way of generating all that stuff on MacOS or Linux is with tls-gen: it requires Python 3.5+, make and openssl in PATH.

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

tls-gen supports RSA and Elliptic Curve Cryptography algorithms for key generation.

Using tls-gen'south Basic Contour

Below is an example that generates a CA and uses it to produce ii certificate/central pairs, one for the server and another for clients. This is the setup that is expected past the balance of this guide.

git clone https://github.com/michaelklishin/tls-gen tls-gen cd tls-gen/basic # individual key password make Countersign=bunnies brand verify make info ls -50 ./result        

The certificate concatenation produced by this basic tls-gen profile looks like this:

Root CA and leaf certificates

Enabling TLS Support in RabbitMQ

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 i more CA certificates), the server's certificate file, and the server'southward key. A TLS listener should also exist enabled to know what port to heed on for TLS-enabled customer connections. More TLS-related things can be configured. Those are covered in the rest of this guide.

Here are the essential configuration settings related to TLS:

Configuration Central Description
listeners.ssl A list of ports to listen on for TLS connections. RabbitMQ can listen on a unmarried interface or multiple ones.
ssl_options.cacertfile Certificate Authority (CA) packet file path
ssl_options.certfile Server certificate file path
ssl_options.keyfile Server individual primal file path
ssl_options.verify Should peer verification be enabled?
ssl_options.fail_if_no_peer_cert When fix to true, TLS connectedness will be rejected if client fails to provide a certificate

The options are provided in the configuration file. An case of the config file is below, which will start one TLS listener on port 5671 on all interfaces on this hostname:

listeners.ssl.default = 5671  ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem ssl_options.verify     = verify_peer ssl_options.fail_if_no_peer_cert = true        

This configuration will besides perform peer document chain verification so clients without any certificates volition be rejected.

Information technology is possible to completely disable regular (non-TLS) listeners. Only TLS-enabled clients would exist able to connect to such a node, and only if they use the correct port:

# disables non-TLS listeners, only TLS-enabled clients will be able to connect listeners.tcp = none  listeners.ssl.default = 5671  ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem ssl_options.verify     = verify_peer ssl_options.fail_if_no_peer_cert = true        

TLS settings can also be configured using the classic config format:

[   {rabbit, [      {ssl_listeners, [5671]},      {ssl_options, [{cacertfile, "/path/to/ca_certificate.pem"},                     {certfile,   "/path/to/server_certificate.pem"},                     {keyfile,    "/path/to/server_key.pem"},                     {verify,     verify_peer},                     {fail_if_no_peer_cert, truthful}]}    ]} ].        

Certificate and Private Key File Paths

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

Note to Windows users: backslashes ("\") in the configuration file are interpreted every bit escape sequences - so for case to specify the path c:\ca_certificate.pem for the CA document you lot would demand to utilize "c:\\ca_certificate.pem" or "c:/ca_certificate.pem".

How to Verify that TLS is Enabled

To verify that TLS has been enabled on the node, restart information technology and audit its log file. Information technology should contain an entry about a TLS listener existence enabled, looking like this:

2020-07-xiii 21:xiii:01.015 [info] <0.573.0> started TCP listener on [::]:5672 2020-07-thirteen 21:13:01.055 [info] <0.589.0> started TLS (SSL) listener on [::]:5671        

Some other way is by using rabbitmq-diagnostics listeners which should contain lines for TLS-enabled listeners:

rabbitmq-diagnostics listeners # # ... (some output omitted for brevity) # => Interface: [::], port: 5671, protocol: amqp/ssl, purpose: AMQP 0-ix-1 and AMQP 1.0 over TLS # ...        

Providing Private Primal Countersign

Individual keys can be optional protected by a password. To provide the password, use the password option:

listeners.ssl.1 = 5671 ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem ssl_options.password   = t0p$3kRe7        

The same example using the classic config format:

[  {rabbit, [            {ssl_listeners, [5671]},            {ssl_options, [{cacertfile,"/path/to/ca_certificate.pem"},                           {certfile,  "/path/to/server_certificate.pem"},                           {keyfile,   "/path/to/server_key.pem"},                           {password,  "t0p$3kRe7"}                          ]}           ]} ].        

Classic config file format allows for config value encryption, which is recommended for passwords.

TLS Peer Verification: Who Do You Say Yous Are?

Every bit mentioned in the Certificates and Keys section, TLS has two primary purposes: encrypting connectedness traffic and providing a way to verify that the peer can be trusted (east.grand. signed past a trusted Certificate Dominance) to mitigate against Homo-in-the-Centre attacks, a form of attacks where an attacker impersonates a legitimate trusted peer (commonly a server). This section volition focus on the latter.

How Peer Verification Works

When a TLS connexion is established client and server perform connectedness negotiation that takes several steps. The first step is when the peers optionally substitution their certificates. Having exchanged certificates, the peers can optionally attempt to institute 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 fundamental hasn't been stolen).

The procedure is known as peer verification or peer validation and follows an algorithm known every bit the Certification path validation algorithm. Understanding the entire algorithm is not necessary in order to apply peer verification, so this section provides an oversimplified explanation of the cardinal parts.

Each peer provides a chain of certificates that begins with a "leaf" (client or server) document and continues with at to the lowest degree 1 Document Dominance (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 past A and C is signed by B, the concatenation is A, B, C (commas here are used for clarity). The "topmost" (first or only) CA is frequently referred to as the root CA for the chain. Root CAs tin be issued by well-known Certificate Authorities (commercial vendors) or whatever other political party (self-signed).

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

Root CA and leaf certificates

A concatenation with intermediate certificates might look similar this:

Root CA, intermediate and leaf certificates

During peer verification TLS connection customer (or server) traverses the concatenation of certificates presented by the peer and if a trusted certificate is establish, considers the peer trusted.

Mutual Peer Verification (Mutual TLS Hallmark or mTLS)

When both sides perform this peer verification procedure, this is known every bit mutual TLS authentication or mTLS.

Enabling mutual peer verification involves two things:

  • Enabling peer verification for client connections on the RabbitMQ side
  • Enabling peer verification of the server in application code

In other words, mutual peer verification ("mTLS") is a articulation responsibility of RabbitMQ nodes and client connections. Enabling peer verification on only one end is non enough.

When Peer Verification Fails

If no trusted and otherwise valid certificate is found, peer verification fails and customer'due south TLS (TCP) connection is closed with a fatal fault ("alert" in OpenSSL parlance) that says "Unknown CA" or similar. The alert volition exist logged past the server with a message similar to this:

2018-09-10 18:x:46.502 [info] <0.902.0> TLS server generated SERVER ALERT: Fatal - Unknown CA        

Document validity is also checked at every step. Certificates that are expired or aren't however valid will be rejected. The TLS alert in that case will look something similar this:

2018-09-10 18:11:05.168 [info] <0.923.0> TLS server generated SERVER ALERT: Fatal - Certificate Expired        

The examples above demonstrate TLS alert messages logged by a RabbitMQ node. Clients that perform peer verification will as well heighten alerts but may use different error messages. RFC 8446 section half-dozen.2 provides an overview of various alerts and what they mean.

Trusted Certificates

Every TLS-enabled tool and TLS implementation, including Erlang/OTP and RabbitMQ, has a style of marking a set of certificates as trusted.

In that location are three common approaches to this:

  • All trusted CA certificates must exist added to a single file called the CA document bundle
  • All CA certificates in a directory are considered to be trusted
  • A dedicated tool is used to manage trusted CA certificates

Different TLS implementation and tools utilise dissimilar options. In the context of RabbitMQ this means that the trusted certificate management approach may exist dissimilar for different client libraries, tools and RabbitMQ server itself.

For example, OpenSSL and OpenSSL command line tools such as s_client on Linux and other UNIX-like systems will apply a directory administered by superusers. CA certificates in that directory volition be considered trusted, and then are the certificates issued by them (such every bit those presented by clients). Locations of the trusted certificate directory will vary between 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 style 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.

RabbitMQ relies on Erlang's TLS implementation. It assumes that all trusted CA certificates are added to the server certificate bundle.

When performing peer verification, RabbitMQ will simply consider the root certificate (beginning certificate in the list) to be trusted. Whatsoever intermediate certificates will exist ignored. If it'due south desired that intermediate certificates are also considered to be trusted they must be added to the trusted certificate list: the certificate bundle.

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

The most common fashion of appending several certificates to ane another and apply in a single Document Authority bundle file is to but concatenate them:

cat rootca/ca_certificate.pem otherca/ca_certificate.pem > all_cacerts.pem        

Enabling Peer Verification

On the server cease, 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 utilize one).

When the ssl_options.verify option is set up to verify_peer, the customer does send us a certificate, the node must perform peer verification. When set to verify_none, peer verification volition be disabled and certificate substitution won't be performed.

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

listeners.ssl.default = 5671  ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile = /path/to/server_certificate.pem ssl_options.keyfile = /path/to/server_key.pem ssl_options.verify = verify_peer ssl_options.fail_if_no_peer_cert = truthful        

The same case in the classic config format:

[ {rabbit, [    {ssl_listeners, [5671]},    {ssl_options, [{cacertfile,"/path/to/ca_certificate.pem"},                   {certfile,"/path/to/server_certificate.pem"},                   {keyfile,"/path/to/server_key.pem"},                   {verify, verify_peer},                   {fail_if_no_peer_cert, true}]}  ]} ].        

How exactly peer verification is configured in client libraries varies from library to library. Java and .Cyberspace customer sections comprehend peer verification in those clients.

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

Thus it is possible to create an encrypted TLS connectedness without having to verify certificates. Customer libraries usually back up both modes of operation.

When peer verification is enabled, it is common for clients to also cheque whether the hostname of the server they are connecting to matches one of two fields in the server certificate: the SAN (Discipline Culling Proper name) or CN (Common Name). When wildcard certificates are used, the hostname is matched against a design. If in that location is no friction match, peer verification volition also be failed by the client. Hostname checks are also optional and generally orthogonal to certificate chain verification performed by the customer.

Because of this it is of import to know what SAN (Subject field Alternative Proper name) or CN (Common Proper noun) values were used when generating the certificate. If a document is generated on one host and used on a dissimilar host so the $(hostname) value should be replaced with the right hostname of the target server.

tls-gen will use local machine'south hostname for both values. Likewise, in the transmission certificate/fundamental pair generation section local car's hostname is specified every bit ...-subj /CN=$(hostname)/... to some OpenSSL CLI tool commands.

Certificate Chains and Verification Depth

When using a client certificate signed past an intermediate CA, it may exist 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 (eastward.g. client) certificate must be signed by the trusted CA directly, if ane the path can be "peer, CA, trusted CA", if it is 2 "peer, CA, CA, trusted CA", and so on. The default depth is i.

The following example demonstrates how to configure certificate validation depth for RabbitMQ server:

listeners.ssl.default = 5671  ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile = /path/to/server_certificate.pem ssl_options.keyfile = /path/to/server_key.pem ssl_options.verify = verify_peer ssl_options.depth  = two ssl_options.fail_if_no_peer_cert = faux        

The same example in the archetype config format:

[   {rabbit, [      {ssl_listeners, [5671]},      {ssl_options, [{cacertfile,"/path/to/ca_certificate.pem"},                     {certfile,"/path/to/server_certificate.pem"},                     {keyfile,"/path/to/server_key.pem"},                     {depth, 2},                     {verify,verify_peer},                     {fail_if_no_peer_cert,false}]}    ]} ].        

When using RabbitMQ plugins such equally Federation or Shovel with TLS, it may be necessary to configure verification depth for the Erlang customer that those plugins use nether the hood, as explained beneath.

Using TLS in the Java Client

There are two main parts to enabling TLS in the RabbitMQ Java client: setting up the primal store with a bit of Java security framework plumbing and implementing the desired peer verification strategy.

Key Managers, Trust Managers and Stores

In that location are three main components in the Java security framework: Central Director, Trust Manager and Key Store.

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

A Trust Director is used past a peer to manage remote certificates. During TLS connection/session negotiation, the trust managing director will control which certificates are trusted from a remote peer. Trust managers can be used to implement any certificate concatenation verification logic.

A Central Shop is a Java encapsulation of the document shop 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) document(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 customer are configured via the ConnectionFactory.

Connecting with TLS

This very basic example will evidence a unproblematic client connecting to a RabbitMQ server over TLS without validating the server certificate, and without presenting any client certificate to the server.

import coffee.io.*; import java.security.*;  import com.rabbitmq.client.*;  public form Example1 {      public static void main(Cord[] args) throws Exception {         ConnectionFactory factory = new ConnectionFactory();         factory.setHost("localhost");         mill.setPort(5671);          factory.useSslProtocol();         // Tells the library to setup the default Central and Trust managers for you         // which exercise not do whatever grade of remote server trust verification          Connexion conn = factory.newConnection();         Channel aqueduct = conn.createChannel();          // not-durable, sectional, automobile-delete queue         channel.queueDeclare("rabbitmq-java-examination", false, truthful, true, null);         channel.basicPublish("", "rabbitmq-java-exam", null, "Hello, World".getBytes());          GetResponse chResponse = channel.basicGet("rabbitmq-java-exam", false);         if (chResponse == nada) {             System.out.println("No message retrieved");         } else {             byte[] torso = chResponse.getBody();             System.out.println("Received: " + new String(trunk));         }          aqueduct.close();         conn.close();     } }

This simple case is an echo client and server. It creates a aqueduct and publishes to the default straight substitution, and then fetches back what has been published and echoes it out. It uses an sectional, not-durable, motorcar-delete queue that will exist deleted presently later on the connection is closed.

Connecting with Peer Verification Enabled

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

keytool -import -alias server1 -file /path/to/server_certificate.pem -keystore /path/to/rabbitstore        

The above command will import server/certificate.pem into the rabbitstore file using the JKS format. The document will be referred to equally 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 whatever tampering attempt.

The customer 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 Fundamental Manager and Trust Director, respectively.

import coffee.io.*; import coffee.security.*; import javax.net.ssl.*;  import com.rabbitmq.client.*;  public course Example2 {      public static void master(String[] args) throws Exception {       char[] keyPassphrase = "MySecretPassword".toCharArray();       KeyStore ks = KeyStore.getInstance("PKCS12");       ks.load(new FileInputStream("/path/to/client_key.p12"), keyPassphrase);        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");       kmf.init(ks, keyPassphrase);        char[] trustPassphrase = "rabbitstore".toCharArray();       KeyStore tks = KeyStore.getInstance("JKS");       tks.load(new FileInputStream("/path/to/trustStore"), trustPassphrase);        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");       tmf.init(tks);        SSLContext c = SSLContext.getInstance("TLSv1.2");       c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), nothing);        ConnectionFactory factory = new ConnectionFactory();       manufacturing plant.setHost("localhost");       factory.setPort(5671);       factory.useSslProtocol(c);       factory.enableHostnameVerification();        Connection conn = manufacturing plant.newConnection();       Aqueduct channel = conn.createChannel();        aqueduct.queueDeclare("rabbitmq-java-examination", imitation, true, true, null);       channel.basicPublish("", "rabbitmq-java-examination", nil, "Hello, Earth".getBytes());        GetResponse chResponse = aqueduct.basicGet("rabbitmq-java-test", false);       if (chResponse == null) {           System.out.println("No message retrieved");       } else {           byte[] body = chResponse.getBody();           System.out.println("Received: " + new String(torso));       }        channel.shut();       conn.close();   } }

To ensure that the above code works equally expected with untrusted certificates, set up a RabbitMQ node with a document that has not been imported into the key store and watch the connectedness fail.

Server Hostname Verification

Hostname verification must exist enabled separately using the ConnectionFactory#enableHostnameVerification() method. This is done in the case above, for case:

import java.io.*; import java.security.*; import javax.net.ssl.*;  import com.rabbitmq.client.*;  public course Example2 {      public static void main(Cord[] args) throws Exception {       char[] keyPassphrase = "MySecretPassword".toCharArray();       KeyStore ks = KeyStore.getInstance("PKCS12");       ks.load(new FileInputStream("/path/to/client_key.p12"), keyPassphrase);        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");       kmf.init(ks, passphrase);        char[] trustPassphrase = "rabbitstore".toCharArray();       KeyStore tks = KeyStore.getInstance("JKS");       tks.load(new FileInputStream("/path/to/trustStore"), trustPassphrase);        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");       tmf.init(tks);        SSLContext c = SSLContext.getInstance("TLSv1.2");       c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);        ConnectionFactory factory = new ConnectionFactory();       factory.setHost("localhost");       factory.setPort(5671);       factory.useSslProtocol(c);       factory.enableHostnameVerification();        // this connexion will both perform peer verification       // and server hostname verification       Connectedness conn = manufactory.newConnection();        // snip ...   } }

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

With JDK vi, information technology is necessary to add a dependency on Apache Commons HttpClient for hostname verification to work, eastward.g. with Maven:

<!-- Maven dependency to add together for hostname verification on JDK 6 --> <dependency>     <groupId>org.apache.httpcomponents</groupId>     <artifactId>httpclient</artifactId>     <version>4.five.half-dozen</version> </dependency>        

With Gradle:

// Gradle dependency to add for hostname verification on JDK 6 compile grouping: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.half-dozen'        

Alternatively with JDK half dozen ConnectionFactory#enableHostnameVerification(HostnameVerifier) can be provided a HostnameVerifier case of pick.

Configuring TLS Version in Java Customer

Just similar RabbitMQ server can exist configured to support but specific TLS versions, it may be necessary to configure preferred TLS version in the Coffee client. This is washed using the ConnectionFactory#useSslProtocol overloads that have a protocol version name or a SSLContext:

ConnectionFactory manufacturing plant = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5671);  mill.useSslProtocol("TLSv1.2");        

Modern releases of the library volition try to employ the latest TLS version supported by the runtime.

Using TLS in the .NET Customer

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

.NET Trust Store

On the .Internet platform, trusted certificates are managed by putting them into any of a number of stores. All management of these stores is done with the 'certmgr' tool.

N.B.: on some flavours of Windows at that place are ii versions of the command: one that ships with the operating arrangement and provides a graphical interface only, and 1 that ships with the Windows SDK and provides both a graphical and control line interface. Either will practise the job, simply the examples below are based on the latter.

For our case, because we're supplying the customer document/key pair in a dissever PKCS#12 file, all we need to exercise is to import the certificate of the root Certificate Authorization into the Root (Windows) or Trust (Mono) store. All certificates signed past whatever document in that store are automatically trusted.

In contrast to the Java client, which is happy to apply a TLS connectedness without performing peer verification, the .NET client past default requires this verification to succeed. To suppress verification, an application can gear up the Organization.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable and System.Cyberspace.Security.SslPolicyErrors.RemoteCertificateChainErrors flags in SslOption.

Document Direction with Certmgr

certmgr is a command line tool that manages certificates in a specified store, for example, adds and deletes them. These stores tin be per-user stores, or organization-broad. Only authoritative users can accept write access to the organisation-wide stores.

The following example adds a certificate to the shop of user Root (likewise known every bit Trust in some .Cyberspace implementation)

# Windows certmgr -add -all \path\to\cacert.cer -s Root        
# Linux with Mono certmgr -add -c Trust /path/to/cacert.cer        

To add together a certificate to the system-wide (auto) certificate store instead, run

# Windows certmgr -add -all \path\to\cacert.cer -south -r localMachine Root        
= # Linux with Mono certmgr -add -c -m Trust /path/to/cacert.cer        

After adding to a shop, nosotros can view the contents of that store with the -all (-list with Mono) switch:

certmgr -all -s Root  # … snip …  Cocky-signed X.509 v3 Certificate   Series Number: AC3F2B74ECDD9EEA00   Issuer Name:   CN=MyTestCA   Subject Name:  CN=MyTestCA   valid From:    25/08/2018 xiv:03:01   valid Until:   24/09/2018 14:03:01   Unique Hash:   1F04D1D2C20B97BDD5DB70B9EB2013550697A05E        
certmgr -list -c Trust  # … snip …  Self-signed 10.509 v3 Document   Serial Number: AC3F2B74ECDD9EEA00   Issuer Name:   CN=MyTestCA   Discipline Name:  CN=MyTestCA   valid From:    25/08/2018 14:03:01   valid Until:   24/09/2018 14:03:01   Unique Hash:   1F04D1D2C20B97BDD5DB70B9EB2013550697A05E        

According to the above output there is ane 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:

# Windows certmgr -del -c -sha1 1F04D1D2C20B97BDD5DB70B9EB2013550697A05E -s Root  # … snip …  Certificate removed from shop.        
# Linux with Mono certmgr -del -c Trust 1F04D1D2C20B97BDD5DB70B9EB2013550697A05E  # … snip …  Certificate removed from store.        

Connexion TLS Settings

To create a TLS-enabled connection to RabbitMQ, nosotros need to ready some new fields in the ConnectionFactory'southward 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'south certificate in PKCS#12 format if your server expects client side verification. This is optional.
Ssl.CertPassphrase If you are using a client document in PKCS#12 format then information technology'll probably have a password, which you lot 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 .Internet expects this to match the Subject Culling Name (SAN) or Common Proper name (CN) on the certificate that the server sends over.

TLS Versions

Just like RabbitMQ server can be configured to support only specific TLS versions, information technology may be necessary to configure preferred TLS version in the .Internet client. This is done using the TLS options attainable via ConnectionFactory#Ssl.

Supported TLS version values are those of the Organisation.Security.Authentication.SslProtocols enum:

using Organization.Security.Hallmark;  // ...  ConnectionFactory cf = new ConnectionFactory();  cf.Ssl.Enabled = true; cf.Ssl.ServerName = System.Internet.Dns.GetHostName(); cf.Ssl.CertPath = "/path/to/client_key.p12"; cf.Ssl.CertPassphrase = "MySecretPassword";  // Use TLSv1.2 for this connection cf.Ssl.Version = SslProtocols.Tls12;        

RabbitMQ .Cyberspace customer v.x series uses TLSv1.0 by default.

Starting with RabbitMQ .NET client half dozen.0 the default changes to SslProtocols.None, which ways the default is picked by the .Internet framework or the operating system depending on app context switches.

If a connection that uses SslProtocols.None to pick a suitable TLS version fails, the client will retry with TLSv1.two enabled explicitly. This reduces the need for explicit configuration on the awarding developer's end in environments where automated TLS version selection is disabled, not available or otherwise cannot be relied on.

Modernistic .NET frameworks versions default to TLSv1.2.

Code Example

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

using System; using Arrangement.IO; using System.Text;  using RabbitMQ.client; using RabbitMQ.Util;  namespace RabbitMQ.customer.Examples {   public form TestSSL {     public static int Main(string[] args) {       ConnectionFactory cf = new ConnectionFactory();        cf.Ssl.Enabled = true;       cf.Ssl.ServerName = System.Net.Dns.GetHostName();       cf.Ssl.CertPath = "/path/to/client_key.p12";       cf.Ssl.CertPassphrase = "MySecretPassword";        using (IConnection conn = cf.CreateConnection()) {         using (IModel ch = conn.CreateModel()) {           Console.WriteLine("Successfully connected and opened a aqueduct");           ch.QueueDeclare("rabbitmq-dotnet-test", false, false, imitation, null);           Panel.WriteLine("Successfully alleged a queue");           ch.QueueDelete("rabbitmq-dotnet-exam");           Console.WriteLine("Successfully deleted the queue");         }       }       return 0;     }   } }        

TLS Peer Verification in .NET Client

TLS offers peer verification (validation), a fashion for client and server to verify each other's identity based on peer'due south 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'due south certificate, otherwise the certificate will be rejected. Still, peer verification doesn't have to be express 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 motorcar, and using them on the other then exist sure to swap out the $(hostname) department, and replace information technology with the correct hostname for your server.

On the .NET platform, RemoteCertificateValidationCallback controls TLS verification behavior.

In RabbitMQ .NET customer, RabbitMQ.client.SslOption.CertificatevalidationCallback tin 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 exist used in conjunction with the AcceptablePolicyErrors property to determine if the remote server certificate is valid.

The System.Cyberspace.Security.SslPolicyErrors.RemoteCertificateNameMismatch flag in RabbitMQ.customer.SslOption.AcceptablePolicyErrors can be used to disable peer verification (not recommended in production environments!).

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

Limiting TLS Versions Used by the Server

Why Limit TLS Versions

TLS (née SSL) has evolved over fourth dimension and has multiple versions in use. Each version builds on the shortcomings of previous versions. Most of the fourth dimension 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 afflicted zip suites).

For the above reasons, recent release series of Erlang only enable latest supported TLS version past default, every bit demonstrated in the below table.

Erlang Serial TLS Versions Enabled by Default
23.x TLSv1.3 (has a dedicated section) and TLSv1.two
22.x TLSv1.2

Users of older supported Erlang releases are encouraged to limit supported TLS versions to one.2 and subsequently versions just, if possible. Consider TLSv1.0 and TLSv1.1 to be deprecated past the industry.

Why Not Limit TLS Versions

Limiting TLS versions to just TLSv1.3 or even only TLSv1.two means that clients that support older TLS versions only won't be able to connect.

If support for applications that use such sometime runtimes is important, the server must be configured to support older versions of TLS. In virtually cases, supporting TLSv1.2 should be sufficient.

To limit enabled TLS protocol versions, use the ssl_options.versions setting.

The example below only accepts TLSv1.three (the virtually contempo and secure version), and requires the node to exist running on Erlang 23 compiled confronting a very recent OpenSSL. Clients that utilize older runtimes (due east.yard. JDK, .Cyberspace, Python) without TLSv1.3 support will not be able to connect with this setup.

listeners.ssl.1 = 5671  ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem  ssl_options.versions.i = tlsv1.3  # Limits enable cipher suites to only those used past TLSv1.3. # There are no cipher suites supported by both TLSv1.iii and TLSv1.2. ssl_options.ciphers.i  = TLS_AES_256_GCM_SHA384 ssl_options.ciphers.two  = TLS_AES_128_GCM_SHA256 ssl_options.ciphers.3  = TLS_CHACHA20_POLY1305_SHA256 ssl_options.ciphers.4  = TLS_AES_128_CCM_SHA256 ssl_options.ciphers.five  = TLS_AES_128_CCM_8_SHA256        

The example below disables versions older than TLSv1.ii:

listeners.ssl.1 = 5671 ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem  ssl_options.versions.1 = tlsv1.two        

Verifying Enabled TLS Versions

To verify provided TLS versions, use openssl s_client with an appropriate TLS version flag:

# connect using TLSv1.3 openssl s_client -connect 127.0.0.1:5671 -tls1_3        

and look for the following in the output:

New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384        

In the example below, TLSv1.two is used:

# connect using TLSv1.2 openssl s_client -connect 127.0.0.i:5671 -tls1_2        

The protocol and negotiated cipher suite in the output would expect like so:

SSL-Session:     Protocol  : TLSv1.2     Aught    : ECDHE-RSA-AES256-GCM-SHA384        

TLSv1.three

TLSv1.3 is a major revision to the TLS protocol. It is the nearly recent and secure selection. Prior to RabbitMQ 3.8.11, TLSv1.3 support was considered experimental and was disabled.

TLSv1.three support requires the node to exist running on Erlang 23 compiled against a very recent OpenSSL.

Clients that use older runtimes (e.g. JDK, .NET, Python) without TLSv1.3 support will not be able to connect to RabbitMQ nodes that are configured to only accept TLSv1.3 connections.

Considering TLSv1.3 shares no cipher suites with earlier TLS versions, when enabling TLSv1.3, list a set of TLSv1.three-specific nada suites:

listeners.ssl.1 = 5671  ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem  ssl_options.versions.1 = tlsv1.iii  # Limits enable cipher suites to only those used by TLSv1.3. # There are no cipher suites supported by both TLSv1.iii and TLSv1.2. ssl_options.ciphers.1  = TLS_AES_256_GCM_SHA384 ssl_options.ciphers.two  = TLS_AES_128_GCM_SHA256 ssl_options.ciphers.3  = TLS_CHACHA20_POLY1305_SHA256 ssl_options.ciphers.4  = TLS_AES_128_CCM_SHA256 ssl_options.ciphers.5  = TLS_AES_128_CCM_8_SHA256        

Explicit cipher suite configuration may also exist necessary on the client side.

To verify provided TLS versions, employ openssl s_client as explained above.

TLS Version Support Tabular array for JDK and .NET

Disabling TLSv1.0 limits the number of customer platforms supported. Below is a table that explains what TLS versions are supported past what JDK and .NET releases.

TLS version Minimum JDK version Minimum .Internet version
TLS 1.three JDK viii starting with JDK8u261, JDK 11+ .NET 4.7 on Windows versions that support TLSv1.3
TLS one.two JDK seven (see Protocols, JDK eight recommended .NET 4.5
TLS 1.ane JDK vii (see Protocols, JDK 8 recommended .Net 4.v

JDK has a public roadmap on catacomb that outlines when certain cipher suites or TLS versions volition be deprecated or removed.

Public Key Usage Options

Public keys (certificates) have a number of fields that describe the intended usage scenarios for the key. The fields limit how the key is allowed to be used past diverse tools. For example, a public key can be used to verify document signatures (act as a Certificate Dominance key).

These fields as well accept effects on what cipher suites will be used by RabbitMQ nodes and clients during connection negotiation (more than specifically, the TLS handshake), and then it is important to explain what the effects are.

This guide volition cover them with some intentional oversimplification. Broadly speaking, the fields fall into one of 3 categories:

  • keyUsage
  • Basic Constraints
  • extendedKeyUsage

Some fields are boolean values, others are of different types such as a set of options ($.25) that tin be fix or unset.

Data services are largely agnostic to the constraints and key usage options used. However, some are essential to the use cases described in this guide:

  • Server authentication (provide server node's identity to the client)
  • Client authentication (provide client'south identity to the server)
  • Verification of digital signatures
  • Primal encipherment

The first ii options are used for peer verification. They must be set for the server and client certificates, respectively, at public key generation time. A document can have both options set at the same time.

tls-gen will make sure that these constraints and extensions are correctly set. When generating certificates manually, this is a responsibility of the operator that generates the cardinal pairs, or a key pair provider.

Extensions and Their Effect on Accepted Zippo Suites (Cipher Suite Filtering)

Two key extensions are critically important for 2 major types of null suites:

  • digitalSignature for ECC (Elliptic Curve Cryptography)-based suites
  • keyEncipherment for RSA-based suites

Information technology is highly recommended that both of the above options ($.25) are set up for certificates that will be used by both RabbitMQ nodes and customer libraries. If those bits are not set, TLS implementations will go out out an entire class of zero suites from consideration, potentially resulting in disruptive "no suitable cipher suite found" alerts (error messages) at connectedness time.

Examining Document Extensions

To encounter what constraints and extensions are set for a public central, use the openssl x509 control:

openssl x509 -in /path/to/certificate.pem -text -noout        

Its output will include a nested list of extensions and constraints that looks similar to this:

X509v3 extensions:     X509v3 Basic Constraints:         CA:FALSE     X509v3 Cardinal Usage:         Digital Signature, Key Encipherment     X509v3 Extended Key Usage:         TLS Web Customer Hallmark        

The above set of extensions says that this is a public key that can exist used to authenticate a client (provide a client identity to a RabbitMQ node), cannot be used as a Certificate Authority certificate and tin can exist used for cardinal encipherment and digital signature.

For the purpose of this guide, this is a suitable document (public primal) to be used for client connections.

Below is an example of a public key suitable certificate for server authentication (provides a RabbitMQ node identity) as well as customer authentication (perhaps for the sake of usability):

X509v3 extensions:     X509v3 Basic Constraints:         CA:FALSE     X509v3 Key Usage:         Digital Signature, Key Encipherment     X509v3 Extended Key Usage:         TLS Spider web Server Hallmark, TLS Web Client Hallmark        

Cipher Suites

It is possible to configure what nil suites volition exist used by RabbitMQ. Note that non all suites will exist bachelor on all systems. For instance, to use Elliptic curve ciphers, a recent supported Erlang release must be used.

What cipher suites RabbitMQ nodes and clients used can besides exist effectively express by the public cardinal usage fields and their values. It is important to make sure that those key usage options are acceptable before proceeding with cipher suite configuration.

Listing Cipher Suites Available on a RabbitMQ Node

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

rabbitmq-diagnostics cipher_suites --format openssl -q        

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

Note that if you employ --format erlang:

rabbitmq-diagnostics cipher_suites --format erlang -q        

then rabbitmq-diagnostics cipher_suites will list cipher suites in the format that'south only accustomed in the classic config format. The OpenSSL format is accepted past both config formats. Notation that cipher suites are non enquoted in the new style config format but double quotes are required in the archetype format.

The zero suites listed by the in a higher place command are in formats that can be used for inbound and outgoing (e.g. Shovel, Federation) client TLS connections. They are different from those used by configuration value encryption.

When overriding cipher suites, it is highly recommended that server-preferred zero suite ordering is enforced.

Configuring Cipher Suites

Nada suites are configured using the ssl_options.ciphers config option (rabbit.ssl_options.ciphers in the classic config format).

The beneath case demonstrates how the option is used.

listeners.ssl.1 = 5671  ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem ssl_options.versions.1 = tlsv1.2  ssl_options.verify = verify_peer ssl_options.fail_if_no_peer_cert = false  ssl_options.ciphers.1  = ECDHE-ECDSA-AES256-GCM-SHA384 ssl_options.ciphers.ii  = ECDHE-RSA-AES256-GCM-SHA384 ssl_options.ciphers.3  = ECDH-ECDSA-AES256-GCM-SHA384 ssl_options.ciphers.4  = ECDH-RSA-AES256-GCM-SHA384 ssl_options.ciphers.v  = DHE-RSA-AES256-GCM-SHA384 ssl_options.ciphers.half-dozen  = DHE-DSS-AES256-GCM-SHA384 ssl_options.ciphers.7  = ECDHE-ECDSA-AES128-GCM-SHA256 ssl_options.ciphers.8  = ECDHE-RSA-AES128-GCM-SHA256 ssl_options.ciphers.9  = ECDH-ECDSA-AES128-GCM-SHA256 ssl_options.ciphers.10 = ECDH-RSA-AES128-GCM-SHA256 ssl_options.ciphers.11 = DHE-RSA-AES128-GCM-SHA256 ssl_options.ciphers.12 = DHE-DSS-AES128-GCM-SHA256  # these MUST exist disabled if TLSv1.3 is used ssl_options.honor_cipher_order = true ssl_options.honor_ecc_order    = true        

In the archetype config format:

%% listing allowed ciphers [  {ssl, [{versions, ['tlsv1.ii', 'tlsv1.1']}]},  {rabbit, [            {ssl_listeners, [5671]},            {ssl_options, [{cacertfile,"/path/to/ca_certificate.pem"},                           {certfile,  "/path/to/server_certificate.pem"},                           {keyfile,   "/path/to/server_key.pem"},                           {versions, ['tlsv1.two', 'tlsv1.1']},                           %% This list is simply an example!                           %% Not all cipher suites are available on all machines.                           %% Cypher suite social club is important: preferred suites                           %% should exist listed first.                           %% Unlike suites have different security and CPU load characteristics.                           {ciphers,  [                             "ECDHE-ECDSA-AES256-GCM-SHA384",                             "ECDHE-RSA-AES256-GCM-SHA384",                             "ECDH-ECDSA-AES256-GCM-SHA384",                             "ECDH-RSA-AES256-GCM-SHA384",                             "DHE-RSA-AES256-GCM-SHA384",                             "DHE-DSS-AES256-GCM-SHA384",                             "ECDHE-ECDSA-AES128-GCM-SHA256",                             "ECDHE-RSA-AES128-GCM-SHA256",                             "ECDH-ECDSA-AES128-GCM-SHA256",                             "ECDH-RSA-AES128-GCM-SHA256",                             "DHE-RSA-AES128-GCM-SHA256",                             "DHE-DSS-AES128-GCM-SHA256"                             ]}                          ]}           ]} ].        

Cipher Suite Order

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

listeners.ssl.1        = 5671 ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem ssl_options.versions.ane = tlsv1.2  ssl_options.honor_cipher_order = true ssl_options.honor_ecc_order    = true        

Or, in the archetype config format:

%% Enforce server-provided cipher suite order (preference) [  {ssl, [{versions, ['tlsv1.2', 'tlsv1.1']}]},  {rabbit, [            {ssl_listeners, [5671]},            {ssl_options, [{cacertfile, "/path/to/ca_certificate.pem"},                           {certfile,   "/path/to/server_certificate.pem"},                           {keyfile,    "/path/to/server_key.pem"},                           {versions,   ['tlsv1.2', 'tlsv1.one']},                            %% ...                             {honor_cipher_order,   true},                           {honor_ecc_order,      true},                          ]}           ]} ].        

Known TLS Vulnerabilities and Their Mitigation

ROBOT

ROBOT attack affects RabbitMQ installations that rely on RSA cipher suites and run on Erlang/OTP versions prior to 19.iii.6.4 and 20.1.7. To mitigate, upgrade Erlang/OTP to a patched version and consider limiting the list of supported cipher suites.

POODLE

POODLE is a known SSL/TLS assault that originally compromised SSLv3. Starting with version 3.4.0, RabbitMQ server refuses to accept SSLv3 connections. In December 2014, a modified version of the POODLE assail that affects TLSv1.0 was announced. Information technology is therefore recommended to either run Erlang xviii.0 or subsequently, which eliminates TLS i.0 implementation vulnerability to POODLE, or disable TLSv1.0 support.

Animate being

Animate being attack is a known vulnerability that affects TLSv1.0. To mitigate it, disable TLSv1.0 support.

Evaluating TLS Setup Security

Considering TLS has many configurable parameters and some of them have suboptimal defaults for historical reasons, TLS setup security evaluation is a recommended practise. Multiple tools be that perform diverse tests on TLS-enabled server endpoints, for example, testing whether it is decumbent to known attacks such as POODLE, Brute, and others.

testssl.sh

testssl.sh is a mature and extensive TLS endpoint testing tool. It can exist used with protocol endpoints that do non serve HTTPS.

The tool performs many tests (for example, on some machines it runs over 350 nada suite tests alone) and passing every single 1 may or may non make sense for every environment. For example, many product deployments practise not use CRLs (Certificate Revocation Lists); most development environments use cocky-signed certificates and don't accept to worry about the near optimal set up of null suites enabled; and then on.

To run testssl.sh, provide an endpoint to test in the course of {hostname}:5671:

./testssl.sh localhost:5671        

The following example configuration that accepts TLSv1.3 connections passes central testssl.sh tests on Erlang 23:

listeners.ssl.one = 5671  ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem  ssl_options.versions.1 = tlsv1.3  ssl_options.verify               = verify_peer ssl_options.fail_if_no_peer_cert = true  ssl_options.ciphers.1  = TLS_AES_256_GCM_SHA384 ssl_options.ciphers.2  = TLS_AES_128_GCM_SHA256 ssl_options.ciphers.3  = TLS_CHACHA20_POLY1305_SHA256 ssl_options.ciphers.4  = TLS_AES_128_CCM_SHA256 ssl_options.ciphers.v  = TLS_AES_128_CCM_8_SHA256  ssl_options.honor_cipher_order   = true ssl_options.honor_ecc_order      = true        

This TLSv1.3-exclusive setup is reported as not vulnerable:

          Service detected:       Couldn't determine what's running on port 5671, bold no HTTP service => skipping all HTTP checks   Testing protocols via sockets except NPN+ALPN   SSLv2      not offered (OK)  SSLv3      not offered (OK)  TLS one      not offered  TLS i.1    not offered  TLS 1.two    not offered  TLS 1.three    offered (OK): final  NPN/SPDY   not offered  ALPN/HTTP2 not offered   Testing cipher categories   Cipher ciphers (no encryption)                      non offered (OK)  Anonymous Zilch Ciphers (no authentication)        not offered (OK)  Export ciphers (w/o ADH+Naught)                     not offered (OK)  Low: 64 Bit + DES, RC[ii,4], MD5 (w/o export)      not offered (OK)  Triple DES Ciphers / Thought                         not offered  Obsoleted CBC ciphers (AES, ARIA etc.)            not offered  Strong encryption (AEAD ciphers) with no FS       not offered  Forward Secrecy stiff encryption (AEAD ciphers)  offered (OK)    Testing server's cipher preferences   Has server cipher order?     yep (TLS 1.iii but)  Negotiated protocol          TLSv1.iii  Negotiated zilch            TLS_AES_256_GCM_SHA384, 253 bit ECDH (X25519)  Cipher per protocol  Hexcode  Cipher Suite Proper name (OpenSSL)       KeyExch.   Encryption  Bits     Cipher Suite Name (IANA/RFC) ----------------------------------------------------------------------------------------------------------------------------- SSLv2  - SSLv3  - TLSv1  - TLSv1.ane  - TLSv1.2  - TLSv1.3 (server order)  x1302   TLS_AES_256_GCM_SHA384            ECDH 253   AESGCM      256      TLS_AES_256_GCM_SHA384  x1301   TLS_AES_128_GCM_SHA256            ECDH 253   AESGCM      128      TLS_AES_128_GCM_SHA256  x1303   TLS_CHACHA20_POLY1305_SHA256      ECDH 253   ChaCha20    256      TLS_CHACHA20_POLY1305_SHA256  x1304   TLS_AES_128_CCM_SHA256            ECDH 253   AESCCM      128      TLS_AES_128_CCM_SHA256  x1305   TLS_AES_128_CCM_8_SHA256          ECDH 253   AESCCM8     128      TLS_AES_128_CCM_8_SHA256    Testing robust forward secrecy (FS) -- omitting Nil Authentication/Encryption, 3DES, RC4   FS is offered (OK)           TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_GCM_SHA256 TLS_AES_128_CCM_SHA256 TLS_AES_128_CCM_8_SHA256  Elliptic curves offered:     prime256v1 secp384r1 X25519 X448    Testing server defaults (Server How-do-you-do)   TLS extensions (standard)    "supported versions/#43" "central share/#51"  Session Ticket RFC 5077 hint no -- no lifetime advertised  SSL Session ID support       yes  Session Resumption           Tickets no, ID resumption test failed  TLS clock skew               -v sec from localtime  Client Authentication        none  Signature Algorithm          SHA256 with RSA  Server key size              RSA 2048 $.25 (exponent is 65537)  Server key usage             Digital Signature, Cardinal Encipherment  Server extended key usage    TLS Web Server Authentication  Serial / Fingerprints        01 / SHA1 7B1C27E995BA409F031CBE0827E017E0CE0B931A                               SHA256 96338084641B5B29FF4E60C570AF5081175D9BDD89EB28FFA3CECE96A995CC8E  Mutual Name (CN)             warp10  subjectAltName (SAN)         warp10 warp10.local localhost  Trust (hostname)             Ok via SAN (same w/o SNI)  Chain of trust               NOT ok (cocky signed CA in concatenation)  EV cert (experimental)       no  Document Validity (UTC)   3611 >= sixty days (2021-01-06 17:43 --> 2031-01-04 17:43)                               >= x years is way too long  ETS/"eTLS", visibility info  not nowadays  Certificate Revocation Listing  --  OCSP URI                     --                               NOT ok -- neither CRL nor OCSP URI provided  OCSP stapling                not offered  OCSP must staple extension   --  DNS CAA RR (experimental)    non offered  Certificate Transparency     Due north/A  Certificates provided        2  Issuer                       TLSGenSelfSignedtRootCA  Intermediate cert validity   #one: ok > twoscore days (2031-01-04 17:43).  Intermediate Bad OCSP (exp.) Ok    Testing vulnerabilities   Heartbleed (CVE-2014-0160)                non vulnerable (OK), no heartbeat extension  CCS (CVE-2014-0224)                       not vulnerable (OK)  Ticketbleed (CVE-2016-9244), experiment.  --   (applicable only for HTTPS)  ROBOT                                     Server does not support whatever cipher suites that use RSA fundamental transport  Secure Renegotiation (RFC 5746)           not vulnerable (OK)  Secure Client-Initiated Renegotiation     not vulnerable (OK)  Criminal offence, TLS (CVE-2012-4929)                not vulnerable (OK)  POODLE, SSL (CVE-2014-3566)               not vulnerable (OK), no SSLv3 support  TLS_FALLBACK_SCSV (RFC 7507)              No fallback possible (OK), TLS i.3 is the only protocol  SWEET32 (CVE-2016-2183, CVE-2016-6329)    not vulnerable (OK)  FREAK (CVE-2015-0204)                     not vulnerable (OK)  DROWN (CVE-2016-0800, CVE-2016-0703)      non vulnerable on this host and port (OK)                                            make sure you lot don't utilize this certificate elsewhere with SSLv2 enabled services                                            https://censys.io/ipv4?q=96338084641B5B29FF4E60C570AF5081175D9BDD89EB28FFA3CECE96A995CC8E could aid you to discover out  LOGJAM (CVE-2015-4000), experimental      not vulnerable (OK): no DH Consign ciphers, no DH primal detected with <= TLS ane.2  BEAST (CVE-2011-3389)                     not vulnerable (OK), no SSL3 or TLS1  LUCKY13 (CVE-2013-0169), experimental     non vulnerable (OK)  Winshock (CVE-2014-6321), experimental    not vulnerable (OK)  RC4 (CVE-2013-2566, CVE-2015-2808)        not vulnerable (OK)  Could not determine the protocol, only simulating generic clients.   Running client simulations via sockets   Browser                      Protocol  Cipher Suite Proper name (OpenSSL)       Forward Secrecy ------------------------------------------------------------------------------------------------  Android 8.1 (native)         No connectedness  Android 9.0 (native)         TLSv1.3   TLS_AES_256_GCM_SHA384            253 chip ECDH (X25519)  Android x.0 (native)        TLSv1.iii   TLS_AES_256_GCM_SHA384            253 chip ECDH (X25519)  Java 6u45                    No connection  Java 7u25                    No connection  Java 8u161                   No connection  Java eleven.0.2 (OpenJDK)        TLSv1.3   TLS_AES_256_GCM_SHA384            256 fleck ECDH (P-256)  Coffee 12.0.1 (OpenJDK)        TLSv1.3   TLS_AES_256_GCM_SHA384            256 bit ECDH (P-256)  OpenSSL 1.0.2e               No connection  OpenSSL ane.1.0l (Debian)      No connectedness  OpenSSL 1.i.1d (Debian)      TLSv1.iii   TLS_AES_256_GCM_SHA384            253 chip ECDH (X25519)        

The post-obit example configuration that accepts TLSv1.2 connections passes cardinal testssl.sh tests on Erlang 23:

listeners.ssl.default  = 5671 ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile   = /path/to/server_certificate.pem ssl_options.keyfile    = /path/to/server_key.pem ssl_options.versions.1 = tlsv1.2  ssl_options.verify               = verify_peer ssl_options.fail_if_no_peer_cert = faux  ssl_options.honor_cipher_order   = true ssl_options.honor_ecc_order      = true  # These are highly recommended for TLSv1.2 merely cannot be used # with TLSv1.3. If TLSv1.three is enabled, these lines MUST exist removed. ssl_options.client_renegotiation = false ssl_options.secure_renegotiate   = true  ssl_options.ciphers.1  = ECDHE-ECDSA-AES256-GCM-SHA384 ssl_options.ciphers.2  = ECDHE-RSA-AES256-GCM-SHA384 ssl_options.ciphers.3  = ECDH-ECDSA-AES256-GCM-SHA384 ssl_options.ciphers.4  = ECDH-RSA-AES256-GCM-SHA384 ssl_options.ciphers.5  = DHE-RSA-AES256-GCM-SHA384 ssl_options.ciphers.6  = DHE-DSS-AES256-GCM-SHA384 ssl_options.ciphers.7  = ECDHE-ECDSA-AES128-GCM-SHA256 ssl_options.ciphers.8  = ECDHE-RSA-AES128-GCM-SHA256 ssl_options.ciphers.9  = ECDH-ECDSA-AES128-GCM-SHA256 ssl_options.ciphers.10 = ECDH-RSA-AES128-GCM-SHA256 ssl_options.ciphers.eleven = DHE-RSA-AES128-GCM-SHA256 ssl_options.ciphers.12 = DHE-DSS-AES128-GCM-SHA256        

This TLSv1.ii-enabled setup is reported as not vulnerable to a ready of known high contour vulnerabilities:

Testing robust (perfect) forward secrecy, (P)FS -- omitting Cipher Hallmark/Encryption, 3DES, RC4  PFS is offered (OK)          ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-GCM-SHA256 Elliptic curves offered:     sect163k1 sect163r1 sect163r2 sect193r1 sect193r2 sect233k1 sect233r1 sect239k1 sect283k1 sect283r1 sect409k1                              sect409r1 sect571k1 sect571r1 secp160k1 secp160r1 secp160r2 secp192k1 prime192v1 secp224k1 secp224r1 secp256k1                              prime256v1 secp384r1 secp521r1 brainpoolP256r1 brainpoolP384r1 brainpoolP512r1   Testing vulnerabilities  Heartbleed (CVE-2014-0160)                not vulnerable (OK), no heartbeat extension CCS (CVE-2014-0224)                       not vulnerable (OK) Ticketbleed (CVE-2016-9244), experiment.  --   (applicative only for HTTPS) Secure Renegotiation (CVE-2009-3555)      not vulnerable (OK) Secure Client-Initiated Renegotiation     not vulnerable (OK) CRIME, TLS (CVE-2012-4929)                not vulnerable (OK) (non using HTTP anyway) POODLE, SSL (CVE-2014-3566)               not vulnerable (OK) TLS_FALLBACK_SCSV (RFC 7507)              No fallback possible, TLS 1.2 is the only protocol (OK) SWEET32 (CVE-2016-2183, CVE-2016-6329)    not vulnerable (OK) FREAK (CVE-2015-0204)                     not vulnerable (OK) DROWN (CVE-2016-0800, CVE-2016-0703)      non vulnerable on this host and port (OK)                                           make certain you lot don't use this certificate elsewhere with SSLv2 enabled services                                           https://censys.io/ipv4?q=5E878E40541CC37F88A0A1BA395FA95EA1EC68373FAC512D54C329F031BA443D could help you to observe out LOGJAM (CVE-2015-4000), experimental      Common prime with 2048 bits detected: RFC3526/Oakley Group 14,                                           but no DH Export ciphers Brute (CVE-2011-3389)                     no SSL3 or TLS1 (OK) LUCKY13 (CVE-2013-0169), experimental     not vulnerable (OK) RC4 (CVE-2013-2566, CVE-2015-2808)        no RC4 ciphers detected (OK)        

Using TLS in the Erlang Client

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

Erlang TLS Options

The three important options which must exist supplied are:

  • The cacertfile option specifies the certificates of the root Certificate Authorities that we wish to implicitly trust.
  • The certfile is the client's ain certificate in PEM format
  • The keyfile is the customer's private key file in PEM format

server_name_indication - prepare this option to the host name of the server to which a TLS connectedness will be made to enable "Server Name Indication" verification of the certificate presented past the server. This ensures that the server certificate'southward CN= value volition be verified during TLS connection establishment. Y'all tin can override this beliefs by setting server_name_indication to a different host name or to the special value disable to disable this verification. Annotation that, by default, SNI is not enabled. This default volition change in a time to come RabbitMQ Erlang client release.

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

Code Example

SslOpts = [{cacertfile, "/path/to/ca_certificate.pem"},            {certfile, "/path/to/customer/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            %%            %% Practice not set up 'verify' or set information technology to verify_none            %% if x509 certificate chain validation is            %% not desired            {verify, verify_peer},             %% If Server Name Indication validation is desired,            %% set the post-obit option to the host proper noun to which            %% the connection is fabricated. If necessary, this option            %% may be ready to some other host name to match the server            %% certificate'southward CN= value.            %% Do not fix this pick 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),        

You can at present go alee and use Conn as a normal connection.

Manually Generating a CA, Certificates and Private Keys

This section of the guide explains how to generate a Certificate Authorization and employ it to generate and sign two certificate/cardinal pairs, one for the server and 1 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 meliorate their understanding of the process, OpenSSL command line tools and some of import aspects of OpenSSL configuration.

This guide assumes a UNIX-similar operating system (Linux, MacOS, a BSD variant and and then on) and a recent version of OpenSSL available in PATH.

First let'south create a directory for our test Document Dominance:

mkdir testca cd testca mkdir certs private chmod 700 private echo 01 > serial impact alphabetize.txt        

Now add the following OpenSSL configuration file, openssl.cnf, inside the newly created testca directory:

[ ca ] default_ca = testca  [ testca ] dir = . certificate = $dir/ca_certificate.pem database = $dir/alphabetize.txt new_certs_dir = $dir/certs private_key = $dir/private/ca_private_key.pem serial = $dir/serial  default_crl_days = 7 default_days = 365 default_md = sha256  policy = testca_policy x509_extensions = certificate_extensions  [ testca_policy ] commonName = supplied stateOrProvinceName = optional countryName = optional emailAddress = optional organizationName = optional organizationalUnitName = optional domainComponent = optional  [ certificate_extensions ] basicConstraints = CA:false  [ req ] default_bits = 2048 default_keyfile = ./private/ca_private_key.pem default_md = sha256 prompt = yes distinguished_name = root_ca_distinguished_name x509_extensions = root_ca_extensions  [ root_ca_distinguished_name ] commonName = hostname  [ root_ca_extensions ] basicConstraints = CA:true keyUsage = keyCertSign, cRLSign  [ client_ca_extensions ] basicConstraints = CA:false keyUsage = digitalSignature,keyEncipherment extendedKeyUsage = i.three.6.1.five.v.seven.3.ii  [ server_ca_extensions ] basicConstraints = CA:simulated keyUsage = digitalSignature,keyEncipherment extendedKeyUsage = 1.3.half dozen.1.5.5.7.three.1        

Next we demand to generate the key and certificates that our exam Certificate Dominance will use. Notwithstanding within the testca directory:

openssl req -x509 -config openssl.cnf -newkey rsa:2048 -days 365 \     -out ca_certificate.pem -outform PEM -subj /CN=MyTestCA/ -nodes openssl x509 -in ca_certificate.pem -out ca_certificate.cer -outform DER        

This is all that is needed to generate a test Document Dominance. The root certificate is in ca_certificate.pem and is also in testca/ca_certificate.cer. These two files contain the same data, only in different formats, PEM and DER. Most software uses the one-time just some tools require the latter.

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

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

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

cd .. ls # => testca mkdir server cd server openssl genrsa -out private_key.pem 2048 openssl req -new -central private_key.pem -out req.pem -outform PEM \     -subj /CN=$(hostname)/O=server/ -nodes cd ../testca openssl ca -config openssl.cnf -in ../server/req.pem -out \     ../server/server_certificate.pem -notext -batch -extensions server_ca_extensions cd ../server openssl pkcs12 -export -out server_certificate.p12 -in server_certificate.pem -inkey private_key.pem \     -passout pass:MySecretPassword        

And now the client:

cd .. ls # => server testca mkdir client cd customer openssl genrsa -out private_key.pem 2048 openssl req -new -central private_key.pem -out req.pem -outform PEM \     -subj /CN=$(hostname)/O=client/ -nodes cd ../testca openssl ca -config openssl.cnf -in ../customer/req.pem -out \     ../client/client_certificate.pem -notext -batch -extensions client_ca_extensions cd ../client openssl pkcs12 -export -out client_certificate.p12 -in client_certificate.pem -inkey private_key.pem \     -passout laissez passer:MySecretPassword        

The two examples above generate individual keys that are 2048 $.25 in size. It is possible to use longer (and thus more secure but besides slower to generate) keys by providing a unlike value to openssl genrsa, east.g.:

openssl genrsa -out private_key.pem 4096        

Some other option would be to generate a primal using Elliptic Curve Cryptography. Instead of openssl genrsa apply openssl ecparam like so:

openssl ecparam -out private_key.pem -genkey -proper name prime256v1        

prime256v1 in the example above is an Elliptic curve name. Dissimilar versions of OpenSSL will have a different set up of curves available, listing them with openssl ecparam -list_curves.

Getting Help and Providing Feedback

If yous take questions nigh the contents of this guide or any other topic related to RabbitMQ, don't hesitate to inquire them on the RabbitMQ mailing list.

Help Us Improve the Docs <three

If y'all'd like to contribute an improvement to the site, its source is available on GitHub. Simply fork the repository and submit a pull asking. Thank y'all!

hansenanswerpose.blogspot.com

Source: https://www.rabbitmq.com/ssl.html

Post a Comment for "Git Clone Error Reading X.509 Key or Certificate File: Error While Reading File."