TLS 1.3 mandates forward secrecy for all connections. There is no way to configure TLS 1.3 without Forward secrecy. If you are still using TLS 1.2, ensure you use ECDHE cipher suites (TLS_ECDHE_*).
Session resumption allows a client to resume a previous TLS session without performing the full Handshake, saving a round trip and reducing computational cost.
The server assigns a session ID in the New Session Ticket message. The client includes this Session ID in subsequent ClientHello messages. The server looks up the session state (previously Negotiated cipher suite, master secret) and resumes the session.
Drawback: The server must maintain session state, which is problematic for distributed systems (behind load balancers). Solutions include shared session caches (Redis, memcached) or session Ticket encryption with a shared key.
The server encrypts the session state and sends it to the client as a “ticket.” The client presents The ticket in subsequent connections. The server decrypts the ticket (using a key shared across all Server instances) and resumes the session without storing any state.
# Check if session resumption is working
openssl s_client -connect example.com:443 -servername example.com -reconnect 2>&1 | grep " Session-ID "
TLS 1.3 uses PSK (pre-shared key) for session resumption. The PSK is derived from a previous session Or configured out-of-band. TLS 1.3 supports external PSKs (configured manually, similar to API keys) And resumption PSKs (derived from previous sessions).
# Basic TLS connection test
openssl s_client -connect example.com:443 -servername example.com
# Show supported cipher suites
nmap --script ssl-enum-ciphers -p 443 example.com
# https://www.ssllabs.com/ssltest/
Expired certificates. Set up monitoring and automated renewal. Let’s Encrypt certificates expire every 90 days. Use certbot with a renewal timer.
Missing intermediate certificates. The server must send the full certificate chain (server + intermediate). Omitting intermediates causes “certificate chain incomplete” errors.
Weak cipher suites. Disable TLS_RSA_* (no forward secrecy), TLS_*_CBC_* (vulnerable to BEAST/LUCKY13), TLS_*_3DES_* (64-bit block cipher, Sweet32), and any suite with SHA-1 or MD5.
TLS 1.0/1.1 enabled. These versions have known weaknesses. Disable them on all servers and clients.
No HSTS header. The Strict-Transport-Security header tells the browser to always use HTTPS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Without HSTS, the first HTTP request to a site is vulnerable to downgrade attacks.
Mixed content. HTTPS pages that load HTTP subresources (images, scripts, stylesheets) are vulnerable to injection. Browsers block mixed content by default.
SNI missing. Server Name Indication (SNI) is required for virtual hosting with TLS. Without SNI, the server cannot determine which certificate to present. All modern browsers send SNI, but some legacy clients (e.g., Windows XP, Java 6) do not.
Certificate name mismatch. The certificate must match the hostname the client connects to. Wildcard certificates (*.example.com) only match one level of subdomains (sub.example.com not a.b.example.com).
# Test TLS connection and show certificate chain
openssl s_client -connect example.com:443 -servername example.com -showcerts
# Test with specific TLS version
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
openssl s_client -connect example.com:443 -status -tlsextdebug
openssl s_client -connect example.com:443 -curves all
# Test with client certificate
openssl s_client -connect example.com:443 -cert client.pem -key client.key
apt install certbot python3-certbot-nginx # For nginx
apt install certbot python3-certbot-apache # For Apache
certbot --nginx -d example.com -d www.example.com
certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem
# Alternative TLS client (from GnuTLS)
gnutls-cli -p 443 example.com
Self-signed certificates in production without proper trust configuration. Self-signed certificates cause errors in all standard clients unless the certificate is manually trusted. For internal services, use an internal CA (e.g., step-ca, smallstep) or configure clients to trust the specific certificate.
Certificate chain ordering. Some servers send certificates in the wrong order (server first, then intermediate). The correct order is: server certificate, then intermediate certificates in order from leaf to root (closest to leaf first).
Not monitoring certificate expiration. Expired certificates cause immediate outages. Set up alerts 30, 14, and 7 days before expiration. Use ACME for automatic renewal.
Disabling certificate verification in development. Using NODE_TLS_REJECT_UNAUTHORIZED=0 verify=False in Python requests, or -k/--insecure in curl masks real certificate problems that will surface in production. Use locally-trusted certificates instead.
TLS termination at the wrong layer. Terminating TLS at a load balancer and re-encrypting to the backend (TLS passthrough/bridging) adds latency and creates a trust boundary that must be secured. Terminating TLS at the application server means the load balancer cannot inspect traffic for WAF or DDoS protection. Choose based on your security requirements.
Assuming TLS 1.3 is universally supported. TLS 1.3 is supported by all modern browsers and operating systems, but legacy clients (Java 8 without patches, Windows 7, Android < 7.0) may not support it. If you need to support these clients, enable TLS 1.2 with forward secrecy as a fallback.
Ignoring SCT (Signed Certificate Timestamp) requirements. Chrome and other browsers require certificates to have embedded SCTs proving the certificate was logged in a Certificate Transparency log. Certificates without SCTs will be rejected by Chrome.
TLS operates on records. Each TLS record has a 5-byte header followed by the encrypted payload:
| Content Type | 1 byte: 20=ChangeCipherSpec, 21=Alert, 22=Handshake, 23=Application
| Version | 2 bytes: 0x0301=TLS 1.0, 0x0302=TLS 1.1, 0x0303=TLS 1.2
| Length | 2 bytes: length of the payload
| Payload | Variable (encrypted with the negotiated cipher suite)
In TLS 1.3, the outer record header always uses TLS 1.2 version (0x0303) for compatibility with Middleboxes. The actual protocol version is negotiated inside the handshake.
Maximum record size is 16,384 bytes (2^14). Larger application data must be split across multiple Records. TLS 1.3 supports records up to 16,384 + 256 bytes (including content type byte and Padding).
TLS alerts communicate errors and closure notifications. They are 2 bytes: alert level (1=warning, 2=fatal) and alert description.
Common alerts:
Description Value Meaning close_notify0 Clean connection closure unexpected_message10 Malformed message received bad_record_mac20 Decryption failed (wrong key or tampered data) handshake_failure40 Handshake negotiation failed certificate_expired45 Certificate has expired certificate_revoked44 Certificate has been revoked illegal_parameter47 Invalid value in handshake field decrypt_error51 Handshake cryptographic operation failed
In TLS 1.3, most alerts result in immediate connection termination. The server cannot send an error Alert after the handshake completes (to prevent middleboxes from interpreting alerts as protocol Errors and closing connections).
Both the client and server generate 32 bytes of random data in their Hello messages. These random Values are used in the key derivation process and must be unpredictable. If an attacker can predict The random values, they may be able to derive the session keys.
In TLS 1.2, the random values include the Unix timestamp in the first 4 bytes (deprecated practice That leaks server clock information). In TLS 1.3, the random values must be generated using a Cryptographically secure random number generator with no structure.
Full TLS handshake requires:
TLS 1.2: 2 RTTs + asymmetric crypto (RSA or ECDHE key exchange)TLS 1.3: 1 RTT + asymmetric crypto (ECDHE key exchange)TLS 1.3 with 0-RTT: 0 RTTs (but no replay protection)For short-lived connections (HTTP/1.1 without keep-alive), the TLS handshake overhead can be Significant. A connection to a server with 100 ms RTT requires:
TLS 1.2: 200 ms (handshake) + 100 ms (request/response) = 300 ms totalTLS 1.3: 100 ms (handshake) + 100 ms (request/response) = 200 ms totalTLS 1.3 0-RTT: 0 ms (handshake) + 100 ms (request/response) = 100 ms totalAsymmetric crypto (ECDHE key exchange) is the most expensive part of the TLS handshake:
ECDHE with P-256: ~1-2 ms on modern hardware (CPU-bound)ECDHE with X25519: ~0.5-1 ms (faster curve operations)RSA-2048 key exchange: ~2-5 ms (slower, no forward secrecy)AES-256-GCM encryption: ~1 GB/s per core (hardware-accelerated on x86 with AES-NI)For servers handling thousands of new connections per second, the computational cost of TLS Handshakes can be significant. Solutions include:
Session resumption: Reduces asymmetric crypto to zero on repeat connections.TLS session tickets: No server-side state required.OCSP stapling: Eliminates the OCSP lookup during the handshake.Hardware acceleration: AES-NI instructions on x86, ARM Crypto Extensions on mobile.TLS offload: Terminate TLS on a dedicated device (load balancer, SSL accelerator).Edge termination: TLS is terminated at the load balancer/reverse proxy. The backend receives Plaintext HTTP.
Client --TLS--> Load Balancer --HTTP--> Backend
Advantages: Backend simplicity, centralized certificate management, WAF/DDoS protection at the edge. Disadvantages: Backend traffic is unencrypted (requires trusted network), single point of failure For TLS.
End-to-end TLS: TLS is terminated at the application server. The load balancer passes TCP Streams without decryption.
Client --TLS--> Load Balancer --TCP/TLS--> Backend
Advantages: End-to-end encryption, backend handles TLS. Disadvantages: No WAF/DDoS inspection at the Load balancer, certificates must be managed on every backend instance.
TLS bridging: TLS is terminated at the load balancer and re-established to the backend.
Client --TLS--> Load Balancer --TLS--> Backend
Advantages: End-to-end encryption, WAF/DDoS protection at the edge. Disadvantages: Double TLS Overhead, certificate management on both sides, more complex configuration.
TLS 1.3 (preferred):
TLS_CHACHA20_POLY1305_SHA256
TLS 1.2 (fallback):
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
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 off ;
ssl_session_cache shared:SSL:10m;
resolver 8.8.8.8 8.8.4.4 ;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# OCSP stapling verification
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1. 1
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
SSLStaplingCache shmcb:/var/run/apache2/stapling-cache( 128000 )
Header always set Strict-Transport-Security "max-age= 63072000 ; includeSubDomains; preload"
Public Key Infrastructure (PKI) is the framework for managing digital certificates and public-key Encryption. PKI includes:
Certificate Authorities (CAs): Organizations that issue certificates and vouch for the identity of certificate holders.Registration Authorities (RAs): Organizations that verify the identity of certificate applicants before the CA issues the certificate.Certificate Repositories: Publicly accessible databases where certificates and CRLs are published.Certificate Management Systems: Systems that manage the lifecycle of certificates (issuance, renewal, revocation).Validation Authorities: Entities that verify certificate validity and chain of trust.When a client validates a server’s certificate, it checks:
Signature chain: The server’s certificate is signed by an intermediate CA, which is signed by a root CA. The root CA’s certificate is in the client’s trust store.Validity period: The current time is within the certificate’s Not Before and Not After.Revocation status: The certificate has not been revoked (checked via CRL or OCSP).Name matching: The certificate’s Subject Alternative Name (SAN) matches the hostname the client connected to.Key usage: The certificate’s Key Usage and Extended Key Usage extensions allow the intended use (TLS Web Server Authentication).Path constraints: Intermediate certificates do not violate path length or name constraints.For internal services, organizations can run their own CA:
step-ca (smallstep): Open-source CA written in Go. Supports ACME, OIDC, SSH certificates, and X.509. Easy to set up and manage.cfssl (Cloudflare): PKI/TLS toolkit for Go. Includes CA, OCSP responder, and certificate bundler.OpenSSL CA: Manual CA operations using openssl ca command. Flexible but requires more scripting for automation.HashiCorp Vault: Secrets management platform that includes PKI as a secrets engine. Issues short-lived certificates automatically.step ca init --name= " Internal CA " --dns= " ca.internal.example.com " --address= " :8443 "
# Issue a certificate with step CLI
step ca certificate api.internal.example.com cert.pem key.pem
# Install the CA root certificate on clients
step ca bootstrap --ca-url https://ca.internal.example.com:8443 --fingerprint $( step certificate fingerprint root_ca.crt )
Operating systems and browsers maintain trust stores containing root CA certificates:
Linux: /etc/pki/tls/certs/ca-bundle.crt (RHEL), /etc/ssl/certs/ca-certificates.crt (Debian). Managed by the ca-certificates package.macOS: Keychain (System Roots keychain). Managed by security command.Windows: Certificate Store (Local Machine\Root). Managed by certlm.msc.Java: $JAVA_HOME/lib/security/cacerts. Managed by keytool.Python: Uses the system trust store (via certifi package or system certificates).Node.js: Uses the system trust store (via OpenSSL).Go: Uses the system trust store by default, or a custom CA pool.When TLS connections fail, check in this order:
Certificate validity: openssl x509 -in cert.pem -text -noout — check dates, SAN, chainCertificate chain: openssl s_client -connect host:443 -servername host -showcerts — verify the chain is completeCipher suite negotiation: openssl s_client -cipher 'ECDHE-RSA-AES256-GCM-SHA384' — test specific cipher suitesOCSP stapling: openssl s_client -status -tlsextdebug — verify OCSP responseTLS version: openssl s_client -tls1_2 or openssl s_client -tls1_3 — test specific versionsSCT verification: Check the certificate for embedded SCTs (Certificate Transparency)HSTS: Check the Strict-Transport-Security response headerMixed content: Ensure no HTTP resources are loaded from HTTPS pagesThis topic covers the core concepts of tls, including underlying theory, practical implementation, and key applications.
Key concepts include:
CPU architecture and the fetch-decode-execute cycle memory hierarchy (cache, RAM, virtual) input/output systems operating systems and scheduling interrupts and polling Understanding these concepts thoroughly is essential for both examinations and practical programming, and requires both theoretical knowledge and hands-on practice.
Worked examples demonstrating the application of key concepts are covered in the detailed sub-pages linked above.