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:
A chain with intermediate certificates might await similar this:
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:
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:
A concatenation with intermediate certificates might look similar this:
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!
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."