Technical Deep-Dives

TLS Hardening Guide: Secure Configuration Best Practices

Actionable TLS and SSL hardening guide with best practices for protocol versions, cipher suites, certificate management, security headers, OCSP stapling, and complete Nginx/Apache configurations.

T&RG
Theertha & Rathnakara GN
Cyber Secify
6 min read

Article 6 of 6: Understanding TLS Security Series

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.

Share this article
TLShardeningNginxApachecipher suitesHSTSOCSPcertificate managementsecurity headersSSL TLS best practices