SSL Passthrough allows encrypted HTTPS/TLS traffic to pass through a proxy or load balancer without decrypting it.
Instead of terminating SSL at NGINX, the encrypted connection is forwarded directly to the backend server.
SSL Passthrough, NGINX cannot inspect:
- URLs
- Headers
- Cookies
- HTTP paths
Because traffic remains encrypted.
Simple rule:
πΉ SSL Termination β NGINX decrypts traffic
πΉ SSL Passthrough β Backend decrypts traffic
Architecture
Client HTTPS
|
v
NGINX Stream
|
v
Backend HTTPS Server
Backend server handles:
- SSL certificates
- TLS handshake
- Decryption
Step 1: Enable Stream Module
Ubuntu/Debian
Install:
sudo apt install libnginx-mod-stream
Check:
nginx -V 2>&1 | grep stream
Step 2: Configure Stream Block
Edit:
/etc/nginx/nginx.conf
Add:
stream {
upstream https_backend {
server 10.0.0.20:443;
}
server {
listen 443;
proxy_pass https_backend;
}
}
Step 3: Reload NGINX
sudo nginx -t
sudo systemctl reload nginx
Step 4: Backend HTTPS Server
Backend server MUST already have:
- SSL certificate
- HTTPS enabled
Example backend:
Apache / NGINX / Kubernetes Ingress
NGINX Stream does NOT terminate SSL.
How It Works
Client connects:
https://example.com
NGINX Stream:
- Accepts TCP connection
- Forwards encrypted packets
Backend:
- Performs TLS handshake
- Decrypts traffic
SNI-Based SSL Passthrough (Multiple Domains)
You can route by SNI hostname.
Example:
stream {
map $ssl_preread_server_name $backend_name {
app1.example.com app1;
app2.example.com app2;
}
upstream app1 {
server 10.0.0.11:443;
}
upstream app2 {
server 10.0.0.12:443;
}
server {
listen 443;
proxy_pass $backend_name;
ssl_preread on;
}
}
What is ssl_preread?
NGINX reads:
- TLS SNI hostname
WITHOUT decrypting SSL.
Used for:
- Multi-domain passthrough
- Kubernetes ingress passthrough
Kubernetes Example
Used in:
- NGINX Ingress Controller
- TCP ingress
- TLS passthrough
Architecture:
Internet
|
Load Balancer
|
NGINX Stream
|
Kubernetes Service
Important Limitations
With SSL Passthrough, NGINX cannot:
- Read URL paths
- Inspect headers
- Use WAF rules
- Cache HTTP
- Modify requests
Because traffic stays encrypted.
SSL Termination vs Passthrough
| Feature | SSL Termination | SSL Passthrough |
| ---------------------- | --------------- | --------------- |
| SSL decrypted at NGINX | Yes | No |
| Backend sees HTTP | Yes | No |
| End-to-end encryption | No | Yes |
| URL routing | Yes | No |
| WAF possible | Yes | No |
Real Production Use Cases
Banking Systems
Strict end-to-end TLS.
Kubernetes
TLS passthrough ingress.
Database TLS
Secure PostgreSQL/MySQL traffic.
Multi-Tenant Platforms
SNI hostname routing.
SSL Passthrough means:
NGINX forwards encrypted traffic
Backend decrypts it
Best when you need:
- End-to-end encryption
- TCP/TLS proxying
- Kubernetes passthrough
- Secure internal infrastructure
In NGINX Stream, SSL certificates can be configured in two different ways, depending on whether you use:
- SSL Termination
- SSL Passthrough
1. SSL Passthrough (No Certificate in NGINX)
In SSL Passthrough:
Client --> NGINX Stream --> Backend HTTPS Server
NGINX does NOT decrypt traffic.
So:
- NO SSL certificate needed in NGINX
- Certificate stays on the backend server
Example:
stream {
upstream backend {
server 10.0.0.20:443;
}
server {
listen 443;
proxy_pass backend;
}
}
Certificate is configured on:
- Apache
- Backend NGINX
- Kubernetes ingress
- Application server
2. SSL Termination in NGINX Stream
Here, NGINX decrypts TLS traffic.
Architecture:
Client HTTPS
|
v
NGINX Stream (SSL Termination)
|
v
Backend TCP/HTTP
Now you MUST configure:
- SSL certificate
- Private key
inside NGINX Stream.
Stream SSL Configuration
Example:
stream {
upstream backend {
server 10.0.0.20:443;
}
server {
listen 443 ssl;
proxy_pass backend;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/private.key;
}
}
SSL Files
Usually:
/etc/nginx/ssl/fullchain.pem
/etc/nginx/ssl/private.key
Using Letβs Encrypt
With Letβs Encrypt:
sudo certbot certonly
Certificates are usually stored in:
/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/privkey.pem
Example with Letβs Encrypt
stream {
upstream app {
server 10.0.0.20:8443;
}
server {
listen 443 ssl;
proxy_pass app;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}
}
Enable TLS Versions
Example:
ssl_protocols TLSv1.2 TLSv1.3;
Configure Strong Ciphers
Example:
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
Full Production Example
stream {
upstream postgres_ssl {
server 10.0.0.11:5432;
server 10.0.0.12:5432;
}
server {
listen 5432 ssl;
proxy_pass postgres_ssl;
ssl_certificate /etc/nginx/ssl/postgres.pem;
ssl_certificate_key /etc/nginx/ssl/postgres.key;
ssl_protocols TLSv1.2 TLSv1.3;
}
}
Test Configuration
sudo nginx -t
Reload:
sudo systemctl reload nginx
Verify SSL
Test with OpenSSL:
openssl s_client -connect example.com:443
Important Difference
| Mode | SSL Certificate Location |
| --------------- | ------------------------ |
| SSL Passthrough | Backend Server |
| SSL Termination | NGINX Stream |
Real Use Cases
SSL Passthrough
Used when:
- End-to-end encryption required
- Kubernetes ingress passthrough
- Banking systems
SSL Termination
Used when:
- Centralized certificate management
- Load balancing HTTPS
- SSL offloading
Passthrough
NGINX forwards encrypted traffic
Backend handles SSL
Termination
NGINX decrypts SSL
NGINX needs certificate
Summary
Configuring SSL in NGINX Stream. NGINX Stream supports SSL in two ways:
SSL Passthrough
NGINX forwards encrypted traffic directly to the backend.
Client β NGINX Stream β Backend HTTPS Server
β
End-to-end encryption
β
Backend manages SSL certificates
β NGINX cannot inspect HTTP traffic
SSL Termination
NGINX decrypts SSL traffic and requires certificates configured locally.
Client β NGINX Stream (SSL) β Backend Server
Example:
server {
listen 443 ssl;
proxy_pass backend;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/private.key;
}
Key Difference
πΉ SSL Passthrough β Certificate on Backend
πΉ SSL Termination β Certificate on NGINX
Commonly used for:
- Kubernetes
- PostgreSQL/MySQL TLS
- Load Balancing
- Secure Infrastructure
- High Availability Systems

Top comments (0)