Essential SSL/TLS Hardening Steps
1. Get a Valid SSL Certificate
Free Option: Let's Encrypt
# Install Certbot
sudo apt install certbot python3-certbot-apache -y # For Apache
sudo apt install certbot python3-certbot-nginx -y # For Nginx
# Get certificate (Apache)
sudo certbot --apache -d example.com -d www.example.com
# Get certificate (Nginx)
sudo certbot --nginx -d example.com -d www.example.com
# Test auto-renewal
sudo certbot renew --dry-run
Commercial Certificates
• DigiCert, Sectigo, GlobalSign for OV/EV certificates
• Install using CSR (Certificate Signing Request)
2. Disable Weak SSL/TLS Protocols
Apache Configuration
# Edit /etc/apache2/sites-available/your-site-ssl.conf or ssl.conf
# Disable SSLv2, SSLv3, TLS 1.0, TLS 1.1
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
# Or only enable TLS 1.2 and 1.3
SSLProtocol TLSv1.2 TLSv1.3
# Restart Apache
sudo systemctl restart apache2
Nginx Configuration
# Edit /etc/nginx/sites-available/your-site or nginx.conf
server {
listen 443 ssl http2;
# Only allow TLS 1.2 and 1.3
ssl_protocols TLSv1.2 TLSv1.3;
# Certificate paths
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
}
# Restart Nginx
sudo systemctl restart nginx
3. Use Strong Cipher Suites
Apache
# Strong cipher configuration
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
# Prefer server cipher order
SSLHonorCipherOrder on
Nginx
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';
ssl_prefer_server_ciphers on;
4. Enable HSTS (HTTP Strict Transport Security)
Apache
# Enable headers module
sudo a2enmod headers
# Add to VirtualHost
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
5. Enable OCSP Stapling
Why: Improves performance and privacy by bundling certificate validity status with TLS handshake.
Apache
SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
Nginx
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
6. Use Strong Diffie-Hellman Parameters
Generate DH Parameters
# Generate 2048-bit (faster, still secure)
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
# Or 4096-bit (slower, more secure - takes ~10 minutes)
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Configure Apache
SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"
Configure Nginx
ssl_dhparam /etc/ssl/certs/dhparam.pem;
7. Enable Session Resumption
Apache
SSLSessionCache "shmcb:/var/cache/apache2/ssl_scache(512000)"
SSLSessionCacheTimeout 300
Nginx
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
8. Redirect HTTP to HTTPS
Apache
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
# Or using mod_rewrite
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Nginx
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
Complete Secure Configuration Examples
Apache Complete SSL Configuration
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
# SSL Certificate
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# Strong protocols only
SSLProtocol TLSv1.2 TLSv1.3
# Strong ciphers
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder on
# DH parameters
SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"
# OCSP Stapling
SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
# Session cache
SSLSessionCache "shmcb:/var/cache/apache2/ssl_scache(512000)"
SSLSessionCacheTimeout 300
# Security headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
# HTTP/2
Protocols h2 http/1.1
</VirtualHost>
Nginx Complete SSL Configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/html;
# SSL Certificate
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Strong protocols only
ssl_protocols TLSv1.2 TLSv1.3;
# Strong ciphers
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
# DH parameters
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "0" always;
location / {
try_files $uri $uri/ =404;
}
}
Testing Your SSL/TLS Configuration
Online Testing Tools:
• SSL Labs Server Test - Comprehensive SSL analysis (aim for A+ rating)
• Security Headers - Check HTTP security headers
• testssl.sh - Command-line SSL testing tool
Command-Line Testing
# Test SSL connection
openssl s_client -connect example.com:443
# Check certificate expiration
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
# Test specific TLS version
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
# Using testssl.sh
git clone https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh example.com
Common SSL/TLS Vulnerabilities to Fix
| Vulnerability | Impact | Fix |
|---|---|---|
| POODLE | High | Disable SSLv3 |
| BEAST | Medium | Disable TLS 1.0, prefer server ciphers |
| CRIME | Medium | Disable SSL compression |
| Heartbleed | Critical | Update OpenSSL to 1.0.1g+ |
| FREAK | High | Disable export ciphers |
| Logjam | High | Use 2048-bit DH parameters |
| DROWN | High | Disable SSLv2 |
Security Checklist
☐ Valid SSL certificate installed
☐ SSLv2, SSLv3, TLS 1.0, TLS 1.1 disabled
☐ Strong cipher suites configured
☐ HSTS enabled with long max-age
☐ OCSP Stapling enabled
☐ Strong DH parameters (2048-bit minimum)
☐ HTTP redirects to HTTPS
☐ Certificate auto-renewal configured
☐ SSL Labs test shows A or A+ rating
☐ Regular security monitoring enabled
🔒 Protect Your Connection
Even with perfect SSL/TLS configuration, your connection can be compromised on untrusted networks. Use a VPN for an additional layer of encryption:
Military-grade encryption • No-logs policy • 30-day money-back guarantee