Pillar guide · SECURITY · 26 min read

TLS and HTTPS: A Complete Guide

How encryption protects the web, what every cert type does, and how to deploy modern TLS

TLS and HTTPS: A Complete Guide
Illustration · HostDir Editorial

TLS encrypts HTTP traffic to create HTTPS, replacing insecure plaintext HTTP. This guide covers TLS 1.2 versus TLS 1.3, the handshake reduction to one round trip, certificate types (DV, OV, EV), certificate authorities and the chain of trust, OCSP stapling, SNI with Encrypted Client Hello (ECH), the ACME protocol used by Let's Encrypt, and deployment practices such as HSTS and mTLS for service-to-service authentication.

What TLS does and why HTTPS replaced HTTP

Transport Layer Security, or TLS, is the protocol that turns plain HTTP into HTTPS. HTTP, defined in RFC 1945 (HTTP/1.0) and RFC 2616 (HTTP/1.1), sends data in cleartext over TCP. Any device between the client and server can read or modify that data. TLS adds three critical protections: encryption, authentication, and integrity.

Encryption scrambles the data so only the intended recipient can read it. TLS uses symmetric encryption (e.g., AES-256-GCM) with per-session keys negotiated during the handshake. Authentication proves the server is who it claims to be. This is done using X.509 certificates, which bind a public key to a domain name, verified by a certificate authority such as Let's Encrypt or DigiCert. Integrity ensures data has not been tampered with in transit, using message authentication codes (HMACs) or authenticated encryption modes (AEAD).

Why did we need to replace HTTP? The early web was designed for sharing academic documents, not for commerce or private communication. As banking, shopping, and personal messaging moved online, the lack of protection became a liability. Without TLS, attackers can perform session hijacking (e.g., Firesheep in 2010), inject malicious content, or steal credentials via packet sniffing. The IETF community and browser vendors pushed for widespread adoption of HTTPS. Google began using HTTPS as a ranking signal in 2014, and by 2018, Chrome marked all HTTP pages as "Not Secure" (Chrome 68).

TLS itself has evolved. The first version, SSL 2.0 (1995, RFC 6176 obsoletes it), was flawed. SSL 3.0 (1996) was replaced by TLS 1.0 (1999, RFC 2246), which itself was succeeded by TLS 1.1 (2006, RFC 4346), TLS 1.2 (2008, RFC 5246), and TLS 1.3 (2018, RFC 8446). Each version improved security and performance. Today, TLS 1.2 and 1.3 are the only recommended versions; SSL 2.0, 3.0, and TLS 1.0/1.1 have been deprecated (see RFC 8996).

HTTPS is not a separate protocol. It is HTTP over TLS, typically using port 443 instead of port 80. The URI scheme https:// tells the client to start a TLS handshake before sending any HTTP request. This combination provides confidentiality, authenticity, and integrity for the entire HTTP exchange, including request headers, cookies, and the response body.

TLS 1.2 vs TLS 1.3, what actually changed

When TLS 1.3 was published as RFC 8446 in August 2018, it was the first major revision of the protocol in a decade. TLS 1.2 (RFC 5246, 2008) had served well, but by 2018 the security community had identified structural weaknesses that could not be fixed with a minor patch. TLS 1.3 is not backward compatible with 1.2. The two versions share almost no wire format. The changes are deep, and they matter for every deployment.

The handshake goes from two round trips to one

The most visible change is latency. A full TLS 1.2 handshake requires two round trips (2-RTT) before the client can send encrypted application data. TLS 1.3 cuts that to one round trip (1-RTT) for a fresh connection, and zero round trips (0-RTT) for a resumed session. This is not a tweak to the existing flow. TLS 1.3 redesigned the handshake so the client sends its key share in the ClientHello, and the server can respond with its finished message and the server certificate in a single flight. The cryptographic negotiation happens in parallel, not sequentially.

Removed: static RSA, RC4, 3DES, CBC mode, compression, renegotiation

TLS 1.2 supported a sprawling menu of cipher suites and extensions. Many of them were dangerous. TLS 1.3 removed every cipher suite that relied on static RSA key exchange, which offered no forward secrecy. It removed RC4, 3DES, and all CBC-mode ciphers. It removed compression (CRIME attack) and renegotiation (a source of client-side confusion attacks). The result is a small, curated set of cipher suites: only AEAD ciphers with forward-secret key exchange. As of 2024, the recommended suites are TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, and TLS_CHACHA20_POLY1305_SHA256.

The key exchange is now always ephemeral Diffie-Hellman

In TLS 1.2, the server could choose between RSA key transport and ephemeral Diffie-Hellman (DHE or ECDHE). Many servers stayed with RSA because it was simpler. TLS 1.3 mandates ephemeral Diffie-Hellman for every handshake. The server's certificate is used only for signing the key exchange, not for encrypting the premaster secret. This guarantees forward secrecy: if the server's private key is stolen later, past sessions cannot be decrypted.

Signature algorithms and the downgrade protection mechanism

TLS 1.3 removed support for SHA-1 and MD5-based signatures. The server's certificate must use a signature algorithm that the client considers acceptable, and the CertificateVerify message is signed with the same algorithm. The protocol also includes a server-side downgrade signal: the server embeds a specific byte pattern in the ServerHello random field. If a TLS 1.3 client sees that pattern in a TLS 1.2 response, it knows a downgrade attack is in progress and aborts the connection.

Encrypted handshake messages

In TLS 1.2, the server certificate and the CertificateVerify message were sent in cleartext. An observer could see the server name, the certificate issuer, and the public key. TLS 1.3 encrypts the server certificate and the Finished message after the key exchange is complete. The ClientHello and ServerHello remain in cleartext, but everything after the key agreement is encrypted. This is a significant privacy improvement for passive network observers.

What this means for deployment

If you are running a web server in 2025, you should disable TLS 1.0 and 1.1 entirely. They are prohibited by PCI DSS and most browser vendors. TLS 1.2 should remain enabled for compatibility with older clients (Android 4.x, Windows 7 without updates, some embedded devices). TLS 1.3 should be the preferred version. Modern web servers like Nginx 1.25+, Apache httpd 2.4.38+, and Caddy enable TLS 1.3 by default. The configuration change is usually a single line: ssl_protocols TLSv1.2 TLSv1.3; in Nginx, or SSLProtocol +TLSv1.2 +TLSv1.3 in Apache.

How the TLS handshake works in one round trip

The TLS 1.3 handshake (RFC 8446) reduces the number of round trips from two to one for a fresh connection. In TLS 1.2, the handshake required two full round trips: one for the initial key exchange and another for the Finished messages. TLS 1.3 eliminates that second round trip by combining the key exchange and authentication into a single flight from the server.

The ClientHello and ServerHello

The client begins by sending a ClientHello message that includes a list of supported cipher suites, a random nonce, and a set of key share extensions (for Diffie-Hellman key exchange). Critically, the client selects one or more key exchange groups (e.g., X25519, secp256r1) and includes the corresponding public key shares in the initial message. This allows the server to compute the shared secret without an additional round trip.

The server responds with a ServerHello that picks a cipher suite and key share, then immediately sends an EncryptedExtensions block. The encryption key is already derived from the key exchange, so the server can start protecting data. The server also sends its certificate (unless using an out-of-band authentication mechanism), followed by a CertificateVerify message and a Finished message. All of these are encrypted under the handshake traffic key.

Single Flight from Server

After the client receives the server's flight, it can validate the certificate, verify the CertificateVerify signature, and check the Finished message. Then the client sends its own Finished message (encrypted) and begins sending application data. The entire exchange completes in one network round trip: the client sends the ClientHello, and the server replies with everything needed to start transmitting application data.

Key Derivation and 0-RTT

TLS 1.3 uses a simpler key derivation scheme based on HKDF (HMAC-based Extract-and-Expand Key Derivation Function). The shared secret from the ephemeral Diffie-Hellman exchange is fed into a key schedule that produces separate handshake and application traffic keys. The protocol also supports 0-RTT (zero round trip time) resumption, where a client that previously connected to a server can send encrypted application data in the same flight as the ClientHello. This uses a pre-shared key (PSK) established during the previous session. 0-RTT data requires careful replay protection, which is why it is often restricted to idempotent operations like HTTP GET requests.

Why It Matters

Eliminating one round trip has a dramatic effect on connection setup latency. For a user on a high-latency link (e.g., 200 ms RTT to a server in another continent), TLS 1.3 cuts the handshake delay from 400 ms to 200 ms. Combined with TCP Fast Open, a TLS 1.3 connection can be established in roughly the same time as a single TCP RTT. This is why modern HTTPS deployments exclusively use TLS 1.3 when supported.

Certificate types: DV, OV, EV, and why EV mostly died

Every TLS certificate is not the same. The difference comes down to how much identity verification a Certificate Authority (CA) performs before issuing the certificate. The industry settled on three levels: Domain Validation (DV), Organization Validation (OV), and Extended Validation (EV). Each step up the ladder requires more paperwork and costs more money, but the security benefit of that extra validation has been questioned for years.

Domain Validation (DV)

DV is the simplest and most common certificate type. The CA verifies that you control the domain name. That is it. No company name, no address, no legal entity check. Validation methods include placing a file at /.well-known/acme-challenge/, adding a DNS TXT record, or receiving an email at a well-known administrative address (like admin@example.com). Let's Encrypt issues only DV certificates, and they represent roughly 90% of all certificates issued on the web today. A DV certificate secures the connection. It does not tell the browser who runs the site.

Organization Validation (OV)

OV certificates add a step. The CA verifies the domain and also checks that the requesting organization is a registered legal entity. They look up business registries, call phone numbers listed for the company, and confirm the address. The resulting certificate includes the organization name in the Subject field. Users can see it by clicking the padlock in most browsers. OV certificates cost more and take days to issue. They are common for business websites that want to display a company name in the certificate details, though most users never look.

Extended Validation (EV) and its decline

EV was introduced in 2007 by the CA/Browser Forum (Baseline Requirements version 1.0). It required the most rigorous vetting: legal existence, physical address, phone verification, and a signed letter from a company officer. Browsers displayed the organization name in a green bar next to the URL. For a while, banks and e-commerce sites paid for EV certificates because the green bar was thought to signal trustworthiness.

That changed. In 2018, Chrome 68 began showing all HTTPS connections as secure, removing the green EV indicator. Firefox followed. The reasoning was sound: the green bar implied a level of security that the underlying TLS connection did not provide. EV does not make the encryption stronger. It does not prevent phishing. A phishing site can get a DV certificate just as easily as a real bank. The visual distinction misled users into believing EV sites were safer, when the real security was in the TLS handshake itself.

By 2020, Chrome stopped displaying the organization name in the address bar for EV certificates. Safari and Firefox had already dropped the green bar. Without the UI differentiation, the business case for EV collapsed. CAs still sell EV certificates, but adoption has plummeted. The CA/Browser Forum deprecated EV guidelines in 2022, effectively killing the standard.

What matters today

For almost every use case, a DV certificate is sufficient. The encryption is identical regardless of validation level. If your application needs to prove organizational identity, OV is the practical choice. EV offers no technical advantage. The industry has moved on to other trust signals, like Certificate Transparency logs and Expect-CT headers, which provide more meaningful security guarantees than a green bar ever did.

Certificate authorities, root stores, and the chain of trust

When your browser connects to a server over HTTPS, it does not just accept any certificate. It validates that the certificate was issued by a trusted Certificate Authority (CA). That validation depends on a chain of trust anchored by root certificates stored in your operating system or browser.

A CA is an organization that issues digital certificates. The CA signs a server's public key and identity information with its own private key. To be useful, the CA itself must be trusted. That trust is established by having the CA's own certificate (or a certificate from an intermediate CA that the CA controls) signed by a root CA whose certificate is included in a root store.

Root stores

A root store is a collection of trusted root certificates that ship with an operating system, browser, or device. Mozilla maintains its own root store (used by Firefox). Apple, Microsoft, and Google each maintain root stores for their platforms. As of 2024, the Mozilla root store contains about 140 root certificates from roughly 50 CAs. Each root store operator decides which CAs to include based on audits, policy compliance, and public accountability.

A root certificate is a self-signed certificate. It signs itself. There is no higher authority above it. The root's private key is kept offline, often in a hardware security module (HSM) in a physically secured facility. Compromising a root key would let an attacker issue fraudulent certificates for any domain, which is why root CAs rarely issue end-entity certificates directly.

Intermediate certificates

Instead of issuing server certificates from the root, CAs use intermediate certificates. The root signs one or more intermediate certificates, which then sign server certificates. This way the root's private key can remain offline, and if an intermediate is compromised, the CA can revoke that intermediate without replacing the root.

When a server presents its certificate, it should also send the intermediate certificate(s) that chain up to a root. The client (browser, OS, library) can then build the chain and verify each signature. The root does not need to be sent: it is trusted by inclusion in the root store. Verification follows RFC 5280, which defines path validation. Each certificate in the chain must be within its validity period, not revoked, and signed by the next certificate in the chain.

Trust anchors and self-signed certificates

If you operate a private CA for internal services, you add your own root certificate to every device's trust store. That root becomes a trust anchor. Without doing this, a self-signed certificate causes a browser warning: the chain of trust cannot be built because the root is unknown. For public HTTPS, you cannot use a self-signed certificate unless every client in the world adds your root, which is impractical. That is why you buy or obtain certificates from a CA whose root is already in the major root stores.

The chain of trust is what makes HTTPS work at scale. It does not require every client to know every server's public key. It only requires clients to know and trust about 140 root CAs. Those roots, in turn, delegate trust through intermediates to millions of individual servers.

OCSP, OCSP stapling, and how revocation actually works

A certificate is valid until its expiration date, unless it gets revoked before then. Revocation is the mechanism a certificate authority (CA) uses to declare a certificate invalid before its natural expiry. The most common reasons: the private key was compromised, the CA issued the certificate by mistake, or the domain owner changed and the old certificate should not be trusted.

The original revocation mechanism was the Certificate Revocation List (CRL), defined in RFC 5280. A CRL is a signed, timestamped list of serial numbers for revoked certificates, published by the CA at a regular interval (often hourly or daily). Clients download the CRL from a URL embedded in the certificate (the CRL Distribution Point, or CDP). The problem: CRLs grow large over time. A browser might have to fetch a multi-megabyte file before it can trust a certificate. That kills performance and, in practice, many browsers simply skip CRL checks for performance reasons.

OCSP: Online Certificate Status Protocol

OCSP (RFC 6960) replaced CRLs as the real-time check. Instead of downloading a list, the client sends a query to the CA's OCSP responder asking: "Is certificate serial number 0xDEADBEEF still valid?" The responder replies with a signed response: good, revoked, or unknown. The OCSP URL is placed in the certificate's Authority Information Access (AIA) extension. OCSP responses are small (a few hundred bytes) and can be cached by the client for a period specified in the response (the nextUpdate field).

OCSP has a critical privacy flaw: the CA learns exactly which certificates every client is checking, which reveals browsing history. It also introduces a dependency: if the OCSP responder is unreachable, the client has to decide whether to fail open (allow the connection) or fail closed (block it). Most browsers fail open, which defeats the purpose.

OCSP Stapling (RFC 6066, 6961)

OCSP stapling moves the revocation check from the client to the server. During the TLS handshake, the server fetches a signed OCSP response from the CA ahead of time (typically every few minutes) and "staples" it into the CertificateRequest or Certificate message. The client receives the stapled response, verifies the CA's signature on it, and never needs to contact the CA directly. This solves both the privacy problem (the CA sees only the server's IP, not every client) and the availability problem (the client doesn't need to reach the CA at all).

Stapling is defined in RFC 6066 (TLS extensions) and extended in RFC 6961 (multiple certificate status requests). TLS 1.3 makes stapling mandatory for servers that support it. The server sends a CertificateStatus extension in the handshake. The client checks that the stapled response covers the certificate being presented and that the response is fresh (within its nextUpdate window).

Must-Staple and the reality of revocation

A certificate can include the OCSP Must-Staple extension (defined in RFC 7633). When present, the client is told: "Do not accept this certificate unless the server staples a fresh OCSP response." This forces the server to keep a current OCSP response or the connection fails. Let's Encrypt and other CAs support Must-Staple.

Despite these mechanisms, revocation has never worked reliably at scale. A 2021 study by Korzh et al. found that fewer than 10% of TLS connections actually verify revocation status. Browsers like Chrome have moved to CRLsets (small, frequently updated lists of high-value revocations pushed to the browser binary) because OCSP checks were too slow and unreliable. Firefox uses a similar approach with OneCRL. For most web traffic, revocation is a best-effort check, not a hard enforcement. The practical advice: deploy OCSP stapling on your servers, use Must-Staple certificates if your infrastructure can handle it, and accept that revocation is a weak link in the chain of trust.

SNI and Encrypted Client Hello (ECH)

When a TLS client connects to a server that hosts multiple domains on a single IP address, the server needs to know which certificate to present. Server Name Indication (SNI) solves this by letting the client include the target hostname in the TLS handshake. SNI was first defined in RFC 3546 in 2003 and updated in RFC 6066. Without SNI, every domain on a shared IP would need the same certificate, or the server would fall back to a default certificate which often triggers browser warnings.

The problem with SNI is that the hostname is sent in cleartext during the TLS handshake, before encryption begins. Anyone watching the network traffic can see www.example.com in the Client Hello message. This leaks the destination site, undermining the privacy that TLS is supposed to provide. ISPs, corporate firewalls, and adversaries can use SNI data to censor or monitor traffic. This is a known privacy weakness that has existed since SNI was introduced.

Encrypted Client Hello (ECH) replaces SNI encryption

Encrypted Client Hello (ECH) is a TLS extension designed to encrypt the entire Client Hello message, including the SNI, so that an on-path observer cannot see which hostname the client is connecting to. ECH was standardized in RFC 8871 (experimental) and later refined. It was previously called Encrypted SNI (ESNI) but was renamed to reflect that it protects more than just the SNI field.

ECH works by having the TLS server publish a public key (via DNS or HTTPS records). The client uses that key to encrypt the Client Hello, then sends it inside the TLS handshake. The server decrypts the inner Client Hello and proceeds with the handshake. If decryption fails, the server falls back to a shared "public name" which does not reveal the actual destination. This fallback prevents connection failures when ECH is misconfigured.

ECH requires TLS 1.3, because earlier versions do not support the necessary handshake structure. Deployment is still limited. As of early 2025, Cloudflare, Fastly, and some CDNs support ECH. Browsers like Chrome and Firefox have experimented with it behind flags. Adoption is slow because both client and server need updates, and the DNS records for the public key must be configured correctly.

For system administrators, enabling ECH means adding a HTTPS DNS record (type 65) containing the public key and the public name. For example, using Cloudflare's API you can enable ECH with a single toggle. Clients that support ECH will automatically encrypt their SNI; clients that do not support it fall back to plain SNI. ECH does not break existing monitoring tools that rely on SNI inspection, but those tools will see only the public name instead of the real hostname, which can complicate network policies.

Let's Encrypt and the ACME protocol explained

Before 2015, getting a TLS certificate meant paying a CA, filling out web forms, waiting hours or days, and manually installing files. Let's Encrypt changed that by offering free, automated, domain-validated certificates. It now issues over 300 million active certificates and accounts for more than half of all certificates on the web.

Let's Encrypt is a nonprofit CA operated by the Internet Security Research Group (ISRG). It validates domain control using the Automated Certificate Management Environment (ACME) protocol, defined in RFC 8555. ACME lets a client prove it controls a domain and then receive, install, and renew certificates without human intervention.

How ACME works

ACME uses a challenge-response model. The client requests a certificate for a domain, and the CA issues one or more challenges to prove domain ownership. The two standard challenge types are HTTP-01 and DNS-01.

HTTP-01 works like this: the CA tells the client to place a specific token at http://<domain>/.well-known/acme-challenge/<token>. The client puts the file there, and the CA fetches it over HTTP (not HTTPS, to avoid a chicken-and-egg problem). If the response matches, the CA issues the certificate. This challenge only works on port 80.

DNS-01 requires the client to create a TXT record at _acme-challenge.<domain> with a specific value. The CA queries the DNS and, if the record matches, issues the certificate. DNS-01 works for wildcard certificates and for servers that cannot listen on port 80.

A typical ACME session using certbot looks like this:

sudo certbot certonly --standalone -d example.com -d www.example.com

Certbot starts a temporary web server, completes the HTTP-01 challenge, and stores the certificate chain and private key in /etc/letsencrypt/live/example.com/.

Renewal and automation

Let's Encrypt certificates are valid for 90 days. Short lifetimes reduce the impact of key compromise and encourage automation. Most ACME clients include a cron job or systemd timer that checks for renewal twice a day. Certificates are renewed only when they have fewer than 30 days of validity left, which avoids hitting rate limits.

Rate limits are important. Let's Encrypt allows 50 certificates per registered domain per week, and 300 pending authorizations per account per week. The limits are generous enough for normal use but prevent abuse.

ACME v2 and the ecosystem

ACME v2 (RFC 8555) added support for wildcard certificates and improved the directory API. The protocol uses JSON over HTTPS, with JWS (JSON Web Signature) for authentication. Clients like certbot (Python), acme.sh (shell), and Lego (Go) all speak ACME v2.

Let's Encrypt relies on two root certificates: ISRG Root X1 (cross-signed by IdenTrust, trusted since 2018) and ISRG Root X2 (an ECDSA root, trusted since 2020). The CA's intermediate certificates are rotated periodically. Old intermediates expire, so clients must always fetch the current chain from the ACME endpoint.

Deploying modern HTTPS (HSTS, cipher suites, key types)

Getting modern HTTPS right means more than just installing a certificate. Three areas demand your attention: the HTTP header that forces encrypted connections, the cryptographic algorithms negotiated during the handshake, and the key material that authenticates your server.

HTTP Strict Transport Security (HSTS)

HSTS is defined in RFC 6797. The server sends a Strict-Transport-Security header that tells the browser: for the next max-age seconds, only connect to this domain over HTTPS. Any HTTP link or user-typed HTTP URL gets internally rewritten to HTTPS before a single packet leaves the machine. This prevents SSL stripping attacks where a man-in-the-middle downgrades a user from HTTPS to HTTP.

A minimal header looks like this:

Strict-Transport-Security: max-age=31536000

That is one year. Include includeSubDomains to cover all subdomains. For the first deployment, start with a short max-age (a few hours or days) to avoid locking out users if something breaks. Once you are confident, bump it to 31536000 and add the preload directive. You can then submit your domain to the HSTS preload list maintained by Chromium. After inclusion, browsers enforce HTTPS for your domain before ever seeing your header. This is a one-way operation: removal from the preload list takes months or years.

Cipher suites and TLS version configuration

Disable TLS 1.0 and TLS 1.1. Both are deprecated by RFC 8996 and removed from major browsers. TLS 1.2 and TLS 1.3 are the only acceptable versions.

For TLS 1.3, cipher suites are simple: you need TLS_AES_128_GCM_SHA256 and TLS_AES_256_GCM_SHA384. That is it. ChaCha20-Poly1305 is an alternative for mobile clients without AES hardware acceleration. There is no choice of key exchange or signature algorithm within TLS 1.3 that you can tune at the cipher suite level; those are negotiated separately.

For TLS 1.2, you need to be more deliberate. Modern cipher suites use AEAD (authenticated encryption with associated data). Prefer ECDHE-RSA-AES128-GCM-SHA256 or ECDHE-ECDSA-AES128-GCM-SHA256. Avoid CBC-mode ciphers and SHA-1 based suites. Drop all static RSA key exchange suites (those without ECDHE or DHE). Modern clients and servers should also support TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 if high performance on mobile CPUs matters.

Key types: RSA, ECDSA, and Ed25519

RSA keys still work but are increasingly a legacy choice. A 2048-bit RSA key is the minimum for server certificates. 4096-bit keys impose a noticeable performance cost on the TLS handshake because the entire public key must be transmitted and processed during certificate verification. ECDSA keys using the P-256 curve (secp256r1) give equivalent security to a 3072-bit RSA key with a much smaller payload (65 bytes for the public key versus 294 bytes for RSA 2048). That reduction saves round-trip time on latency-sensitive connections.

Ed25519 is an Edwards-curve signature scheme defined in RFC 8032. It offers fast signing, small keys (32 bytes), and constant-time operation, which reduces side-channel attack surface. OpenSSL 1.1.1 and later support Ed25519. Not all Certificate Authorities issue Ed25519 certificates today, so check your CA's supported algorithms before committing.

If you have full control over your client base (internal services, mobile apps you ship), use ECDSA P-256 or Ed25519. If you serve the general web, you can dual-stack: publish two certificates for the same domain, one RSA and one ECDSA. The server selects the best match based on the client's signature_algorithms extension during the TLS handshake. Mozilla's SSL Configuration Generator at ssl-config.mozilla.org outputs safe configurations for nginx, Apache, HAProxy, and other servers.

mTLS for service-to-service authentication

Mutual TLS (mTLS) flips the usual TLS authentication model. In standard HTTPS, only the server presents a certificate to prove its identity. The client, usually a browser, does not present a certificate. mTLS requires both sides to present and validate certificates during the handshake. The client proves its identity to the server, and the server proves its identity to the client. This is why it is often called two-way TLS or mutual authentication.

mTLS is widely used for machine-to-machine communication in zero-trust networks, microservice architectures, and API gateways, especially within Kubernetes and service mesh environments like Istio, Linkerd, and Consul Connect. In those setups, every service sidecar proxy terminates TLS and enforces mTLS between all pods.

The handshake difference is small but critical. In a standard TLS 1.3 handshake, after the server sends its Certificate and CertificateVerify messages, it sends a Finished message. In mTLS, the server then sends a CertificateRequest message before its Certificate message. This request tells the client to present its own certificate. The client responds with its Certificate, a CertificateVerify, and an optional CertificateStatus (for OCSP stapling of the client certificate). The server validates the client certificate against a configured trust store, which is a list of allowed CA certificates or pinned leaf certificates.

Where do the client certificates come from? For internal services, you can run your own private CA using tools like cfssl, step-ca (Smallstep), or Vault PKI (HashiCorp). Each service instance gets a short-lived certificate, often with a 24-hour TTL, and rotates it automatically. The ACME protocol (RFC 8555) can also issue client certificates if the CA supports the right profile.

Key configuration details matter. For NGINX, you enable mTLS with ssl_client_certificate /path/to/ca.pem and ssl_verify_client on;. For HAProxy, you set verify required in the bind line. In Envoy, the config lives under tls_certificates and validation_context in the upstream and downstream TLS contexts.

mTLS does not replace application-level authentication. It handles transport-layer identity. After the TLS connection is established, the application still needs to enforce authorization, typically by extracting the client certificate's Subject or SAN from the TLS session (e.g., the X509_SAN header in NGINX). Never rely solely on the fact that a connection is mTLS enabled. The client certificate identity must map to an authorized service role.

Performance cost is real but small. The extra certificate exchange adds roughly one round trip. Certificate validation adds CPU time but less than asymmetric key operations for session key exchange. In practice, the overhead is negligible compared to the security gain in a multi-service environment.

A common mistake is using the same CA and trust store for both client and server certificates. That creates a situation where any compromised service can impersonate any other service. Use separate CA hierarchies or at least separate trust anchors for clients and servers. Pin intermediate CAs per role.

Frequently asked questions
What is the difference between TLS and SSL? Read

SSL (Secure Sockets Layer) was the original protocol, with versions 2.0 and 3.0. TLS (Transport Layer Security) is the successor starting with RFC 2246 in 1999, effectively SSL 3.1. All SSL versions are deprecated. TLS 1.3 from RFC 8446 (2018) is the current standard. The term 'SSL' is often used informally to mean TLS, but the protocol running today is always TLS.

Why does TLS 1.3 have only one round trip in the handshake? Read

TLS 1.3 reduced the handshake from two round trips to one by sending the client's key share in the very first ClientHello message. This uses the Diffie-Hellman ephemeral (DHE) key exchange pre-negotiated via supported groups. The server responds with its key share and finished messages. This design also removes older, insecure features like static RSA key exchange and renegotiation.

What is the actual difference between DV, OV, and EV certificates? Read

A DV (Domain Validation) cert only proves control of the domain via email or DNS. An OV (Organization Validation) cert adds checks against business registries, so the Subject field includes the company name. An EV (Extended Validation) cert required a more rigorous audit, but as of 2024, both Chrome and Safari no longer display the EV green bar or company name differently from DV. All three use the same X.509 standard and offer identical encryption; the difference is only in the vetting level.

How does OCSP revocation actually work and what is stapling? Read

OCSP (Online Certificate Status Protocol, RFC 6960) lets a client query the CA for a certificate's revocation status. The client sends a request containing the serial number to the CA's OCSP responder. Stapling (RFC 6066) has the server fetch that OCSP response ahead of time and include it ('staple') in the TLS handshake. The client then trusts the server-provided response, reducing latency and removing the CA as a privacy leak.

What is Server Name Indication (SNI) and why do we need Encrypted Client Hello? Read

SNI is a TLS extension that lets the client send the hostname it wants to reach in the ClientHello, so the server can send the correct certificate when hosting multiple domains on a single IP. This hostname is sent in cleartext, visible to network observers. Encrypted Client Hello (ECH) encrypts the entire ClientHello, including SNI, using a public key from the server's DNS record. ECH is specified in RFC 8871 and prevents censorship and traffic analysis based on the target domain.

How does Let's Encrypt automate certificate renewal? Read

Let's Encrypt implements the ACME protocol (RFC 8555). The client software (like Certbot) generates a key pair and proves domain control by placing a token at a well-known HTTP URL or in a DNS TXT record. The CA verifies the token, then signs and issues the certificate. Certificates expire after 90 days, and the ACME client automatically renews by repeating this challenge before expiry. The entire process runs on port 80 (HTTP-01) or port 53 (DNS-01) with no human interaction.

What is mTLS and when would I use it? Read

Mutual TLS (mTLS) is TCP-1503 authentication where both the client and server present X.509 certificates during the handshake. In standard HTTPS, only the server sends a certificate. In mTLS, the server sends a CertificateRequest message, and the client responds with its own certificate. The server validates that client certificate against a trusted CA or a whitelist. mTLS is used for service-to-service authentication in microservices, IoT device connections, and API gateways.

Glossary terms used in this guide
TLS 1.3 ACME protocol X.509 OCSP stapling Encrypted Client Hello (ECH) HSTS Certificate authority (CA) Mutual TLS (mTLS) Diffie-Hellman key exchange DNSSEC
Put this guide to work Where the practical stuff lives

Browse providers

Continue reading
NETWORKING · Updated Jun 2026

BGP: A Complete Guide to Border Gateway Protocol

How the internet's routing protocol works, why it matters, and what every network operator should know

RFC grounded
INFRASTRUCTURE · Updated Jun 2026

Kubernetes for sysadmins: when it is worth it, and when it is not

An honest reference for engineers who run servers today, written from outside the Kubernetes evangelism circle. What K8s actually buys you, what it does not, and the alternatives that deserve consideration first.

RFC grounded
DOMAINS · Updated Jun 2026

Domain Names: A Complete Guide

How domains work, what gTLD vs ccTLD really means, and how to pick and protect one

RFC grounded
HOSTING · Updated Jun 2026

Web Hosting: A Complete Guide for Buyers

How shared, VPS, dedicated, cloud, and managed hosting differ, and how to choose

RFC grounded

Who Is Online

In total there are 64 users online: 0 registered, 56 guests and 8 bots.

Most users ever online was 5,555 on 17 Jul 2026, 3:23 am.

Bots: AhrefsBot Applebot Baiduspider Bingbot Other Bot Other Crawler PetalBot SemrushBot

Users active in the past 15 minutes. Total registered members: 369