TLS Protocol and Cipher Suite Hardening
Disable legacy protocols, configure strong cipher suites, and enable HSTS to secure your TLS configuration against downgrade attacks.
Why TLS 1.0 and 1.1 Must Be Disabled
TLS 1.0 was published in 1999 and TLS 1.1 in 2006. Both were formally deprecated by RFC 8996 in March 2021. Every major browser dropped support for these versions in 2020. There is no legitimate client that still requires them, and keeping them enabled exposes your server to well-documented attacks.
POODLE (CVE-2014-3566) exploits a design flaw in CBC padding used by SSL 3.0 and, in certain implementations, TLS 1.0. An attacker on the same network can force a protocol downgrade and then decrypt sensitive data one byte at a time. The attack is practical, not theoretical — it requires roughly 256 requests per byte of plaintext recovered.
BEAST (CVE-2011-3389) targets a predictable initialization vector weakness in TLS 1.0's CBC mode. It allows an attacker to recover HTTP cookies and session tokens from encrypted traffic. While browser-side mitigations exist, the only complete fix on the server side is to stop offering TLS 1.0 entirely.
Beyond these named attacks, TLS 1.0 and 1.1 permit cipher suites and constructions that have no place in a modern configuration: MD5-based MACs, static RSA key exchange without forward secrecy, and export-grade ciphers. Disabling these protocol versions eliminates the entire class of problems in one step. For a detailed look at how deprecated protocols persist and the real-world risks they create, see End-of-Life TLS: The Hidden Risk in Your Domain Configuration.
Recommended Protocol Versions
TLS 1.2 is the minimum acceptable version for production servers. It supports AEAD cipher suites (AES-GCM, ChaCha20-Poly1305) and ECDHE key exchange, which together provide authenticated encryption and perfect forward secrecy.
TLS 1.3 is the preferred version. It removed all legacy cipher suites, static RSA key exchange, and renegotiation. The handshake completes in one round trip instead of two, reducing latency. Every cipher suite in TLS 1.3 provides forward secrecy and uses AEAD construction by default — there is nothing to misconfigure.
Your server should offer both TLS 1.2 and TLS 1.3. Clients that support 1.3 will negotiate it automatically. The small number of clients limited to TLS 1.2 will still connect securely, provided your cipher suite list is properly configured.
Cipher Suite Configuration
For TLS 1.3, the cipher suites are fixed by the protocol specification. No server-side configuration is needed — all three standard suites (TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256) are strong.
For TLS 1.2, you must explicitly configure the server to use only strong suites. The guiding principles are:
- ECDHE key exchange only — provides perfect forward secrecy
- AEAD ciphers only — AES-128-GCM, AES-256-GCM, or ChaCha20-Poly1305
- No RC4, 3DES, DES, or export ciphers
- No CBC-mode ciphers unless you have a specific compatibility requirement
- No static RSA key exchange — it offers zero forward secrecy
Nginx
server {
listen 443 ssl;
server_name example.com;
ssl_protocols TLSv1.2 TLSv1.3;
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;
ssl_prefer_server_ciphers on;
ssl_certificate /etc/ssl/certs/example.com.pem;
ssl_certificate_key /etc/ssl/private/example.com.key;
}
For guidance on obtaining, renewing, and deploying those certificate files, see our TLS certificate management guide. Setting ssl_prefer_server_ciphers on ensures the server's cipher order takes priority over the client's preference. This prevents a client from selecting a weaker suite that your configuration permits but does not prefer.
Apache
<VirtualHost *:443>
ServerName example.com
SSLEngine on
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
SSLHonorCipherOrder on
SSLCertificateFile /etc/ssl/certs/example.com.pem
SSLCertificateKeyFile /etc/ssl/private/example.com.key
</VirtualHost>
The -all directive in SSLProtocol disables every protocol version first, then explicitly enables only TLS 1.2 and 1.3. This is safer than selectively disabling versions, because it protects against any future deprecated version being left on by default.
HSTS (Strict-Transport-Security)
Even with a fully configured HTTPS server, users who type example.com in their browser will first make an HTTP request. An attacker on the network can intercept this request and serve a spoofed HTTP version of the site, stripping the HTTPS upgrade entirely. This is the SSL stripping attack.
HSTS tells the browser to only connect over HTTPS, eliminating the HTTP window. Add this header to your HTTPS responses:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age=31536000 instructs the browser to enforce HTTPS-only access for one year (the minimum for preload eligibility). Once the browser sees this header, it will refuse to connect over HTTP for the duration.
includeSubDomains extends the policy to every subdomain. Without this, an attacker could target http://api.example.com or http://cdn.example.com even if the apex domain is protected.
preload signals that you intend to submit your domain to the HSTS preload list maintained by browser vendors. Once your domain is on this list, browsers enforce HTTPS from the very first visit — there is no initial HTTP request to intercept. Submit your domain at hstspreload.org after confirming your configuration meets all requirements.
Warning: HSTS preloading is difficult to reverse. If you add your domain to the preload list and later need to serve HTTP, removal takes months. Make sure HTTPS works correctly across all subdomains before enabling preload.
HTTP to HTTPS Redirect
HSTS only takes effect after the browser has seen the header at least once. You still need a server-side redirect to move HTTP visitors to HTTPS on their first visit.
Nginx
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Apache
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>
Use a 301 (permanent) redirect, not a 302 (temporary). A 301 tells browsers and search engines that the HTTP URL has permanently moved to HTTPS, which improves caching and SEO.
Testing Your Configuration
After making changes, verify that your server behaves as expected.
openssl s_client lets you test specific protocol versions from the command line:
# This should succeed (TLS 1.2)
openssl s_client -connect example.com:443 -tls1_2
# This should fail (TLS 1.1 disabled)
openssl s_client -connect example.com:443 -tls1_1
# Show negotiated cipher and protocol
openssl s_client -connect example.com:443 </dev/null 2>/dev/null | grep -E 'Protocol|Cipher'
If the TLS 1.1 connection succeeds, your protocol restriction is not applied correctly. Check that you reloaded the server configuration after editing.
SSL Labs (ssllabs.com/ssltest) provides a comprehensive online assessment. It grades your configuration from A+ to F, checks for all known vulnerabilities, and shows exactly which cipher suites your server accepts. Aim for an A or A+ rating. An A+ requires a valid HSTS header with a sufficient max-age.
CyberShield's TLS scan performs equivalent checks programmatically and integrates the results into your overall security posture score. It flags deprecated protocols, weak ciphers, missing HSTS, and certificate chain issues with severity-rated findings. For a full walkthrough of what an automated TLS assessment covers, read Beyond the Padlock: What a TLS Audit Actually Reveals.
Common Issues
Mixed content: Your pages load over HTTPS, but some resources (images, scripts, stylesheets) are loaded over HTTP. Browsers block or warn about this. Audit your HTML, CSS, and JavaScript for hardcoded http:// URLs. Use protocol-relative URLs or, better, fully qualified https:// URLs.
Cipher mismatch: The client and server cannot agree on a cipher suite. This usually means your cipher list is too restrictive for the connecting client, or the client is extremely old. Check your server logs for the failing client's User-Agent, and decide whether supporting that client is worth the security tradeoff.
Missing HTTP to HTTPS redirect: HSTS is configured, but there is no redirect on port 80. First-time visitors see a connection refused or an unsecured page. Always configure the redirect alongside HSTS.
HSTS header served over HTTP: The Strict-Transport-Security header must only be sent over HTTPS. Browsers ignore it on HTTP responses. Make sure the header is attached to your HTTPS virtual host, not the HTTP redirect block.
Certificate chain incomplete: The server sends the leaf certificate but omits the intermediate. Some clients (especially API clients and mobile browsers) fail to connect because they cannot build a trust path to a root CA. Use openssl s_client -connect example.com:443 -showcerts to verify the full chain is present.
Continue Reading
End-of-Life TLS: The Hidden Risk in Your Domain Configuration
Legacy TLS 1.0, TLS 1.1, and weak cipher suites persist across the internet despite formal deprecation. Learn why end-of-life TLS configurations remain dangerous, how to identify them, and how to migrate safely.
Beyond the Padlock: What a TLS Audit Actually Reveals
The browser padlock means your connection is encrypted — but encryption alone does not mean secure. Here's what a proper TLS audit examines.
Post-Quantum Cryptography: Is Your TLS Quantum-Safe?
NIST has finalized its first post-quantum cryptographic standards. With quantum computers threatening current encryption, organizations need to assess their TLS configurations now. Learn what post-quantum cryptography means for your external security.