Skip to content

SecurityPart of: SSL and HTTPS

TLS 1.2 vs 1.3: what changed, and turning TLS 1.0 and 1.1 off

TLS 1.3 is faster and simpler than TLS 1.2, and both are safe when configured well; TLS 1.0 and 1.1 are not. The differences, a 1.2-plus-1.3 config for every server, and how to prove the old versions are off.

getReport teamUpdated 27 Sept 202610 min read

TLS 1.3 differs from TLS 1.2 in three ways that matter to a site owner: the handshake needs one round trip instead of two, so connections start sooner; every weak option of 1.2 (RSA key exchange, CBC ciphers, SHA-1, renegotiation) is gone; and only 1.3 carries the post-quantum key exchange that current browsers now offer. TLS 1.2 is still safe with a modern cipher list, so the right setting today is both: TLS 1.2 as the minimum, TLS 1.3 enabled, and TLS 1.0 and 1.1 switched off. This guide compares the two, shows the config for each server, and how to check nobody you care about still needs the old versions. It is one of the checks in SSL/TLS checks that matter.

Quick answer

  • Accept TLS 1.2 and 1.3 only. nginx: ssl_protocols TLSv1.2 TLSv1.3;. Apache: SSLProtocol -all +TLSv1.2 +TLSv1.3. Caddy: the default. Cloudflare: SSL/TLS → Edge Certificates → Minimum TLS Version → TLS 1.2, and TLS 1.3 on.
  • Before switching off 1.0 and 1.1 on a server with devices or old integrations calling it, log the negotiated protocol for a week.
  • For TLS 1.2, keep only ECDHE with AES-GCM or ChaCha20-Poly1305 suites. TLS 1.3 suites need no tuning.
  • Prove it: openssl s_client -tls1_1 must fail against your host, and the SSL checker must report "The server only accepts TLS 1.2 or newer".

TLS 1.2 vs 1.3 at a glance

TLS 1.2 (RFC 5246, 2008)TLS 1.3 (RFC 8446, 2018)
Full handshake2 round trips1 round trip
Resumed connection1 round trip1, or 0 with early data (0-RTT)
Key exchangeRSA, static DH or (EC)DHE(EC)DHE only, so forward secrecy always
Ciphersdozens, including CBC, RC4, 3DESfive AEAD suites (AES-GCM, ChaCha20-Poly1305, AES-CCM)
Certificate in the handshakesent in clear textencrypted
Renegotiation, compressionallowedremoved
Post-quantum hybrid key exchangenoyes (X25519MLKEM768)
Needed forHTTP/2 (with a modern cipher)HTTP/3, Encrypted Client Hello

Speed. The saved round trip shows on every new connection: on a phone with 100 ms of latency, the page's first byte arrives about 100 ms sooner. 0-RTT early data goes further on repeat visits but can be replayed, so servers accept it only for safe requests; leave it off unless your stack handles that.

Security. A well-configured TLS 1.2 server is not broken. The risk is that TLS 1.2 allows weak choices a careless config still offers, while TLS 1.3 removed them from the protocol.

Post-quantum. Chrome (131 and later), Firefox (132 and later) and Apple's 26 releases offer the hybrid X25519MLKEM768 key exchange, which protects today's traffic against decryption by a future quantum computer. It exists only in TLS 1.3. Cloudflare's edge supports it, and servers built with OpenSSL 3.5 or later offer it with default settings.

Why turn off TLS 1.0 and 1.1

TLS 1.0 (1999) and 1.1 (2006) rely on constructions attacked in practice: CBC with a predictable IV (BEAST), MD5 and SHA-1 in the handshake, and no AEAD ciphers. A server that still offers them lets an attacker who can tamper with the connection try to push it down to the weak version.

The formal end came in three steps. Chrome, Firefox, Safari and Edge removed TLS 1.0 and 1.1 in 2020. The IETF deprecated both in RFC 8996 in March 2021. And PCI DSS, the card-payment rules, has prohibited "SSL and early TLS" since 30 June 2018, so a shop that accepts TLS 1.0 fails its scan.

Who still cannot speak TLS 1.2: Android 4.3 and older, Internet Explorer 10 and older, Windows XP, Java 6, and old payment terminals, printers, TVs and embedded devices that call a web service and were never updated. For a public website that is a rounding error; for an API that a device fleet calls, it is the thing to check before flipping the switch.

How getReport checks it

The checker makes two TLS handshakes, both with the hostname as SNI, and sends no application data. The first is modern, with TLS 1.2 as its minimum and HTTP/2 offered through ALPN; it records the negotiated protocol and cipher and reads the certificate. The second offers only TLS 1.0 and 1.1. If the server accepts it, the finding fails; if the server refuses, it passes. If the local OpenSSL policy refuses even to try, the finding is left out rather than guessed.

The evidence reads, for example, A TLS 1.0/1.1 handshake was accepted; a modern client negotiates TLSv1.3. A server that negotiates TLSv1.2 with a modern client has 1.3 off, which costs a round trip on every new connection.

The TLS result panel of the SSL / TLS checker with the protocol version row: the negotiated protocol and cipher, whether a TLS 1.0/1.1 handshake was accepted, the certificate chain result and the HSTS row, each marked pass, warn or fail
The protocol row shows what a modern client negotiates and whether the legacy handshake was accepted.

Re-read the next two findings after any TLS change, because the settings sit next to each other and a typo in one often breaks the other:

Step by step

1. Log the negotiated protocol for a week

nginx, in the http block:

nginx
log_format tls '$remote_addr [$time_local] "$request" $status '
               '$ssl_protocol $ssl_cipher "$http_user_agent"';
access_log /var/log/nginx/access.log tls;

Apache (mod_ssl):

Apache
LogFormat "%h %t \"%r\" %>s %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%{User-Agent}i\"" tls
CustomLog /var/log/apache2/access.log tls

Then count and list the user agents:

Shell
grep -c -E " TLSv1(\.1)? " /var/log/nginx/access.log
grep -E " TLSv1(\.1)? " /var/log/nginx/access.log | awk -F'"' '{print $6}' | sort | uniq -c | sort -rn | head

Scanners and bots will be most of them; look for a device or integration you recognise. Behind Cloudflare, the dashboard's analytics show traffic by TLS version with no server change.

2. Set the protocols and ciphers

Mozilla's SSL Configuration Generator maintains an "intermediate" profile for exactly this; the essentials:

nginx, in the http block so every server inherits it:

nginx
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

ssl_prefer_server_ciphers off lets a phone without AES hardware pick ChaCha20, which is faster for it. Run nginx -t, then reload.

Apache 2.4.36 or later with OpenSSL 1.1.1 or later, in the SSL virtual host (never .htaccess, because the protocol is negotiated before Apache knows the directory):

Apache
SSLProtocol         -all +TLSv1.2 +TLSv1.3
SSLCipherSuite      ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off
SSLSessionTickets   off

On an older Apache that rejects +TLSv1.3, use SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1, which gives TLS 1.2 only.

Caddy uses TLS 1.2 as its minimum and prefers 1.3 without configuration. Only add tls { protocols tls1.2 tls1.3 } if a previous admin lowered it.

Cloudflare: visitors negotiate with the edge, so its setting is what the checker sees. Cloudflare's documentation still lists TLS 1.0 as the default minimum, so set Minimum TLS Version to 1.2 and turn TLS 1.3 on. Your origin's own setting governs the Cloudflare-to-origin hop; set it too.

Hosting panels and load balancers: Plesk has "TLS versions and ciphers" under Tools & Settings; WHM sets Apache's SSLProtocol globally. AWS load balancers and CloudFront use named security policies (pick one with TLS13 in the name), Google Cloud an SSL policy with a minimum version, Azure Application Gateway an SSL policy. On shared hosting, ask support.

3. Keep weak ciphers out on purpose

The lists above contain only ECDHE or DHE key exchange with AES-GCM or ChaCha20-Poly1305. Keep out RC4, 3DES, every CBC suite, NULL, EXPORT and plain RSA key exchange (any suite without ECDHE or DHE). The TLS 1.3 suites are configured separately and are all AEAD, so these lists affect only 1.2.

A cipher list with no suite matching the certificate's key type makes every handshake fail; the lists include both ECDHE-RSA and ECDHE-ECDSA for that reason. If a change does break handshakes, browsers show ERR_SSL_PROTOCOL_ERROR.

Platform notes

Shopify, Wix, Squarespace, WordPress.com: the platform terminates TLS and has required 1.2 or newer for years. Run the checker to confirm. Self-hosted WordPress: the setting is on the web server, not in WordPress. Mail servers: Postfix (smtpd_tls_protocols) and Dovecot (ssl_min_protocol) have their own settings, and other mail servers negotiate with yours unattended, so log before tightening.

Verify

  1. Re-run the SSL checker: "The server only accepts TLS 1.2 or newer", with negotiated TLSv1.3 in the evidence.
  2. From a terminal:
Shell
# Expected: an error such as "alert protocol version" or "handshake failure"
openssl s_client -connect example.com:443 -servername example.com -tls1_1 </dev/null

# Expected: "Protocol : TLSv1.3" (and TLSv1.2 with -tls1_2)
openssl s_client -connect example.com:443 -servername example.com -tls1_3 </dev/null 2>/dev/null | grep -E "Protocol|Cipher"

If the first command prints no protocols available, your own OpenSSL refused to try, which says nothing about the server; add -cipher 'DEFAULT:@SECLEVEL=0' or rely on the checker.

  1. The site loads in every browser you support, checkout completes, and the integration you worried about in step 1 still works.

Common mistakes

  • ssl_protocols in one server block only. A forgotten virtual host on the same IP re-enables old versions. Set it in http.
  • Origin fixed, edge forgotten. Behind Cloudflare or a load balancer, the edge setting is what visitors and the checker see.
  • +TLSv1.3 on an Apache that does not support it. The config test fails and the old config keeps running. Read apachectl configtest.
  • Turning off 1.2 as well. TLS 1.3-only is possible, but some bots, corporate proxies and older clients still need 1.2. Keep it until your logs show otherwise.
  • Switching off 1.0 and 1.1 without the week of logs on a server that devices call. Log first, then switch, then watch the logs again.

Questions people ask

Is TLS 1.3 faster than TLS 1.2?

Yes, on new connections. A full TLS 1.3 handshake takes one round trip instead of two, so the first byte arrives one network round trip sooner, which matters most on high-latency mobile connections. Resumed connections are similar in both, unless you enable 0-RTT. Once the connection is open, encryption speed is the same, because both use the same AES-GCM and ChaCha20 ciphers.

Is TLS 1.2 still secure?

Yes, when it is configured with forward-secret ECDHE key exchange and AEAD ciphers (AES-GCM or ChaCha20-Poly1305). The weaknesses of TLS 1.2 come from optional features, such as CBC and RC4 ciphers or RSA key exchange, that a modern cipher list leaves out. PCI DSS and current IETF guidance accept it. Keep it next to TLS 1.3 for older clients.

Should I allow only TLS 1.3?

Not yet for a public website. Every current browser supports TLS 1.3, but some crawlers, monitoring services, corporate proxies and older libraries still connect with 1.2 only. Accepting TLS 1.2 with strong ciphers costs no security. Log the negotiated protocol for a few weeks; if 1.2 traffic is only bots you do not need, a 1.3-only internal service is reasonable.

Do all browsers support TLS 1.3?

All current ones do. Chrome and Firefox enabled TLS 1.3 by default in 2018, Safari in 2019 with iOS 12.2 and macOS 10.14.4, and Edge since its move to Chromium. Older operating systems and apps may only speak TLS 1.2, which is why servers keep 1.2 as the minimum rather than requiring 1.3.

Check your site before and after Check