Forward vs Reverse Proxies: Direction Matters
Who Hired the Middleman?
A Proxy is just a server that sits between a Client and a Server. The difference depends on who owns it and who it protects.
1. Forward Proxy (The Client’s Agent)
- Analogy: A Hollywood Agent. The Actor (Client) doesn’t talk to the Studio (Server) directly. The Agent talks for them.
- Owner: The Client (or their company/ISP).
- Goal: To protect the Client.
- Use Cases:
- VPN: Hides the Client’s IP address. The Server sees the Proxy’s IP.
- Censorship Bypass: Access blocked sites through the proxy.
- Content Filtering: Corporate firewalls blocking Facebook.
- Direction: Outbound traffic (from Intranet to Internet).
2. Reverse Proxy (The Server’s Bodyguard)
- Analogy: A VIP’s Bodyguard. You (Client) can’t talk to the VIP (Server) directly. You talk to the Bodyguard.
- Owner: The Server (the website owner).
- Goal: To protect the Server.
- Use Cases:
- Load Balancing: Distributing traffic across multiple servers.
- Security: Hiding the backend Server’s IP to prevent direct attacks.
- SSL Termination: Handling encryption so the backend doesn’t have to.
- Caching: Serving static files (see CDNs).
- API Management: Rate limiting and Auth (see API Gateway).
- Direction: Inbound traffic (from Internet to Intranet).
Deep Dive: Security & TLS Fingerprinting
Reverse Proxies aren’t just dumb pipes. They are intelligent guards. One advanced technique they use is JA3 (TLS Fingerprinting).
- The Problem: Bots can spoof
User-Agent: Chrome. But their SSL handshake looks different (different cipher suites, extensions). - The Solution: The Reverse Proxy (e.g., Cloudflare) analyzes the raw packets of the “Client Hello” TLS message.
- Result: It can identify that a client claims to be an iPhone but performs an SSL handshake like a Python script. BLOCK!
Deep Dive: The Sidecar Proxy (Service Mesh)
In modern Microservices (Kubernetes), we have a third type: The Sidecar. It is a Reverse Proxy attached to every single service instance.
- Mechanism: It runs on
localhostinside the same Pod as the application container. - The Magic: The application talks to
localhost:8080, thinking it’s talking to another service. The Sidecar intercepts this, handles Service Discovery, Retries, Circuit Breaking, and mTLS (Mutual TLS), then forwards it to the destination Sidecar.
Why use a Sidecar?
It decouples Networking Logic from Business Logic.
- Without Sidecar: Every Java/Python/Go service needs libraries for Retries, Circuit Breaking, and Tracing.
- With Sidecar: The app code is simple. Envoy handles the complexity.
Example: Envoy Sidecar Config
This is how a Sidecar defines an “Upstream” (Backend) service.
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 10000 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: service_google }
clusters:
- name: service_google
connect_timeout: 0.25s
type: LOGICAL_DNS
# Comment: Envoy will resolve 'google.com' and LB across IPs
load_assignment:
cluster_name: service_google
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: google.com
port_value: 443
Battle of the Proxies: Nginx vs HAProxy vs Traefik vs Envoy
Which tool should you use?
| Feature | Nginx | HAProxy | Traefik | Envoy |
|---|---|---|---|---|
| Architecture | Process-based (Workers) | Event-driven (Single Process) | Go-based (Single Binary) | C++ Thread-based |
| Role | Web Server + LB | Pure LB | Kubernetes Ingress | Service Mesh Sidecar |
| Performance | High | Extreme (1M+ req/s) | Medium (Go GC overhead) | High |
| Hot Reload | Process restart | Seamless | Automatic (Watches Docker) | Seamless (xDS API) |
| Observability | Basic (Logs) | Good (Stats page) | Good (Dashboard) | Best in Class |
| Best For | Static Files, Standard LB | Edge TCP/HTTP LB | Docker/K8s Ingress | Microservices Mesh |
[!TIP] Interview Tip: “I’d use Traefik for a simple Docker Swarm/K8s setup because it auto-discovers containers. I’d use Envoy if I need a complex Service Mesh with deep observability.”
Connection Pooling: The Hidden Performance Lever
Every time a Load Balancer forwards a request to a backend server, it must establish a TCP connection. This involves the 3-way handshake (SYN, SYN-ACK, ACK), which adds ≈1-3ms of latency.
The Problem: Thundering Connections
If your LB closes the connection after every request (No Keep-Alive), you pay the handshake cost for every single request.
Example:
- 10,000 requests/sec
- 1ms handshake per request
- = 10 seconds of CPU time wasted just on handshakes
Solution: Connection Pooling
The LB maintains a pool of persistent connections to each backend server.
Mechanism:
- When a request arrives, the LB reuses an existing connection from the pool
- After the response, the connection goes back to the pool (not closed)
- Idle connections are reaped after a timeout (e.g., 60s)
Performance Impact: 5-10x reduction in latency for short requests.
Pool Sizing Formula
Pool Size per Backend = (Peak RPS × Avg Response Time) / Number of LB instances
Example:
- Peak: 5000 RPS
- Avg Response: 50ms (0.05s)
- LB instances: 2
Pool Size = (5000 × 0.05) / 2 = 125 connections per backend
Trade-off: Too large → wasted memory. Too small → connection starvation (requests queue).
HTTP Keep-Alive Configuration
# Nginx: Enable connection pooling to backends
upstream backend {
server 10.0.1.10:8080;
keepalive 128; # Pool size
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # Remove close header
}
}
Interview Insight: AWS ELB automatically pools connections. Google Cloud LB uses a default pool of 100 connections per backend.
Interactive Demo: The Identity Switcher
Visualize the flow of traffic and who is being protected.
- Forward Proxy Mode: Protects the User (Mask). The Internet doesn’t know who the User is.
- Reverse Proxy Mode: Protects the Server (Shield). The User doesn’t know who the Server is.
- Connection Pooling: Visualize the handshake overhead vs pooling.
- Firewall Mode: The Reverse Proxy detects a threat (Bot) and BLOCKS it before it reaches the server.
Summary
- Forward Proxy: Client-side. For Anonymity (VPN).
- Reverse Proxy: Server-side. For Scale and Security (Load Balancer).
- See Network Fundamentals for more on Firewalls.