Technical Deep-Dives

TLS Hardening Guide: Configuration Best Practices

TLS and SSL hardening guide: protocol versions, cipher suites, certificate management, security headers, OCSP stapling, and Nginx/Apache configs.

RG&T
Rathnakara GN & Theertha
Cybersecify
8 min read

Article 6 of 6: Understanding TLS Security Series

TLS hardening for 2026 means TLS 1.3 only (TLS 1.2 as fallback if legacy clients must be supported), AEAD cipher suites only (AES-256-GCM or ChaCha20-Poly1305), ECDSA P-256 certificates with automated 90-day rotation via ACME, HSTS with preload, OCSP stapling, and the complete set of security headers (X-Frame-Options, X-Content-Type-Options, Content-Security-Policy, Referrer-Policy). Maximum certificate validity drops to 200 days on March 15, 2026 and to 47 days by 2029, which makes ACME automation mandatory, not optional. Test SSL Labs after every configuration change; the goal is A+ with HSTS preload eligibility.

Key findings

  • TLS 1.3 only is the 2026 default. Keep TLS 1.2 enabled only if you measure legacy client traffic that requires it. Disable SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1 (deprecated per RFC 8996).
  • AEAD ciphers only. AES-256-GCM and ChaCha20-Poly1305 are the safe choices. Disable RSA key exchange (no forward secrecy), CBC mode (padding oracle attacks), 3DES (Sweet32), RC4 (broken), and all export ciphers (Logjam, FREAK).
  • Certificate lifetimes are shrinking. Maximum validity drops from 398 days to 200 days on March 15, 2026, then to 100 days on March 15, 2027, then to 47 days on March 15, 2029. Automate renewal via Let’s Encrypt and ACME now.
  • ECDSA P-256 is preferred over RSA 2048. Smaller signatures, faster handshake, equivalent security. Use Let’s Encrypt with certbot --key-type ecdsa --elliptic-curve secp256r1.
  • HSTS plus preload defeats SSL stripping on every connection including the first visit. Submit to hstspreload.org with max-age=31536000; includeSubDomains; preload.
  • OCSP stapling reduces revocation check latency and avoids leaking the client’s browsing history to the CA. Enable with ssl_stapling on; ssl_stapling_verify on; in Nginx.
  • Test SSL Labs after every change. A+ requires A grade plus HSTS with long max-age. Mozilla SSL Configuration Generator (ssl-config.mozilla.org) produces current Modern profile configs.

Cybersecify is a founder-led penetration testing and security consulting firm based in Bengaluru, India, serving AI-first and API-first SaaS startups. We audit TLS hardening posture as part of every pentest, including protocol version enforcement, cipher suite hygiene, certificate chain validation, HSTS preload eligibility, and OCSP stapling configuration. For an example of the pentest deliverable that documents these findings, see our SOC 2 + ISO 27001 ready pentest report sample.

This final article provides actionable configuration guidance for hardening TLS on web servers, load balancers, and applications. We cover protocol versions, cipher suites, certificates, security headers, and testing tools.

Each section includes the theory (why it matters), practical configuration (copy-paste ready), and common mistakes to avoid.

Quick Reference Checklist

ConfigurationMinimumRecommended
TLS VersionTLS 1.2TLS 1.3 only
Key ExchangeECDHEX25519 + ML-KEM
Cipher ModeAEAD (GCM)AES-256-GCM
Certificate KeyRSA 2048ECDSA P-256
Certificate Validity200 days90 days (ACME)
HSTSEnabledPreloaded
OCSP StaplingEnabledMust-Staple

2026 Certificate Lifetime Changes

Starting March 2026, maximum certificate validity periods are decreasing significantly. Automate your certificate renewal now.

DateMax ValidityAction Required
Before Mar 2026398 daysCurrent standard
Mar 15, 2026200 daysUpdate automation
Mar 15, 2027100 daysQuarterly renewal
Mar 15, 202947 days~Monthly renewal

1. Protocol Version Configuration

Theory: Why This Matters

VersionStatusAction
SSL 2.0BROKENDisable immediately, many critical vulnerabilities
SSL 3.0BROKENDisable. POODLE attack, RFC 7568 prohibits
TLS 1.0DEPRECATEDDisable. BEAST, RFC 8996 deprecates
TLS 1.1DEPRECATEDDisable. No benefits over 1.0, RFC 8996 deprecates
TLS 1.2SUPPORTEDEnable with strong ciphers only
TLS 1.3RECOMMENDEDEnable, best security and performance

Practical: Configuration

Nginx:

# Enable only TLS 1.2 and 1.3
ssl_protocols TLSv1.2 TLSv1.3;

Apache:

# Enable only TLS 1.2 and 1.3
SSLProtocol -all +TLSv1.2 +TLSv1.3

HAProxy:

# In bind line
bind *:443 ssl crt /path/cert.pem ssl-min-ver TLSv1.2

Reality: Common Mistakes

  • Enabling TLS 1.0 “for compatibility” when most clients support 1.2+
  • Not testing after changes. Use SSL Labs to verify.
  • Forgetting to restart service after config change

2. Cipher Suite Configuration

Theory: Why This Matters

Cipher Suite Priority:

  1. TLS 1.3 ciphers (all secure, automatic)
  2. ECDHE + AESGCM (forward secrecy + AEAD)
  3. ECDHE + CHACHA20 (mobile-friendly)
  4. DHE + AESGCM (if ECDHE unavailable)

Must Disable:

  • RSA key exchange (no forward secrecy)
  • CBC mode ciphers (padding oracles)
  • 3DES (Sweet32 attack)
  • RC4 (broken)
  • Export ciphers (Logjam, FREAK)

Practical: Configuration

Nginx, Recommended Cipher Suite:

ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
ssl_ecdh_curve X25519:secp384r1;

Apache, Recommended Cipher Suite:

SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder on

Reality: Common Mistakes

  • Using HIGH or ALL cipher strings, which are too permissive
  • Not setting server cipher preference. Client might choose weak cipher.
  • Forgetting to specify curves, which may use weak DH params

3. Certificate Configuration

Theory: Why This Matters

  • Use automated certificate management (Let’s Encrypt/ACME)
  • Short validity (90 days) with automated renewal
  • ECDSA P-256 preferred over RSA (smaller, faster)
  • Include full certificate chain (not just leaf)
  • Enable OCSP stapling for revocation checking

Practical: Configuration

Let’s Encrypt with Certbot:

# Install certbot
apt install certbot python3-certbot-nginx

# Get certificate (ECDSA)
certbot --nginx -d example.com --key-type ecdsa --elliptic-curve secp256r1

# Auto-renewal (cron)
0 0 * * * certbot renew --quiet

OCSP Stapling (Nginx):

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;

Verify Certificate Chain:

# Check certificate chain is complete
openssl s_client -connect example.com:443 -showcerts 2>/dev/null | \
  grep 'Certificate chain' -A 20

Reality: Common Mistakes

  • Missing intermediate certificate, which causes trust errors on some clients
  • Manual renewal process that leads to expired certificates
  • Using self-signed in production with no trust and no revocation

4. Security Headers

Theory: Why This Matters

Security headers complement TLS by providing additional browser-enforced protections.

HeaderPurpose
Strict-Transport-SecurityForces HTTPS, prevents SSL stripping
X-Frame-OptionsPrevents clickjacking attacks
X-Content-Type-OptionsPrevents MIME type sniffing
Content-Security-PolicyControls resource loading, prevents XSS
Referrer-PolicyControls referrer information leakage

Practical: Configuration

Complete Security Headers (Nginx):

# HSTS - Force HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# Prevent clickjacking
add_header X-Frame-Options "SAMEORIGIN" always;

# Prevent MIME sniffing
add_header X-Content-Type-Options "nosniff" always;

# XSS protection (legacy browsers)
add_header X-XSS-Protection "1; mode=block" always;

# Referrer policy
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Content Security Policy (customize for your app)
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;

Reality: Common Mistakes

  • CSP too restrictive, breaks application functionality
  • Missing always, headers not sent on error pages
  • HSTS without testing can lock out users if HTTPS breaks

5. Testing & Validation

Theory: Why This Matters

Always test TLS configuration after changes. Use multiple tools to catch different issues.

Practical: Tools

Online Testing Tools:

ToolPurpose
SSL LabsComprehensive, industry standard
Security Headerssecurityheaders.com, HTTP header analysis
Mozilla Observatoryobservatory.mozilla.org, overall security check
Hardenizehardenize.com, email + web security

Command-Line Testing:

# testssl.sh - comprehensive local testing
testssl.sh example.com

# Check specific vulnerability
testssl.sh --heartbleed --poodle --beast example.com

# nmap SSL scripts
nmap --script ssl-enum-ciphers,ssl-cert -p 443 example.com

# Quick OpenSSL check
openssl s_client -connect example.com:443 -tls1_3 -brief

SSL Labs Grade Requirements:

GradeRequirements
A+A grade + HSTS with long max-age
ATLS 1.2+, strong ciphers, no vulnerabilities, valid cert
BMinor issues like weak DH, missing features
C-FVulnerable to known attacks, weak protocols enabled

Reality: Common Mistakes

  • Testing only once when configurations drift over time
  • Not testing after certificate renewal, which causes chain issues
  • Automate testing in CI/CD pipeline

6. Complete Server Configuration

Complete Nginx TLS Configuration (2026 Recommended):

server {
    listen 443 ssl http2;
    server_name example.com;

    # Certificates
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Protocols - TLS 1.3 only (2026 recommendation)
    ssl_protocols TLSv1.3;

    # Ciphers
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
    ssl_prefer_server_ciphers on;
    ssl_ecdh_curve X25519:secp384r1;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    # Session
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;  # Forward secrecy

    # Security Headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
}

Reference: Use ssl-config.mozilla.org (Modern profile) for the latest recommended configurations.

Series Summary

This 6-article series covered everything you need to understand and implement secure TLS:

  1. Cryptography Fundamentals: Symmetric, asymmetric, hashing, key exchange, post-quantum
  2. TLS 1.2 Deep Dive: Handshake, key derivation, certificate trust model
  3. TLS 1.3: The Modern Standard: 1-RTT, HKDF, ECH, hybrid post-quantum
  4. TLS Attacks & Vulnerabilities: POODLE, Heartbleed, BEAST, Logjam, DROWN, ROBOT
  5. MITM Attacks: Interception, SSL stripping, HSTS, certificate pinning
  6. TLS Hardening Guide (this article): Configuration, testing, best practices

Key Takeaways

  • Use TLS 1.3 where possible, TLS 1.2 as fallback only
  • AEAD ciphers only: AES-256-GCM or ChaCha20-Poly1305
  • Automate certificate management with Let’s Encrypt and ACME
  • Prepare for shorter certificate lifetimes (200 days in 2026)
  • Enable HSTS with preload for SSL stripping defense
  • Test regularly with SSL Labs, testssl.sh, and nmap
  • Prepare for post-quantum with X25519 + ML-KEM hybrid

Previous: Article 5: MITM Attacks

This concludes our 6-article series on Understanding TLS Security.

Want to verify your TLS hardening is actually effective? We validate TLS configuration as part of our Web Application Pentest and IoT Pentest engagements. Get a free external security snapshot to see what’s exposed, or view our pricing.

Related: TLS 1.3: The Modern Standard, TLS Attacks and Vulnerabilities: A Pro Guide, SOC 2 + ISO 27001 ready pentest report sample.

Frequently Asked Questions

What TLS version and cipher suites should I configure in 2026?

Enable TLS 1.3 as the primary protocol and TLS 1.2 as a fallback only with strong cipher suites. Use ECDHE for key exchange, AEAD modes like AES-256-GCM for encryption, and ECDSA P-256 certificates. Disable all SSL versions and TLS 1.0/1.1 completely.

How do I test my server's TLS configuration?

Use SSL Labs (ssllabs.com/ssltest) for a comprehensive public scan that grades your configuration A through F. Check for supported protocol versions, cipher suite order, certificate chain validity, HSTS headers, and OCSP stapling. Run the test after every configuration change and aim for an A+ rating.

Why are certificate lifetimes shrinking in 2026 and what should I do?

Apple, Google, and Mozilla jointly drove a CA/Browser Forum ballot to shrink maximum TLS certificate validity from 398 days (current) to 200 days on March 15, 2026, then 100 days on March 15, 2027, then 47 days on March 15, 2029. The rationale is to reduce the harm window of compromised certificates and force operational maturity around automation. The practical implication is that manual certificate renewal becomes impossible at 47-day cadence. Set up ACME automation now via Let's Encrypt (certbot, acme.sh, lego) or your CDN's managed certificates (Cloudflare, AWS ACM, Google Cloud-managed certificates all rotate automatically). If you are still renewing certificates by hand once a year in 2026, you are roughly two cert generations away from breaking your production deployments.

What is HSTS and why does preload matter?

HTTP Strict Transport Security (HSTS, RFC 6797) is a response header that tells browsers to only ever connect to your domain over HTTPS for a specified duration. Once a browser sees the HSTS header, it refuses HTTP connections to that domain for the max-age period. The first visit is still vulnerable to SSL stripping (attacker downgrades the initial HTTP request to a non-HSTS site). HSTS preload solves the first-visit gap: domains submitted to hstspreload.org are baked into Chrome, Firefox, Safari, Edge source code so the browser knows HTTPS-only from the very first request. Submit with `Strict-Transport-Security: max-age=31536000; includeSubDomains; preload` then submit at hstspreload.org. Removal after submission is slow (months), so test thoroughly first.

What is OCSP stapling and should I enable it?

Online Certificate Status Protocol (OCSP) is how a browser checks whether a certificate has been revoked. Without stapling, the browser queries the CA's OCSP server directly, which adds latency, leaks the user's browsing history to the CA, and fails open if the CA's OCSP server is unreachable. OCSP stapling has the server fetch the OCSP response from the CA, sign it, and attach it (staple it) to the TLS handshake. The browser gets the freshness proof without contacting the CA. Enable in Nginx with `ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /path/to/chain.pem;`. Enable in Apache with `SSLUseStapling on`. CDN-fronted sites (Cloudflare, Fastly) get stapling automatically. Every TLS deployment in 2026 should staple.

What security headers should I send alongside TLS?

Six core headers. Strict-Transport-Security (HSTS) to enforce HTTPS. Content-Security-Policy (CSP) to prevent XSS and clickjacking via inline-script restrictions and frame-ancestors. X-Content-Type-Options: nosniff to prevent MIME confusion attacks. Referrer-Policy: strict-origin-when-cross-origin to prevent referrer-based information leak. Permissions-Policy to restrict browser features (camera, microphone, geolocation) that your app does not need. Cross-Origin-Opener-Policy and Cross-Origin-Resource-Policy for Spectre-class isolation. Drop the legacy X-Frame-Options if your CSP includes frame-ancestors (frame-ancestors supersedes it). Test headers at securityheaders.com after every config change. Target A+ grade.

ECDSA vs RSA certificates: which should I use?

ECDSA P-256 (also called secp256r1 or prime256v1) for new deployments. It produces smaller signatures (256-bit vs RSA-2048's 2048-bit), faster handshake (less CPU per connection), and equivalent security to RSA-3072. Issue ECDSA with Let's Encrypt: `certbot certonly --key-type ecdsa --elliptic-curve secp256r1 -d example.com`. For maximum compatibility with very old clients (Android 4.x, Windows XP), serve both ECDSA and RSA via dual-certificate setup (Nginx supports this with two `ssl_certificate` directives). In 2026, ECDSA-only is safe for >99 percent of consumer SaaS traffic. Avoid ECDSA P-384 unless you have a specific compliance requirement; P-256 is the broadly supported sweet spot.

Should I enable post-quantum key exchange now?

Enable hybrid post-quantum (X25519MLKEM768 or X25519Kyber768) wherever your TLS termination supports it. Cloudflare enables this by default on all sites. OpenSSL 3.5+ supports it natively. AWS ALB, Google Cloud Load Balancer, and most modern CDNs are rolling it out through 2025 and 2026. The hybrid construction means even if ML-KEM is later broken, you still have classical X25519 security; even if X25519 is later broken by a quantum computer, you have ML-KEM security. The cost is negligible (slightly larger key exchange messages). The benefit is forward secrecy against future quantum adversaries, which matters for any data that retains sensitivity for 10+ years (medical, legal, government, long-tenure SaaS contracts).

How do I configure Nginx for an A+ SSL Labs grade?

Start with Mozilla SSL Configuration Generator Modern profile (ssl-config.mozilla.org), which produces current copy-paste Nginx config. Key lines: `ssl_protocols TLSv1.3 TLSv1.2;` (TLS 1.3 first), `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 off;` (TLS 1.3 ignores this anyway), `ssl_session_cache shared:SSL:10m;`, `ssl_session_timeout 1d;`, `ssl_stapling on;`, `ssl_stapling_verify on;`, `add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;`. Reload Nginx, test at SSL Labs. A+ requires A grade plus HSTS with max-age at least 6 months.

What is the difference between SSL Labs A grade and A+ grade?

A grade requires modern protocols (TLS 1.2+), strong cipher suites (no weak ciphers), valid certificate chain, no protocol vulnerabilities (no POODLE, no Heartbleed, no Logjam), and forward secrecy on all common cipher suites. A+ requires everything in A plus HSTS with long max-age (minimum 6 months, ideally 1 year) and preload eligibility. The A+ grade is a meaningful signal to security-questionnaire reviewers and compliance auditors. Going from A to A+ usually means adding one HSTS header. Going from B or C to A+ usually means disabling legacy protocols (TLS 1.0, TLS 1.1) and weak cipher suites (CBC mode, 3DES, RC4). Test at ssllabs.com/ssltest after every config change.

Got a question or counter-take?

Email contact@cybersecify.com, WhatsApp +91 9986 998 333, or DM Rathnakara GN on LinkedIn.

Share this article
TLShardeningNginxApachecipher suitesHSTSOCSPcertificate managementsecurity headersSSL TLS best practices