Security

SSL/TLS Hardening: Ciphers, HSTS and OCSP

Harden your HTTPS configuration with modern cipher suites, HSTS, and OCSP stapling

Why Default TLS Configurations Are Not Enough

Modern HTTPS requires careful configuration. Default or legacy setups often contain:

  • Weak cipher suites, older algorithms like RC4 or DES
  • Deprecated protocols, SSLv3, TLS 1.0, and TLS 1.1 are cryptographically broken
  • Missing security headers, no HSTS, missing X-Frame-Options, etc.
  • No OCSP stapling, slower certificate validation and privacy leaks

The result: your domain may have an HTTPS lock, but traffic is vulnerable to downgrade attacks, man-in-the-middle interception, and compromise.

Test Your Current Configuration

Before making changes, audit your existing setup:

Using SSL Labs:

  1. Visit SSL Labs (ssllabs.com/ssltest)
  2. Enter your domain: tuodominio.com
  3. Review the grade and identified weaknesses

Using testssl.sh:

# Download and run the automated tester
git clone https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh --full https://tuodominio.com

This tool identifies weak ciphers, protocol versions, and missing headers.

Nginx: Modern TLS Configuration

Replace your ssl_ directives in the server block with:

# Protocol support: only modern versions
ssl_protocols TLSv1.2 TLSv1.3;

# Modern cipher suite (prefer AEAD ciphers)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

# Let client choose cipher (modern TLS 1.3 handles this)
ssl_prefer_server_ciphers off;

# Session resumption: improves performance
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# Diffie-Hellman for forward secrecy
ssl_dhparam /etc/nginx/dhparam.pem;

Generate Diffie-Hellman parameters (one-time operation, takes a few minutes):

sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048

Apache Equivalent Configuration

For Apache with mod_ssl, add to your VirtualHost:

SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384

# Use server ciphers for TLS 1.2 (TLS 1.3 ignores this)
SSLHonorCipherOrder on

# Session cache
SSLSessionCache "shmcb:/var/cache/mod_ssl/scache(512000)"
SSLSessionCacheTimeout 300

# OCSP Stapling
SSLUseStapling on
SSLStaplingCache "shmcb:/var/run/ocsp(128000)"
SSLStaplingResponderTimeout 5

HSTS Header Configuration

Add the Strict-Transport-Security header to force HTTPS:

Nginx:

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

Apache:

Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
  • max-age=63072000, 2 years in seconds
  • includeSubDomains, apply to all subdomains
  • preload, allow inclusion in browser preload lists

Once you add the preload directive and it's cached by browsers, reverting to HTTP becomes extremely difficult. Test thoroughly before enabling this in production.

OCSP Stapling

OCSP Stapling allows your server to provide certificate revocation status directly, speeding up connections and improving privacy.

Nginx:

ssl_stapling on;
ssl_stapling_verify on;
ssl_stapling_responder http://ocsp.int-x3.letsencrypt.org;
ssl_trusted_certificate /etc/letsencrypt/live/tuodominio.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

Apache:

SSLStapling on
SSLStaplingResponder "http://ocsp.int-x3.letsencrypt.org"
SSLStaplingCache "shmcb:/var/run/ocsp(128000)"
SSLStaplingResponderTimeout 5

Additional Security Headers

Implement these headers alongside HSTS for defense-in-depth:

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

Verification Steps

Test that weak protocols are rejected:

# This should FAIL (TLS 1.1 disabled)
openssl s_client -connect tuodominio.com:443 -tls1_1

# This should SUCCEED (TLS 1.2/1.3 enabled)
openssl s_client -connect tuodominio.com:443 -tls1_2

Check HSTS header presence:

curl -i https://tuodominio.com | grep -i "strict-transport"

Verify OCSP stapling:

openssl s_client -connect tuodominio.com:443 -tlsextdebug 2>&1 | grep "OCSP"

Use Mozilla SSL Configuration Generator as a reference. It provides tested configurations for Nginx, Apache, and other servers with detailed explanations.

Checklist

  • Review SSL Labs test results
  • Update protocol version to TLSv1.2 and TLSv1.3 only
  • Configure modern cipher suites
  • Generate Diffie-Hellman parameters
  • Add HSTS header (start with max-age=300 for testing)
  • Enable OCSP stapling
  • Add security headers (X-Frame-Options, X-Content-Type-Options)
  • Verify weak protocols are rejected
  • Increase HSTS max-age to 63072000 after validation
  • Re-test with SSL Labs

On this page