Taction Software — FHIR Integration with Mirth Connect
Security · TLS · Production Operations

Mirth Connect SSL/TLS Hardening:
The 2026 Playbook

Updated April 2026 · Written by the Taction Software integration team

Enforce TLS 1.2+, choose the right cipher suites, manage keystores without tears, set up mTLS for MLLPS, automate certificate rotation, and tune the JVM — the full hardening playbook we run on every production Mirth Connect environment.

Mirth Connect moves HL7 and FHIR traffic containing ePHI across networks. TLS is the only thing standing between those messages and passive eavesdropping, active tampering, or impersonation attacks. Default Mirth settings accept far more TLS configurations than a modern security program allows — legacy protocols enabled, weak ciphers available, keystores on disk with loose permissions, one-way TLS where mutual TLS should be required.

This playbook is the exact hardening sequence we run on every production Mirth Connect environment. It aligns with NIST SP 800-52r2 guidance on TLS configuration, HIPAA Security Rule transmission security requirements, and the defense-in-depth controls expected in a modern healthcare security program.

Pair this with our security and HIPAA checklist for the broader hardening program, and with the MLLP connection refused guide for the adjacent debugging playbook.

1. Why TLS Hardening Is Non-Negotiable

Three reasons TLS configuration deserves dedicated attention:

  • Regulation — HIPAA transmission security, HITRUST, 42 CFR Part 2, state breach laws. A weak TLS configuration is not an unenforced best practice; it is a finding in every audit.
  • Attack surface — MLLPS and HTTPS endpoints are often internet-reachable or reachable from partner networks. Any protocol or cipher allowed on those endpoints is an attack target.
  • Partner requirements — modern health systems, labs, and payers increasingly refuse to integrate with partners who can't demonstrate a current TLS posture. A TLS audit is common during onboarding.

"Mirth supports TLS" is the starting line, not the finish line. What matters is which TLS — which versions, which ciphers, which key strength, which certificate trust chain, which rotation policy. This guide answers each.

2. Document Your TLS Posture First

Before changing configuration, inventory what you have. For every TLS-enabled listener (MLLPS, HTTPS, REST API) and every TLS-enabled destination (outbound HTTPS, outbound MLLPS), capture:

  • Hostname and port.
  • Allowed protocol versions (TLS 1.2, 1.3, or others).
  • Allowed cipher suites.
  • Certificate: subject, issuer, expiration, key algorithm and size.
  • Keystore path and alias.
  • mTLS required or one-way TLS.
  • Counterparty organization and contact.
  • Rotation cadence and method.

A one-shot probe to collect this per endpoint:

# Enumerate supported protocols and ciphers
nmap --script ssl-enum-ciphers -p 6661 mirth-host

# Pull the certificate for inspection
openssl s_client -connect mirth-host:6661 -showcerts < /dev/null 2>&1 \
  | openssl x509 -noout -subject -issuer -dates

Store the resulting inventory somewhere durable — a wiki, a version-controlled YAML file, a compliance tool. Without this inventory you cannot drive a rotation cadence, and you cannot audit drift over time.

3. Enforce TLS 1.2+ and Disable Legacy Protocols

TLS 1.2 is the minimum defensible version in 2026. TLS 1.3 is preferred where both sides support it. SSLv3, TLS 1.0, and TLS 1.1 are deprecated and must be disabled.

3.1 JVM-level enforcement

In mcserver.vmoptions:

-Djdk.tls.client.protocols=TLSv1.2,TLSv1.3
-Djdk.tls.server.protocols=TLSv1.2,TLSv1.3
-Dhttps.protocols=TLSv1.2,TLSv1.3

3.2 java.security belt-and-suspenders

Edit $JAVA_HOME/conf/security/java.security (or lib/security/java.security on older JDKs) and add legacy protocols to the disabled list:

jdk.tls.disabledAlgorithms=SSLv2Hello, SSLv3, TLSv1, TLSv1.1, \
  RC4, DES, MD5withRSA, DH keySize < 2048, \
  EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
  include jdk.disabled.namedCurves

This prevents even inadvertent negotiation of disabled protocols. If something tries to connect with TLS 1.0, the handshake fails — which is exactly what you want.

3.3 Verify enforcement

# Attempting TLS 1.0 should fail after enforcement
openssl s_client -connect mirth-host:6661 -tls1 < /dev/null
# Expect: write:errno=104 or similar failure

# TLS 1.2 should succeed
openssl s_client -connect mirth-host:6661 -tls1_2 < /dev/null
# Expect: TLSv1.2 handshake complete

4. Cipher Suite Selection

A good cipher policy offers strong, modern suites first and refuses weak ones entirely. Prefer AEAD ciphers (AES-GCM, ChaCha20-Poly1305). Prefer ECDHE key exchange for forward secrecy. Avoid CBC mode, static RSA, and anonymous key exchange.

4.1 Recommended suite list (TLS 1.2 and 1.3)

  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
  • TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

4.2 Ciphers to disable unconditionally

  • RC4 suites — broken, disable unconditionally
  • 3DES suites — effectively broken, remove
  • Export-grade and NULL suites — no purpose in 2026
  • CBC-mode suites on TLS 1.0/1.1 — Lucky13 family attacks
  • Anonymous Diffie-Hellman — no authentication
  • Static RSA key exchange — no forward secrecy
  • MD5 MAC suites
  • SHA-1 MAC suites (prefer SHA-256+)

4.3 Configuring ciphers per listener

Mirth's MLLPS listener configuration exposes a cipher allowlist. Set it explicitly — do not rely on defaults. In the channel source/destination properties:

# Example allowed ciphers field value (comma-separated)
TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,\
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

For HTTPS and REST API listeners, set the cipher allowlist in Mirth's server properties or via JVM system properties. Test after configuration — a misplaced comma or unknown cipher name will cause the listener to refuse to start.

5. Keystore and Truststore Management

The keystore holds Mirth's own private keys. The truststore holds CAs and peer certificates Mirth trusts. Treat both as sensitive material.

5.1 Use PKCS12

PKCS12 is the modern default in Java 9+. Convert JKS keystores to PKCS12 on the next rotation:

keytool -importkeystore \
  -srckeystore keystore.jks -srcstoretype JKS \
  -destkeystore keystore.p12 -deststoretype PKCS12

5.2 Generate keys with strong parameters

# RSA 4096 for general use
keytool -genkeypair -alias mirth-mllps \
  -keyalg RSA -keysize 4096 \
  -sigalg SHA256withRSA \
  -validity 365 \
  -keystore keystore.p12 -storetype PKCS12 \
  -dname "CN=mirth.example.org, O=Example Health, C=US"

# ECDSA P-384 for partners who support EC
keytool -genkeypair -alias mirth-ecdsa \
  -keyalg EC -groupname secp384r1 \
  -sigalg SHA384withECDSA \
  -validity 365 \
  -keystore keystore.p12 -storetype PKCS12 \
  -dname "CN=mirth.example.org, O=Example Health, C=US"

5.3 Filesystem ACLs

sudo chown mirth:mirth /opt/mirthconnect/conf/keystore.p12
sudo chmod 600 /opt/mirthconnect/conf/keystore.p12
sudo chown mirth:mirth /opt/mirthconnect/conf/truststore.p12
sudo chmod 600 /opt/mirthconnect/conf/truststore.p12

Only the Mirth service user should be able to read these files. No group or world read. Confirm regularly — a sloppy backup job can loosen these permissions silently.

5.4 Password storage

Do not store keystore passwords in plain text config files. Use a secrets manager (Vault, AWS Secrets Manager, Azure Key Vault) and load the password at Mirth start. If you must keep it in a local file for now, use Mirth's encrypted configuration (mirth.properties with encrypted values) and ensure the master encryption key conf/mirthkey has 0600 permissions.

6. Mutual TLS (mTLS) Setup

One-way TLS authenticates the server to the client. Mutual TLS additionally authenticates the client to the server. For MLLPS interfaces crossing trust boundaries (between organizations, across the public internet, across cloud tenants), mTLS should be the default.

6.1 Receive side — require client certificate

In the MLLPS listener channel configuration, enable "Require Client Certificate" (or equivalent setting per Mirth version). Import the counterparty's CA certificate into Mirth's truststore:

keytool -importcert \
  -alias partner-ca \
  -file partner-root-ca.pem \
  -keystore /opt/mirthconnect/conf/truststore.p12 \
  -storetype PKCS12 \
  -noprompt

6.2 Send side — present client certificate

On the outbound MLLPS destination, configure Mirth to present its client cert. Typically this uses the same keystore as the server side (a single certificate serving both roles) or a dedicated client-cert keystore.

6.3 Verify mTLS end-to-end

# Client-side probe presenting a client cert
openssl s_client -connect mirth-host:6661 \
  -cert client.pem -key client.key \
  -CAfile server-ca.pem

# Expect: handshake succeeds, certificate chain shown

Without -cert, the handshake should fail with a client certificate required error. If it succeeds, mTLS is not actually enforced — go back and fix the listener configuration.

7. MLLPS Listener Hardening

Beyond protocol and cipher configuration, MLLPS listeners benefit from several additional hardening steps.

  • Bind to a specific interface — not 0.0.0.0 unless the listener must be universally reachable.
  • Source IP allowlist at the firewall — MLLPS listeners should not accept connections from the whole internet.
  • Connection rate limits — cap concurrent sessions per source IP. Stops resource-exhaustion attacks.
  • Logging enabled on handshake failures — failed TLS handshakes are a signal worth watching.
  • Certificate revocation checking — enable OCSP stapling or CRL checking if the counterparty PKI supports it.
  • Alert on repeat handshake failures — a sudden burst is worth investigating quickly.

See the MLLP connection refused guide for the adjacent debugging playbook when these listeners break.

8. HTTPS Listener Hardening

Mirth Connect exposes HTTPS for the Administrator and for REST API access. These endpoints need the same TLS hardening as MLLPS, plus HTTP-specific controls.

  • HSTS headerStrict-Transport-Security: max-age=31536000; includeSubDomains tells browsers to require HTTPS for future visits.
  • Secure cookies — set Secure and HttpOnly on all session cookies.
  • Disable HTTP entirely — no plain-HTTP listener for administrator traffic.
  • Restrict admin endpoint to management network — HTTPS on port 8443 should not be reachable from arbitrary networks.
  • Consider fronting with a reverse proxy — nginx or envoy in front of Mirth gives you better header control, rate limiting, and WAF options.
  • MFA at the admin gateway — either at an IdP (Okta/Azure AD) or at a bastion.

9. Certificate Rotation Automation

Expired certificates are the single most preventable cause of MLLPS outages we see. Automation is not optional once you have more than a handful of certificates.

9.1 Rotation checklist

  • Certificate inventory with expiration dates, aliases, hosts, owners
  • Automated alerts at 90, 60, 30, 7, 1 day before expiry
  • Automated renewal for internal CA certs via cert-manager, Vault, ACM, or equivalent
  • Pre-expiry test in staging — verify new cert works end-to-end before touching production
  • Automation to update keystore, restart relevant channels, verify handshake from sender
  • Rollback procedure tested — how to restore the previous certificate if the new one breaks
  • Communication plan — notify sender/receiver orgs before rotation if mTLS pinning is involved
  • Post-rotation verification — handshake probe from every sender host
  • Audit log entry for every rotation event
  • Annual end-to-end rehearsal of rotation procedure for each MLLPS interface

9.2 Example rotation script (sketch)

#!/usr/bin/env bash
set -euo pipefail

ALIAS="mirth-mllps"
KEYSTORE="/opt/mirthconnect/conf/keystore.p12"
PASS=$(vault kv get -field=password secret/mirth/keystore)
NEW_CERT="/tmp/new-mirth-mllps.pem"
BACKUP_SUFFIX=$(date +%Y%m%d-%H%M%S)

# 1. Backup existing keystore
cp "$KEYSTORE" "$KEYSTORE.bak.$BACKUP_SUFFIX"

# 2. Import new cert (renewed from CA)
keytool -importcert \
  -alias "$ALIAS" \
  -file "$NEW_CERT" \
  -keystore "$KEYSTORE" -storetype PKCS12 \
  -storepass "$PASS" -noprompt

# 3. Restart only the affected channels via Mirth REST API
curl -sS -X POST --cacert /etc/pki/mirth-api-ca.pem \
  -u "$API_USER:$API_PASS" \
  "https://mirth-host:8443/api/channels/<channel-id>/_redeploy"

# 4. Verify handshake from a known client
echo | openssl s_client -connect mirth-host:6661 \
  -CAfile /etc/pki/root-ca.pem \
  -servername mirth.example.org 2>/dev/null \
  | openssl x509 -noout -subject -enddate

In production we layer this into cert-manager (Kubernetes) or HashiCorp Vault PKI (bare metal / VMs) so rotation happens on schedule without human action. Any automation you build should include a rollback path — if verification fails, restore the previous keystore from backup.

10. JVM Tuning for TLS

TLS operations are CPU-intensive. On high-volume MLLPS listeners, a few JVM tweaks improve both throughput and security posture.

10.1 Enable hardware AES acceleration

-XX:+UseAES
-XX:+UseAESIntrinsics

These are default on modern JVMs, but verify with java -XX:+PrintFlagsFinal -version | grep AES. Most production CPUs support AES-NI — Mirth should use it.

10.2 Session ticket and cache tuning

-Djavax.net.ssl.sessionCacheSize=20480
-Djdk.tls.ephemeralDHKeySize=2048

Larger session cache reduces full handshakes when many senders reconnect periodically. Ephemeral DH size 2048 is the safe default; some legacy partners still need 1024 but that's increasingly rare.

10.3 Entropy source

# Linux: ensure /dev/urandom is used (default on modern JVMs)
-Djava.security.egd=file:/dev/./urandom

On older JVMs or certain Linux distributions, the default could be /dev/random which blocks on low entropy and causes TLS handshake stalls during boot or heavy load. Force /dev/urandom.

11. FIPS Mode and Compliance

FIPS 140-2 (and the newer 140-3) defines cryptographic module validation for U.S. federal use and some regulated industries. If your deployment must be FIPS-compliant, you need a FIPS-validated JCE provider and a JVM configured to use only FIPS-approved algorithms.

  • BouncyCastle FIPS — the most common provider for Java applications that need FIPS mode.
  • Vendor JDKs — some commercial JDKs ship with FIPS mode enabled via a configuration flag.
  • Red Hat OpenJDK — when running on a FIPS-enabled RHEL host, inherits FIPS from the OS.

FIPS mode restricts algorithms to the approved set, which can break some older integration partners. Test thoroughly. Validate with tooling that confirms the JVM is operating in FIPS mode before relying on it for compliance claims.

Most HIPAA deployments do not require FIPS. Confirm with your compliance team before enabling it — FIPS adds complexity without always adding defensible protection for non-federal environments.

12. Testing Your TLS Configuration

Tooling we use after every change:

12.1 openssl s_client

# Basic handshake probe
openssl s_client -connect mirth-host:6661 -tls1_2

# With SNI (if the listener uses name-based virtual hosting)
openssl s_client -connect mirth-host:6661 -servername mirth.example.org

# Probe a specific cipher
openssl s_client -connect mirth-host:6661 \
  -cipher 'ECDHE-RSA-AES256-GCM-SHA384'

12.2 nmap ssl-enum-ciphers

nmap --script ssl-enum-ciphers -p 6661 mirth-host

# Output shows every protocol and cipher the server accepts, with grades

12.3 testssl.sh

./testssl.sh --severity HIGH mirth-host:6661
# Comprehensive report — protocols, ciphers, vulnerabilities, cert details

12.4 Synthetic MLLPS heartbeat

#!/usr/bin/env bash
# Send a framed HL7 heartbeat over MLLPS and check for ACK
printf '\x0bMSH|^~\\&|MON|MON|TEST|TEST|20260421000000||ADT^A01|HB1|P|2.5\rEVN|A01|20260421000000\x1c\r' \
  | openssl s_client -connect mirth-host:6661 \
      -cert client.pem -key client.key \
      -quiet -servername mirth.example.org 2>/dev/null \
  | grep -q 'AA' && echo OK || echo FAIL

Run this synthetic check from your monitoring system every few minutes. Any failure immediately alerts on-call — which catches expiration, cipher regressions, and listener failures long before upstream senders notice.

13. Frequently Asked Questions

What TLS version should Mirth Connect use in 2026?

TLS 1.2 is the minimum you can defend in an audit; TLS 1.3 is preferred where both sides support it. SSLv3, TLS 1.0, and TLS 1.1 are deprecated by NIST, PCI, and every modern standard — disable them unconditionally. Many older integration partners still require TLS 1.2, so that's your production default.

How do I disable TLS 1.0 and 1.1 in Mirth Connect?

Set -Djdk.tls.client.protocols=TLSv1.2,TLSv1.3 and -Djdk.tls.server.protocols=TLSv1.2,TLSv1.3 in mcserver.vmoptions. Also set jdk.tls.disabledAlgorithms in java.security to explicitly block TLSv1 and TLSv1.1. Restart Mirth and test from a client that can negotiate only the old protocols — the handshake should fail.

Should I use JKS or PKCS12 keystores for Mirth?

PKCS12 is the modern default on Java 9+ and what we recommend for new deployments. JKS still works for existing keystores but is Java-specific, harder to interoperate with non-Java tooling, and considered legacy. Convert old JKS keystores to PKCS12 with keytool -importkeystore during any scheduled rotation.

Do I need mTLS for MLLPS in production?

Strongly recommended for any MLLPS interface crossing trust boundaries — between organizations, between clouds, across the public internet. mTLS ensures both sides authenticate before any HL7 data flows, which blocks entire classes of attacks that one-way TLS still allows. Internal intranet MLLPS on a fully controlled network can be one-way TLS if the threat model allows.

What cipher suites should I allow on Mirth MLLPS listeners?

AEAD ciphers only: AES-GCM and ChaCha20-Poly1305. Prefer ECDHE key exchange for forward secrecy. Avoid CBC ciphers unless you have a specific partner compatibility need. TLS 1.3 ciphers are limited to three AEAD choices by design — that's a good thing.

How do I rotate the Mirth keystore password?

keytool -storepasswd -keystore keystore.jks -storepass OLD -new NEW. Then update wherever Mirth references the password (channel config or secrets store), and restart. Rotate the password whenever an admin with knowledge of it leaves, on a fixed annual cadence, and after any suspected compromise.

Can I use Let's Encrypt certificates with Mirth Connect?

Yes for HTTPS Administrator and REST API endpoints, where the short 90-day lifetime is fine if your renewal automation is solid. For MLLPS certificates exchanged with external partners, most organizations prefer longer-lived certs from an internal CA or a commercial CA — the partner's trust store update cycle is usually the limiting factor, not your renewal preference.

What is FIPS 140-2 / 140-3 compliance and do I need it?

FIPS-validated cryptographic modules are required for federal agencies and their contractors, and for some state-level healthcare programs. Mirth Connect itself doesn't ship a FIPS-validated module; you enable FIPS mode at the JVM level using a FIPS-validated JCE provider (BouncyCastle FIPS, or a vendor-specific provider) and ensure every TLS operation uses it. Confirm your specific compliance requirement before engaging — not every healthcare org needs FIPS.

How do I test my Mirth TLS configuration?

Three tools: openssl s_client for basic probes and cipher negotiation, nmap with the ssl-enum-ciphers script to enumerate what's offered, and testssl.sh for a comprehensive posture report. For internal use we also build a simple synthetic check that connects, completes the handshake, sends a framed MLLP heartbeat, and verifies the ACK — any failure pages on-call.

Why does my TLS handshake fail after a JVM upgrade?

JVM updates sometimes change default protocols, ciphers, or algorithm restrictions. A common case is jdk.tls.disabledAlgorithms being tightened to exclude 1024-bit RSA or SHA-1 — working certificates suddenly fail validation. Read the release notes before any JVM upgrade, test in staging, and adjust java.security if you have legacy partner requirements you can't yet migrate off.

Related Reading

Need hardened TLS on your Mirth stack?

We harden Mirth Connect TLS end-to-end — protocol enforcement, cipher allowlists, PKCS12 migration, mTLS with partners, certificate rotation automation — as a fixed-scope engagement. Typical timeline: 1–2 weeks, documented configuration and runbooks at handover.

  • Every TLS control applied the same way on every Mirth host
  • mTLS configuration with partner organizations included
  • Cert-manager or Vault PKI rotation automation on request
  • Audit-ready documentation of final TLS posture
Contact Us

Tell us about your TLS posture

How many Mirth hosts, how many interfaces, where you are today, and what audit or partner requirement you're working toward. We'll come back with a tailored scope.

What is 2 + 2 ?