G
GuideDevOps
Lesson 15 of 28

SSL / TLS & Certificate Management

Part of the Networking Basics tutorial series.

SSL/TLS is the encryption protocol that protects data in transit over networks. Every HTTPS connection, VPN, and secure communication relies on SSL/TLS to keep data confidential and authentic.

What is SSL/TLS?

SSL (Secure Sockets Layer) and TLS (Transport Layer Security) are cryptographic protocols:

Unencrypted (HTTP):
Client: "Here's my password"
        123456 (visible to everyone!)

Encrypted (HTTPS with TLS):
Client: "Here's my password"
        ◆■▲●◇■▲● (encrypted gobbledygook)

SSL vs TLS:

  • SSL 3.0 (1996) — Insecure, deprecated
  • TLS 1.0 (1999) — Legacy, should avoid
  • TLS 1.1 (2006) — Outdated
  • TLS 1.2 (2008) — Current standard
  • TLS 1.3 (2018) — Modern, recommended

Everyone calls it "SSL" even though TLS is technically correct. TLS is newer and more secure.

How TLS Works

TLS Handshake (happens before data transfer):

Client                              Server
   ├─ Hello (supported ciphers) ──────→
   ├←─ Hello + Certificate ────────────┤
   ├─ Verify certificate (trust chain)
   ├─ Generate shared secret ──────────→
   ├← Handshake complete ─────────────┤
   │
   └─ All data encrypted ←─────────────→

Key Agreement:

  1. Client & server agree on encryption algorithm
  2. Exchange public keys
  3. Both derive same shared secret (symmetric key)
  4. Use shared secret to encrypt all data

Why two types of encryption?

Asymmetric (slow, for key exchange):
- Public key: anyone can use
- Private key: only owner knows
- Safe to share public key over internet

Symmetric (fast, for data):
- Same key for encryption & decryption
- Both sides know the key (agreed during handshake)
- Fast enough for bulk data

Digital Certificates

Certificate proves the server is who it claims to be:

Owner: api.example.com
Issued by: Letsencrypt (certificate authority)
Expires: 2026-04-09
Public Key: -----BEGIN PUBLIC KEY-----
            MIIBIjANBgkqhkiG9w0B...
Fingerprint: F3:3E:D8:D7:...

Certificate Chain:

Root CA (self-signed, trusted)
  └─ Intermediate CA (signed by root)
      └─ Server Certificate (signed by intermediate)

Browser verification:

  1. Server sends certificate
  2. Browser checks signature chain
  3. Verifies domain matches
  4. Checks expiration date
  5. If all good → green lock 🔒

Certificate Types

TypeCoveragePriceUse
Single Domainapi.example.com onlyFree-$50/yrSingle service
Wildcard*.example.com$50-$200/yrAll subdomains
Multi-SANMultiple domains$100-$300/yrMultiple domains
EVWith company verification$150-$250/yrEnterprise

Let's Encrypt = Free certificates!

# Get free 90-day certificate
certbot certonly --standalone -d example.com
 
# Automatically renews before expiry

Creating SSL/TLS Certificates

Generate Self-Signed Certificate (for testing):

# Generate private key (2048 bits)
openssl genrsa -out private.key 2048
 
# Generate certificate (valid 365 days)
openssl req -new -x509 -key private.key \
  -out certificate.crt -days 365 \
  -subj "/CN=example.com"
 
# View certificate
openssl x509 -in certificate.crt -text -noout

Generate Certificate Signing Request (for CA):

# Create private key
openssl genrsa -out private.key 2048
 
# Create signing request (CSR)
openssl req -new -key private.key \
  -out certificate.csr \
  -subj "/CN=example.com/O=Company/C=US"
 
# Send CSR to Certificate Authority
# CA verifies identity, returns signed certificate

Configuring TLS on Server

Nginx Example:

server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    # Certificate files
    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    
    # TLS configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    # Redirect HTTP to HTTPS
    location / {
        proxy_pass http://backend:8080;
    }
}
 
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$server_name$request_uri;  # Redirect to HTTPS
}

Apache Example:

<VirtualHost *:443>
    ServerName api.example.com
    
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/api.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/api.example.com/privkey.pem
    
    SSLProtocol TLSv1.2 TLSv1.3
    SSLCipherSuite HIGH:!aNULL:!MD5
    
    ProxyPreserveHost On
    ProxyPass / http://localhost:8080/
</VirtualHost>
 
<VirtualHost *:80>
    ServerName api.example.com
    Redirect / https://api.example.com/
</VirtualHost>

Checking Certificates

View certificate details:

# From server
openssl x509 -in certificate.crt -text -noout
 
# From live connection
openssl s_client -connect example.com:443

Check expiration date:

openssl x509 -in certificate.crt -noout -dates
 
# Output:
# notBefore=Apr  9 00:00:00 2024 GMT
# notAfter=Apr   9 23:59:59 2025 GMT

Verify certificate chain:

openssl verify -CAfile ca-bundle.crt certificate.crt
 
# Result: OK (valid)
#    or: error (problem)

Certificate Management

Automated Renewal with Certbot:

# Install certbot
sudo apt-get install certbot python3-certbot-nginx
 
# Get certificate
sudo certbot certonly --nginx -d example.com
 
# Automatic renewal
sudo systemctl enable certbot.timer
 
# Check renewal status
sudo certbot renew --dry-run

Monitoring Certificate Expiry:

#!/bin/bash
# Alert if certificate expires in < 30 days
 
for cert in /etc/letsencrypt/live/*/fullchain.pem; do
    expiry=$(openssl x509 -in $cert -noout -dates | grep notAfter)
    echo "$cert: $expiry"
done

Troubleshooting TLS

"Certificate not trusted"

1. Check expiration
   openssl x509 -noout -dates -in cert.pem

2. Verify domain matches
   openssl x509 -noout -subject -in cert.pem
   ← Should match server hostname

3. Check certificate chain
   openssl verify -CAfile ca-bundle.crt cert.pem

4. Reconstruct cert chain
   cat server.crt intermediate.crt root.crt > fullchain.pem

"Connection refused on 443"

1. Check if HTTPS server is running
   telnet example.com 443
   ← Should connect

2. Verify firewall allows port 443
   sudo ufw allow 443

3. Check server config
   grep -A5 "listen 443" /etc/nginx/sites-enabled/*

"Certificate expired"

1. Renew certificate
   openssl x509 -req -days 365 \
     -in old.csr -signkey private.key \
     -out new.crt

2. Deploy new certificate
   cp new.crt /path/to/server/cert
   systemctl restart nginx

3. Verify renewal
   openssl x509 -noout -dates -in new.crt

TLS Best Practices

1. Use Current TLS Version

✓ TLS 1.2 minimum
✓ TLS 1.3 preferred
✗ Never use SSL 3.0, TLS 1.0, TLS 1.1

2. Keep Certificates Valid

✓ Renew before expiry (but not too early)
✓ Monitor expiration dates
✗ Don't let certificates expire

3. Use Strong Ciphers

✓ ECDHE with AES-GCM
✗ Avoid weak ciphers (DES, RC4, MD5)

4. Enable HSTS (force HTTPS):

Strict-Transport-Security: max-age=31536000; includeSubDomains

5. Monitor Certificate Usage

# Check which certificates are deployed
find /etc -name "*.pem" -o -name "*.crt" 2>/dev/null
 
# List expiration dates
for cert in $(find /etc -name "*.crt" 2>/dev/null); do
  echo "$cert: $(openssl x509 -noout -dates -in $cert)"
done

Key Concepts

  • SSL/TLS = Encryption protocol for secure communication
  • Handshake = Process to establish encrypted connection
  • Certificate = Proves server identity
  • Certificate Authority (CA) = Issues and signs certificates
  • Private key = Keep secret, used for decryption
  • Public key = Share openly, used for encryption
  • Self-signed = Certificate not issued by CA (for testing)
  • Symmetric encryption = Fast, same key for encrypt/decrypt
  • Asymmetric encryption = Slow, different public/private keys
  • Always use HTTPS with valid certificates in production