Stage 3 · Build
TLS & Certificate Management
Mutual TLS (mTLS)
Client certificates, service mesh mTLS, and zero-trust networking.
What is mTLS?
In standard TLS, only the server proves its identity — the client trusts whoever connects. Mutual TLS (mTLS) requires both sides to present certificates. The server verifies the client, and the client verifies the server. This is the foundation of zero-trust networking.
| Aspect | Standard TLS | Mutual TLS |
|---|---|---|
| Server authentication | Yes | Yes |
| Client authentication | No | Yes (certificate) |
| Use case | Public websites | Service-to-service, API auth |
| Who verifies whom | Client verifies server | Both verify each other |
mTLS Handshake Differences
Client Server
|--- ClientHello ------------------>|
|<-- ServerHello -------------------|
|<-- CertificateRequest ------------| <-- NEW in mTLS
|<-- Certificate -------------------|
|<-- CertificateVerify -------------|
|<-- ServerHelloDone ---------------|
|--- Certificate ------------------>| <-- NEW in mTLS
|--- CertificateVerify ------------>| <-- NEW in mTLS
|--- ClientKeyExchange ------------>|
|--- Finished --------------------->|
|<-- Finished ----------------------|The key difference is the CertificateRequest from the server and the client's Certificate + CertificateVerify response. The server sends which CAs it trusts, and the client must present a certificate signed by one of those CAs.
Client Certificate Configuration
# Generate client certificate
openssl req -new -newkey rsa:2048 -nodes \
-keyout client-key.pem -out client.csr
# Sign with your CA
openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out client.pem -days 365
# Test with curl
curl --cert client.pem --key client-key.pem --cacert ca.pem \
https://internal.example.comFor testing, self-signed certificates work. In production, use an internal CA (cfssl, Vault) to sign client certificates. The CA certificate must be configured on the server as a trusted CA.
server {
listen 443 ssl;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
# mTLS configuration
ssl_client_certificate /etc/nginx/ca.crt;
ssl_verify_client on;
ssl_verify_depth 2;
# Pass client cert info to backend
proxy_set_header X-Client-Cert $ssl_client_s_dn;
proxy_set_header X-Client-Cert-Verify $ssl_client_verify;
}ssl_verify_client on enables mTLS. The server verifies the client certificate against ssl_client_certificate (your CA). The X-Client-Cert header passes the client identity to the application.
Service Mesh mTLS
Service meshes like Istio and Linkerd automate mTLS between all services. Every pod gets an identity certificate. The mesh proxy (sidecar) handles certificate rotation, verification, and encryption transparently.
# Enforce mTLS for all services in the mesh
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT
# Allow permissive mode during migration
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: PERMISSIVE # accepts both mTLS and plain traffic
# Check mTLS status
istioctl x describe pod <pod-name>
istioctl proxy-config secret <pod-name>Istio uses SPIFFE identities for each workload. Certificates are automatically rotated by the Istiod control plane. The sidecar proxy intercepts all traffic and negotiates mTLS without application changes.
Zero-Trust with mTLS
Zero-trust networking assumes no implicit trust — every connection must be authenticated and authorized. mTLS provides the authentication layer: every service proves who it is before any data flows.
Traditional (perimeter security):
[External] --firewall--> [Internal network: trust everyone]
Zero-trust:
[Service A] --mTLS--> [Service B]
(A proves identity to B, B proves identity to A)
(Every connection authenticated, every request authorized)In zero-trust, there is no trusted internal network. Every service-to-service call requires authentication (mTLS) and authorization (policy). This limits lateral movement if an attacker compromises a service.
mTLS gives you cryptographic identity for workloads. This is more reliable than network-based identity (IP addresses can be spoofed). SPIFFE provides a standard identity framework that works across Kubernetes, VMs, and bare metal.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.