This guide continues from the manual steps in the main README.md.
- Generate a New Certificate Request
- Convert Binary Certificate to Human Readable
- Certificate Format Conversion
- Import and Export Certificates
- Extract Private Key and Certificate from PFX
- Automate the Process
- Generate CSR on Different Host
- Test mTLS Authentication
Scenario Client settings Server Setting Will it work?
Strict mTLS (Default) verify_peer verify_peer ❌ No (Server rejects expired client cert)
Server-Only Relaxed verify_peer verify_none Yes (Client trusts server; Server ignores client cert date)
Full Relaxed verify_none verify_none Yes (Both sides ignore all dates and signatures)
If you want to keep your remote RabbitMQ server secure while allowing this expired client certificate to connect temporarily, you have two configuration options on the server side:
Option A: Set verify = verify_none on the Server
- This tells the server to completely ignore all validation parameters for any client certificate sent to it.
verify_noneStay with Certificate Auth (mTLS Bypass) If you want to keep using the certificate files (even though the client cert is expired), you must change verify=verify_peer to verify=verify_none in the client URI, and keep your certificate paths.
{uris, ["amqps://pdp-shovel-1@xx.xx.xx.xx:5671?cacertfile=C:\\testca_store\\bundle\\pdp-shovel-1.ca-bundle&certfile=C:\\testca_store\\client\\client_certificate.pem&keyfile=C:\\testca_store\\client\\private_key.pem&verify=verify_none&fail_if_no_peer_cert=true&server_name_indication=pdp-shovel-2&auth_mechanism=external&heartbeat=15"]}Note: As we uncovered earlier, some Erlang/RabbitMQ combinations will still fail auth_mechanism=external under a global verify_none server setting because the identity parsing is skipped. If it fails, use Choice B).
Option B: Turn off Client Certificate Requirement entirely
- Alternatively, if you don't want to change the global verification mode, you can change the server's rabbitmq.conf to stop demanding client certificates entirely:
ssl_options.fail_if_no_peer_cert = falseIf you change the remote server's configuration to ssl_options.fail_if_no_peer_cert = false, it means the server no longer demands a client certificate. It will happily accept standard TLS connections that only use a username and password.
{uris, ["amqps://pdp-shovel-1:password@xx.xx.xx.xx:5671?cacertfile=C:\\testca_store\\bundle\\pdp-shovel-1.ca-bundle&verify=verify_peer&server_name_indication=pdp-shovel-2&heartbeat=15"]}Use certreq to create a new certificate request:
certreq -new request.inf certificate.req📖 Reference: certreq command documentation
Convert a .crt binary certificate to .cer Base64 format:
certutil -encode C:\tmp\server01.corp.logo.com.crt C:\tmp\server01.corp.logo.com.cerExpected output:
Input Length = 2205
Output Length = 3088
CertUtil: -encode command completed successfully
| Format | Description |
|---|---|
.pem |
Base64 encoded X.509 certificate (commonly used in Apache/Tomcat) |
.crt |
Certificate file - can be Base64 or binary |
.cer |
Certificate file - can be Base64 or binary |
.der |
Binary format certificate |
.pfx / .p12 |
PKCS12 bundle containing certificate, chain, and private key |
📖 Reference: SSL Shopper Converter
To convert PEM to .crt or .cer: Simply rename the file (if Base64 encoded is desired).
⚠️ A PEM encoded certificate is already valid - using.certextension is not standard. Use.cer,.pem, or.crtinstead.
When the CSR is approved, import the certificate in MMC:
- Add to Personal certificate store
- If the cert shows as invalid, import all CA certificates to the store
💡 The shovel server needs server auth (at minimum server auth is required, since role is reciever).
💡 The shovel client (server) needs both server auth and client auth (since role is connect and send).
If the certificate is binary (content does not start with -----BEGIN CERTIFICATE-----):
- Import the
.certo local MMC (add signers for verification) - Export from MMC as Base64 encoded
.cer
- After importing all CAs, the personal certificate should be valid
- If not found in MMC Personal, import directly to Personal tab
Export the personal certificate from MMC:
- Format: PFX (include private key)
- Include all certificates in the chain if possible
- Save the password for OpenSSL operations
Check OpenSSL version:
cd "c:\Program Files\OpenSSL-Win64\bin"
openssl version
OpenSSL 3.1.4 24 Oct 2023 (Library: OpenSSL 3.1.4 24 Oct 2023)✅ Recommended: OpenSSL 3.1.4 24 Oct 2023 (Library: OpenSSL 3.1.4 24 Oct 2023)or later
openssl pkcs12 -in myfile.pfx -nocerts -out private.key.pem -nodesEnter the password used during MMC export when prompted.
openssl pkcs12 -in myfile.pfx -clcerts -nokeys -out public.crt.pem -nodesEnter the same password.
Check CN (must be hostname.domain.something):
openssl x509 -noout -subject -in public.crt.pemCheck expiration date:
openssl x509 -noout -enddate -in public.crt.pemExample output: notAfter=Jan 27 10:36:48 2026 GMT
Check serial number:
openssl x509 -noout -serial -in public.crt.pem
**Check .crt vs key**
**Rename public.crt.pem to public.crt,
# Check the .crt and .key files match by comparing the modulus of each file. If they match, the key pair is valid.
openssl x509 -noout -modulus -in C:\OP\SSL\public.crt | openssl sha256 && openssl rsa -noout -modulus -in C:\OP\SSL\private.key.pem | openssl sha256** You can get info about all certs in the bundle if you need to**
openssl storeutl -noout -text -certs C:\RabbitmqBaseFolder\cert\ca.bundleFor automated certificate requests, see README_auto_ps1.md.
# Make request
certreq -new request.inf certificate.req
# Accept the issued certificate (links private key with certificate)
certreq -accept certnew.cerℹ️ The
-acceptparameter links the previously generated private key with the issued certificate and removes the pending request from the system.
Yes! You can generate the CSR and private key on a different host, then transfer both to your app host for mTLS.
** Just make sure that to check .crt vs key** **Rename public.crt.pem to public.crt,
# Check the .crt and .key files match by comparing the modulus of each file. If they match, the key pair is valid.
openssl x509 -noout -modulus -in C:\OP\SSL\public.crt | openssl sha256 && openssl rsa -noout -modulus -in C:\OP\SSL\private.key.pem | openssl sha256-
Generate on Host A (Secure Machine)
- Create private key and CSR or .pfx file (this requires a password that follows with it)
- Send CSR to Certificate Authority (CA)
- Or generate cert and key local
-
Get Signed Certificate
- CA signs and returns the certificate
- Or sign the cert and key local
-
Transfer to App Host (Host B)
- Securely copy private key and certificate or the pfx file
- Use secure methods:
scp,rsyncover SSH - Verify that cert and key matches and that all atributtes are present
- Windows Certificate Manager on Host B will not have the original enrollment request
- The pending request will appear as "orphaned" - this is harmless
- Best Practice: Delete unused "Certificate Enrollment Request" entries to keep the store clean
| Protocol | Port | Description |
|---|---|---|
| AMQP | 5672 | Unencrypted |
| AMQPS | 5671 | TLS-encrypted (often with mTLS) |
openssl s_server -accept 5671 -CAfile C:\path\to\cacert.pem -cert C:\path\to\server.cert.pem -key C:\path\to\server.key.pem -stateopenssl s_client -connect 127.0.0.1:5671 -key C:\path\to\client.key.pem -cert C:\path\to\client.cert.pem -CAfile C:\path\to\cacert.pem -stateopenssl s_client -connect your-broker-host:5671 -key C:\path\to\client.key.pem -cert C:\path\to\client.cert.pem -CAfile C:\path\to\cacert.pem -state- OpenSSL output:
Verify return code: 0 (ok) - RabbitMQ logs: Successful TLS handshake (may show AMQP protocol header error after - this is expected as s_client does not send AMQP frames)
- OpenSSL output: SSL alert error
error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure - RabbitMQ logs:
TLS handshake error: tls_alert_certificate_unknown
⚠️ Runningopenssl s_clientto test does NOT disturb or interrupt current traffic on your RabbitMQ server.
- Public key is embedded in the SSL certificate
- Private key is stored on the server and kept secret
- The Shovel server requires both server auth and client auth for full mTLS support

