SSL termination at the edge means your load balancer handles all the TLS encryption and decryption, so your backend servers don’t have to.
Let’s watch a request flow through:
- Client to Load Balancer: A user’s browser connects to your load balancer’s IP address over HTTPS. The load balancer presents its SSL certificate and negotiates a secure TLS connection.
- Load Balancer Decrypts: The load balancer receives the encrypted HTTP request from the client, decrypts it, and inspects the plaintext HTTP headers.
- Load Balancer to Backend: The load balancer then forwards the decrypted HTTP request to one of your backend servers. This connection between the load balancer and the backend can be plain HTTP or another TLS connection, depending on your configuration.
- Backend Processes: The backend server receives the (decrypted) request, processes it, and generates a response.
- Backend to Load Balancer: The backend server sends the (decrypted) HTTP response back to the load balancer.
- Load Balancer Encrypts: The load balancer receives the plaintext response, encrypts it using TLS, and sends the encrypted response back to the client.
This offloading is typically done to reduce the CPU load on your application servers, simplify certificate management, and enable features like centralized security policy enforcement at the edge.
Here’s a simplified Nginx configuration snippet for an AWS Application Load Balancer (ALB) demonstrating SSL termination. The ALB listens on port 443, terminates SSL using a certificate stored in AWS Certificate Manager (ACM), and forwards traffic to backend instances on port 80.
# This is a conceptual example for an ALB listener.
# Actual configuration is managed via the AWS Console or CLI/API.
# ALB Listener Configuration (Conceptual)
# Protocol: HTTPS
# Port: 443
# Certificate: arn:aws:acm:us-east-1:123456789012:certificate/abcdefgh-ijkl-mnop-qrst-uvwxyz123456
# Default Actions:
# Forward to: target-group-name
# This is what the ALB translates the above into conceptually for its internal routing logic.
# The actual Nginx configuration for a self-managed load balancer would look more like this:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# Recommended SSL settings for strong security
ssl_protocols TLSv1.2 TLSv1.3;
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 off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off; # Consider enabling if performance is critical and security implications understood
location / {
proxy_pass http://backend_app_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # Important: $scheme will be 'https'
}
}
upstream backend_app_servers {
server 10.0.1.10:80;
server 10.0.1.11:80;
# ... more backend servers
}
In this Nginx example, listen 443 ssl http2; tells Nginx to listen for HTTPS connections. The ssl_certificate and ssl_certificate_key directives point to the files containing your server’s SSL certificate and private key. The proxy_pass directive then forwards the request, now in plaintext, to the backend_app_servers upstream group. Crucially, proxy_set_header X-Forwarded-Proto $scheme; will pass the original protocol (https) to the backend, which is invaluable for applications that need to know if the original client connection was secure.
When you terminate SSL at the load balancer, your backend servers communicate with the load balancer over an unencrypted channel (or a separate, potentially internal, encrypted channel). This means your application code doesn’t need to worry about loading SSL certificates or performing computationally expensive encryption/decryption. The load balancer handles it all. This also consolidates certificate management; you only need to update certificates on the load balancer, not on every single application server.
One common misunderstanding is that once SSL is terminated, the traffic is "insecure" all the way to the backend. This is only true if the network path between your load balancer and your backend servers is untrusted. In cloud environments like AWS, traffic within a VPC is generally considered private and secure. However, for defense-in-depth or if your backend servers are in a different network, you can configure the load balancer to re-encrypt traffic to the backend using TLS. This is often called SSL pass-through (which is different, it just forwards the encrypted traffic) or mutual TLS (mTLS) between the load balancer and backends.
The next logical step after mastering SSL termination is often implementing HTTP/2 or HTTP/3 on the load balancer to further improve client-to-load balancer performance.