Skip to main content

• Updated

mTLS (Mutual TLS): How It Works, with Diagram

Mutual TLS (mTLS) is a security protocol that extends standard TLS by requiring both parties in a connection to authenticate each other using digital certificates. The server proves itself to the client, and the client proves itself right back.

This mutual authentication is what separates mTLS from standard TLS and makes it the dominant choice for securing machine-to-machine communication: microservices, API gateways, IoT devices, and zero trust architectures all rely on it.

What is TLS, and why isn’t it enough?

Before understanding mTLS, it helps to understand what standard TLS does, and what it leaves out.

TLS (Transport Layer Security) is the protocol that secures most internet traffic today. When your browser connects to https://ngrok.com, TLS is doing two things: authenticating the server (via its certificate) and encrypting the connection so nobody can read the data in transit.

That authentication is one-directional. The server proves its identity to you, but you don’t prove your identity to the server. For a public website, that’s fine: the server doesn’t need to know who you are just to serve a web page. Application-layer authentication (username and password) handles that.

For service-to-service communication, the situation is different. There’s no human logging in. Service A needs to know that the response it’s receiving is genuinely from Service B, not an attacker who has compromised the network and is intercepting calls. A shared secret or API key helps, but those can be stolen. A cryptographic certificate, backed by a trusted Certificate Authority, cannot be forged.

That’s the gap mTLS fills.

How does mTLS work?

The mTLS handshake extends the standard TLS handshake by adding a client certificate exchange step. Here’s the full sequence:

1. Handshake initiation

The client sends a ClientHello message to the server, advertising the TLS version and cipher suites it supports.

The server responds with a ServerHello and, critically, includes a CertificateRequest message asking the client to present its own certificate. This is the step that doesn’t exist in standard TLS.

2. Certificate exchange

The server sends its digital certificate to the client. This certificate contains the server’s public key and is signed by a Certificate Authority (CA) the client trusts.

The client then sends its own certificate to the server, containing the client’s public key, signed by a CA the server trusts.

3. Certificate verification

Both parties independently verify the other’s certificate:

  • The client checks the server’s certificate against its trusted CA list, verifying the signature, expiry date, and hostname.
  • The server checks the client’s certificate against its trusted CA list. If the client’s certificate isn’t valid or isn’t signed by a CA the server recognizes, the connection is rejected here, before any application data is sent.

This is where mTLS stops man-in-the-middle attacks. An attacker intercepting the connection cannot produce a valid certificate signed by your private CA without access to the CA’s private key.

4. Key exchange

Once both certificates are verified, the client and server use the exchanged public keys to derive a shared session key through a key agreement algorithm (typically ECDHE). Neither side transmits this session key directly. Each one computes it independently from the other’s public key and their own private key.

5. Encrypted communication

All subsequent data is encrypted using the shared session key. Even if someone intercepts the traffic, they cannot decrypt it without the private keys that were never transmitted.

The mTLS handshake diagram

The diagram below traces the same flow in six numbered steps: the hellos (1–2), the server’s certificate being verified by the client (3), the client’s certificate being verified by the server (4), the key exchange (5), and the encrypted session (6). Reading the flow this way makes the key point obvious: a client that can’t present a CA-signed certificate is rejected at step 4, before any application data moves.

Want to see this handshake succeed and fail for real? Skip to the hands-on walkthrough: you’ll generate a CA and client certificate, put an mTLS-protected endpoint in front of a local service, and watch curl get rejected without a certificate.

mTLS vs TLS: key differences

TLSmTLS
Who authenticatesServer onlyClient and server
Client certificate requiredNoYes
Protects against impersonationServer impersonation onlyBoth sides
Typical use caseBrowser to websiteService to service
Operational complexityLowHigher (certificate lifecycle)
Zero trust compatiblePartialYes

The core trade-off is complexity vs. assurance. Standard TLS is simpler to operate because only server certificates need managing. mTLS requires issuing, rotating, and revoking client certificates too, but in return you get cryptographic proof that both parties are who they claim to be.

mTLS authentication: how certificates work

The foundation of mTLS is X.509 digital certificates. Understanding these explains why mTLS is stronger than shared secrets or API keys.

Certificate Authorities (CAs) are the root of trust. A CA is an entity that issues certificates, signing each one with its private key to vouch for the certificate holder’s identity. In an mTLS setup, you typically run your own private CA, not a public CA like Let’s Encrypt, because you don’t want arbitrary clients on the internet to be able to obtain a certificate.

Certificate issuance works like this: a service generates a key pair (public + private), creates a Certificate Signing Request (CSR) containing its public key and identity information, and submits it to the CA. The CA verifies the identity and signs the certificate. The private key never leaves the service.

Certificate verification at handshake time asks: does this certificate chain back to a CA I trust? Is it expired? Has it been revoked?

Revocation is the Achilles heel of certificate-based auth. If a service’s private key is compromised, you need to revoke its certificate quickly. Two mechanisms handle revocation:

  • OCSP (Online Certificate Status Protocol) lets the verifier query the CA in real time for a certificate’s current status.
  • CRL (Certificate Revocation List) is a list of revoked certificates that the CA publishes and verifiers download periodically.

For production mTLS, automated certificate rotation, using short-lived certificates that expire every few hours or days, is increasingly preferred over revocation, because it limits the blast radius of a compromised key without depending on revocation infrastructure being available.

When to use mTLS

mTLS shines in environments where all participants are machines and you can control certificate issuance:

Microservices and service meshes. Service meshes like Istio and Linkerd use mTLS by default for all intra-cluster traffic. Every service gets a certificate, and mutual authentication happens transparently at the sidecar proxy layer.

API gateways. When your API gateway receives requests from partner services or internal clients, mTLS gives you cryptographic proof of which client is connecting. That’s stronger than API keys, which can be shared or leaked. See how ngrok works as an API gateway with mTLS for exactly this pattern.

Zero trust networks. Zero trust security assumes no implicit trust based on network location: every connection must be authenticated regardless of whether it’s internal or external. mTLS is the standard mechanism for enforcing this for machine identities.

IoT devices. Devices in the field can hold a certificate provisioned at manufacture time. When they connect home, mTLS verifies the device is genuine, not an attacker who has taken over the device’s IP address.

Webhooks and callbacks. If your service sends webhooks to customer endpoints, mTLS lets you verify the customer’s endpoint is authentic before sending sensitive data.

mTLS is generally not used for browser-to-server connections, because distributing client certificates to end users at scale is operationally difficult. For human-facing authentication, OAuth 2.0 and OpenID Connect are the standard choice.

mTLS challenges and limitations

Understanding the costs helps you decide when mTLS is worth it:

Certificate lifecycle management. Every service needs a certificate, and certificates expire. Automating issuance and rotation is critical, because manual certificate management at scale is a source of outages, not security.

Debugging. Encrypted connections with mutual auth are harder to inspect than plain HTTP. Tools like ngrok’s Traffic Inspector help here by capturing the decrypted request/response at the gateway layer before forwarding to your upstream.

CA infrastructure. Running a private CA requires operational care. Compromise of the CA’s private key means all certificates it has signed must be considered untrusted. Keep CA keys in a hardware security module (HSM) or a secrets manager with tight access controls.

Performance. The additional certificate verification during the handshake adds a few milliseconds of latency compared to standard TLS. For long-lived connections this is negligible; for high-frequency short-lived connections it can accumulate.

How to implement mTLS with ngrok

ngrok’s terminate-tls Traffic Policy action puts mTLS in front of any service without changing your application code. ngrok verifies the client certificate at its edge, rejects anything not signed by your CA, and forwards only authenticated traffic to your upstream. It’s the same building block behind ngrok’s secure customer connectivity, where mutual TLS authenticates both ends of a private link.

The whole thing takes about five minutes. You’ll need openssl, curl, and an ngrok account on the Pay-as-you-go plan, which is where mTLS is available. Its monthly fee counts as a credit against usage, so trying this costs effectively nothing.

1. Generate a CA and a client certificate

If you already run a private CA, skip this and use your existing CA certificate.

# CA private key and self-signed CA certificateopenssl genpkey -algorithm RSA -out ca.key -pkeyopt rsa_keygen_bits:2048openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt -subj "/CN=ExampleCA" # Client private key, signing request, and CA-signed client certificateopenssl genpkey -algorithm RSA -out client.key -pkeyopt rsa_keygen_bits:2048openssl req -new -key client.key -out client.csr -subj "/CN=ExampleClient"openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256

2. Write the Traffic Policy

Paste the contents of ca.crt into policy.yml. The second rule is optional: it passes the verified client’s identity to your upstream as a header, which ngrok does not do on its own.

on_tcp_connect:  - actions:      - type: terminate-tls        config:          mutual_tls_certificate_authorities:            - |-              -----BEGIN CERTIFICATE-----              <contents of ca.crt>              -----END CERTIFICATE-----on_http_request:  - actions:      - type: add-headers        config:          headers:            x-client-cn: "${conn.tls.client.subject.common_name}"

3. Start an mTLS-protected endpoint

Point ngrok at any local service, for example one on port 8080:

ngrok http 8080 --traffic-policy-file policy.yml

4. Test it

Use the URL ngrok prints. Without a client certificate, the handshake fails before any request reaches your service:

curl https://<your-ngrok-url>

With the certificate signed by your CA, the request goes through, and your service sees x-client-cn: ExampleClient:

curl --cert client.crt --key client.key https://<your-ngrok-url>

That’s mutual TLS end to end: your CA decides who gets in, and ngrok enforces it at the edge.

For uploading your CA to the dashboard instead of inlining it, matching on other certificate fields, and terminating mTLS at the agent instead of the edge, see the mTLS termination docs. To put mTLS in front of an API, see mTLS for API gateways.

Ready to try it? Create an ngrok account and you’ll have an mTLS-protected endpoint running in minutes.

Frequently asked questions

Avatar for Team ngrok

Team ngrok

This author has not provided a bio yet.

Share this post