system-design · beginner
Proxy vs Reverse Proxy — Who Hides Whom
The Central Question
Consider two distinct network routing scenarios:
- Scenario A: An enterprise corporation wants to restrict 10,000 corporate employee laptops from accessing malicious phishing websites on the public internet, while caching outgoing file downloads to save WAN bandwidth.
- Scenario B: An online e-commerce platform (
checkoutlab.com) needs a stable public entry point to terminate TLS encryption, filter SQL injection attacks, and route incoming customer traffic across 50 private microservice containers without exposing container IP addresses to the internet.
Both scenarios require a middlebox intermediary known as a Proxy. However, the directions of traffic flow and the entities being protected are completely opposite.
A Forward Proxy represents clients making outbound requests to the internet. A Reverse Proxy represents servers receiving inbound requests from clients.
This lesson answers one central question: What is the key functional difference between a Forward Proxy (representing outbound clients) and a Reverse Proxy (representing inbound servers), and how do reverse proxies terminate TLS, sanitize X-Forwarded-For headers, and route traffic to backend microservices?
Topology Comparison: Forward vs. Reverse Proxy
The fundamental distinction between proxy types lies in who is being represented and who is being hidden:
flowchart TB
subgraph Forward Proxy Topology: Egress (Outbound Protection)
C1[Internal Client Laptops] --> FP[Forward Proxy / Corporate Gateway]
FP --> Net1[Public Internet / Target Servers]
Note1["Forward Proxy Hides CLIENT Identities from Internet Servers"]
end
subgraph Reverse Proxy Topology: Ingress (Inbound Protection)
C2[Public Internet Clients] --> RP[Reverse Proxy / Nginx / Gateway]
RP --> B1[Private App Server 1]
RP --> B2[Private App Server 2]
Note2["Reverse Proxy Hides SERVER Topology from Public Clients"]
end
Figure 1: Comparison of Forward Proxy (egress client protection) against Reverse Proxy (ingress server protection).
The "Who Hides Whom?" Operational Test
Engineers apply a simple 3-part test to categorize any proxy deployment:
flowchart TD
Q1{Who initiated the request?} -->|Internal Client| Q2{Who deployed the proxy?}
Q1 -->|External Public Client| RP[It is a REVERSE PROXY]
Q2 -->|Client Organization| FP[It is a FORWARD PROXY]
Q2 -->|Server Organization| RP
Figure 2: Decision tree for identifying proxy classification.
Proxy Classification Matrix
| Vector / Property | Forward Proxy | Reverse Proxy |
|---|---|---|
| Location | Sits near the Client (Client Network / Enterprise Egress). | Sits near the Server Tier (Data Center Edge / VPC Ingress). |
| Protected Entity | Protects and hides Client Devices. | Protects and hides Backend Application Servers. |
| Client Awareness | Client is explicitly configured to use the proxy. | Client is unaware of proxy (thinks proxy IS the origin server). |
| Primary Use Cases | Corporate web filtering, egress security, NAT, outbound caching. | TLS termination, load balancing, path routing, WAF, rate limiting. |
| Typical Software | Squid, Blue Coat, Zscaler. | Nginx, HAProxy, Envoy, Cloudflare, AWS ALB. |
Core Operational Responsibilities of a Reverse Proxy
In modern cloud architectures, application servers never expose raw sockets directly to the internet. Instead, all incoming connections hit a reverse proxy cluster performing five primary duties:
flowchart TD
Client[Public HTTPS Client] --> RP[Reverse Proxy Tier]
RP -->|1. TLS Termination| Duty1[Decrypt HTTPS -> Forward HTTP to VPC]
RP -->|2. Path-Based Routing| Duty2[Route /v1/orders to Order Pods]
RP -->|3. Load Balancing| Duty3[Distribute traffic across healthy nodes]
RP -->|4. Security & WAF| Duty4[Strip dangerous headers & block SQLi]
RP -->|5. Response Compression| Duty5[Gzip / Brotli compress responses]
Figure 3: Five core operational responsibilities of a production reverse proxy.
1. TLS Termination and SNI Routing
Executing Diffie-Hellman key exchanges and symmetric decryption consumes CPU cycles. A reverse proxy handles TLS handshakes at the edge, forwarding un-encrypted (or lightly re-encrypted) HTTP packets over high-speed private VPC networks to application pods.When a single reverse proxy cluster hosts multiple distinct HTTPS domain names on a single public IP address (such as api.checkoutlab.com and admin.checkoutlab.com), the proxy relies on Server Name Indication (SNI). SNI is a TLS extension where the client sends the target hostname in the un-encrypted ClientHello packet. This enables the reverse proxy to select the correct X.509 TLS certificate before completing the cryptographic handshake.
2. Path and Host Routing
A single public domain (`checkoutlab.com`) can route traffic to different microservices based on request URI path prefixes:https://checkoutlab.com/v1/orders$\rightarrow$ Routes to Order Service.https://checkoutlab.com/v1/catalog$\rightarrow$ Routes to Catalog Service.https://checkoutlab.com/static/*$\rightarrow$ Routes to Object Storage Bucket.
Connection Pooling and Keep-Alive Offloading
Opening and closing TCP connections for thousands of concurrent public clients creates severe socket allocation and CPU overhead on application servers.
Reverse proxies perform Connection Multiplexing and Keep-Alive Offloading:
flowchart LR
subgraph Public Client Tier
C1[1,000 Short-Lived Public Client Connections]
end
subgraph Reverse Proxy Layer
RP[Reverse Proxy Pool]
end
subgraph Private Upstream Tier
App[50 Persistent Keep-Alive TCP Connections to App Pods]
end
C1 -->|Short-Lived TLS Handshakes| RP
RP -->|Reuses Persistent Upstream Pool| App
Figure 4: Connection pooling multiplexing short-lived client calls over persistent upstream sockets.
How Keep-Alive Offloading Protects Microservices
The reverse proxy accepts thousands of short-lived client HTTPS connections at the edge. It maintains a small, fixed pool of persistent, pre-opened TCP `keepalive` sockets to internal application containers. Incoming HTTP requests are multiplexed over these pre-existing sockets, eliminating TCP handshake overhead on backend servers.Canary Deployments and Weighted Traffic Shifting
Reverse proxies act as the central control plane for shipping zero-downtime application updates using Canary Deployments:
flowchart TD
Client[Public Ingress Request] --> RP{Reverse Proxy Weighted Routing}
RP -->|95% Traffic Weight| V1[Stable Version v1.4.0 Upstream Cluster]
RP -->|5% Traffic Weight| V2[Canary Release v1.5.0 Upstream Cluster]
Figure 5: Weighted traffic splitting at the reverse proxy layer for canary testing.
Executing Zero-Downtime Releases
Instead of updating 100% of application pods at once, operators configure the reverse proxy to split incoming traffic by weight (e.g. 95% to `v1.4.0` and 5% to `v1.5.0`) or by HTTP header (`X-Canary: true`). Operators monitor real-time error rates on the 5% canary pool before gradually shifting 100% of traffic to the new version.Layer 4 vs. Layer 7 Proxy Inspection
Reverse proxies operate at two distinct layers of the OSI model:
flowchart LR
subgraph Layer 4 (Transport Proxy)
L4[L4 Proxy: HAProxy / AWS NLB] -->|Inspects TCP Ports & IP Headers Only| L4B[Forwards Raw TCP Stream without HTTP Parsing]
end
subgraph Layer 7 (Application Proxy)
L7[L7 Proxy: Nginx / Envoy / AWS ALB] -->|Decrypts & Inspects HTTP Headers & Body| L7B[Executes Header Sanitization, Path Routing, Cookies]
end
Figure 6: Structural differences between Layer 4 TCP proxies and Layer 7 HTTP proxies.
L4 vs. L7 Trade-Off Analysis
- Layer 4 Proxies (TCP/UDP): Inspect only IP addresses and port numbers. They do not decrypt HTTP or inspect headers, making them extremely fast ($O(1)$ packet forwarding) with ultra-low CPU overhead. Layer 4 proxies cannot modify HTTP headers or inspect payload contents.
- Layer 7 Proxies (HTTP/HTTPS): Decrypt TLS and parse full HTTP request payloads. They support complex path-based routing, JWT authentication, and header rewriting, but consume higher CPU memory per request.
Header Sanitization: The X-Forwarded-For Vulnerability
When a reverse proxy forwards a request to a backend application server, the backend sees the proxy's private IP address as the socket source, losing the original client's public IP address.
To preserve client identity, proxies append headers:
X-Forwarded-For: Chain of client and proxy IP addresses (client, proxy1, proxy2).X-Forwarded-Proto: Original protocol used by client (https).
sequenceDiagram
autonumber
actor Attacker as Malicious Client (IP: 198.51.100.4)
participant RP as Reverse Proxy (IP: 203.0.113.10)
participant App as Backend App (IP: 172.16.1.5)
Note over Attacker,RP: Attacker sends forged header: X-Forwarded-For: 127.0.0.1
Attacker->>RP: GET /admin (Header: X-Forwarded-For: 127.0.0.1)
Note over RP: SANITIZATION STEP!<br/>Proxy MUST overwrite or append real connecting IP!
RP->>App: GET /admin (Header: X-Forwarded-For: 198.51.100.4)
Note over App: App inspects X-Forwarded-For: 198.51.100.4.<br/>Denies Admin access! Attack Blocked!
Figure 7: Sequence diagram illustrating reverse proxy X-Forwarded-For header sanitization.
Complete Worked Example: CheckoutLab Nginx Reverse Proxy Config
Let's inspect the production Nginx reverse proxy configuration for the CheckoutLab platform (checkoutlab.com).
Production Nginx Reverse Proxy Configuration
# /etc/nginx/sites-available/checkoutlab.conf
upstream order_service_cluster {
server 172.16.1.10:8080 max_fails=3 fail_timeout=10s;
server 172.16.1.11:8080 max_fails=3 fail_timeout=10s;
keepalive 32; # Keep-alive connection pool to backends
}
server {
listen 443 ssl http2;
server_name api.checkoutlab.com;
# TLS Certificate Configuration
ssl_certificate /etc/letsencrypt/live/api.checkoutlab.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.checkoutlab.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Request Body Limit & Timeouts
client_max_body_size 10M;
proxy_read_timeout 60s;
# Route: /v1/orders -> Order Microservice Cluster
location /v1/orders {
proxy_pass http://order_service_cluster;
# Header Sanitization (Essential Security Settings)
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;
# Disable Buffering for Real-Time Responses
proxy_buffering off;
}
}
Failure Modes and Engineering Mitigations
| Failure Scenario | Root Cause | System Symptom | Detection Metric | Mitigation Strategy |
|---|---|---|---|---|
| 1. Un-Sanitized Header IP Spoofing | Reverse proxy appends client headers without stripping forged X-Forwarded-For inputs. | Attacker bypasses API rate limits and IP whitelist checks by spoofing headers. | Audit logs show administrative actions originating from 127.0.0.1. | Configure proxy to explicitly set $remote_addr as the initial element of X-Forwarded-For. |
| 2. Upstream Proxy Connection Timeout | Backend app pod freezes or crashes, holding open TCP sockets without returning bytes. | Proxy returns HTTP 504 Gateway Timeout to public clients. | Spikes in 504 status codes on edge metrics dashboards. | Enforce strict proxy_read_timeout (e.g. 5s-10s) and configure fast failover to alternate upstream pods. |
| 3. Proxy Buffer Exhaustion | Large JSON or file responses fill proxy memory buffers faster than clients can consume. | Proxy writes temporary response files to disk, causing severe latency spikes. | Elevated disk I/O metrics on reverse proxy instances. | Tune proxy_buffers and proxy_buffer_size memory allocation rules based on expected payload sizes. |
| 4. Single Reverse Proxy SPOF | Running a single Nginx instance fronting all backend microservices without redundancy. | Single Nginx VM crash takes down 100% of public application endpoints. | Total outage of all public domain routes. | Deploy reverse proxies behind Anycast DNS or an AWS Application Load Balancer in a Multi-AZ autoscaling group. |
What You Should Remember
- Forward Proxy = Client Protection: Forward proxies sit near clients, sending outbound requests to the internet while hiding client identities.
- Reverse Proxy = Server Protection: Reverse proxies front backend servers, terminating TLS, enforcing security, and hiding internal server topology.
- Reverse Proxies offload TLS and routing: Edge proxies handle expensive TLS 1.3 handshakes, URL path routing, and Gzip response compression.
- Keep-alive offloading saves sockets: Reverse proxies multiplex thousands of short-lived client calls over persistent upstream sockets.
- Always sanitize
X-Forwarded-For: Overwrite or append the true connecting socket IP at the edge to prevent header spoofing attacks.
Glossary of Terms
| Term | Definition |
|---|---|
| Forward Proxy | A proxy server that routes outbound requests on behalf of client devices to the internet. |
| Reverse Proxy | A proxy server that routes inbound internet requests to internal backend application servers. |
| TLS Termination | The process of decrypting HTTPS connections at the edge proxy before forwarding plain HTTP to internal networks. |
| SNI (Server Name Indication) | A TLS extension allowing a client to specify the target domain name during the handshake so the proxy presents the correct certificate. |
| Connection Pooling | Reusing a fixed set of persistent backend network connections to eliminate handshake overhead. |
| Upstream (Backend) | The internal application server or microservice cluster that receives proxied requests. |
| X-Forwarded-For | An HTTP request header field used to track the original IP address of a client connecting through a proxy. |
| Layer 7 Proxy | An application-layer proxy capable of inspecting HTTP headers, cookies, and URIs for routing decisions. |
Practice Scenario and Self-Assessment
Architecture Scenario
You are designing the edge ingress infrastructure for an online banking platform (`bank.com`).The platform consists of:
https://bank.com/api/v1/accounts(Account Microservice)https://bank.com/api/v1/transfers(Payment Microservice)https://bank.com/static/*(S3 Object Storage)
Questions:
- Design an Nginx reverse proxy routing specification to distribute incoming traffic across all three upstream targets.
- Detail how your proxy configuration enforces
X-Forwarded-Forheader sanitization to prevent malicious IP spoofing on financial endpoints.
Interactive Self-Assessment
A Forward Proxy represents outbound clients; a Reverse Proxy represents inbound servers.
Forward proxies use TCP while Reverse proxies use UDP exclusively.
Forward proxies handle TLS encryption while Reverse proxies cannot terminate TLS.
Reverse proxies require public IP addresses for all backend application containers.
To prevent attackers from supplying fake client IP headers to bypass IP-based security and rate limits.
To enable Gzip response payload compression on the backend server.
To decrypt TLS encryption packets before they reach the backend socket.
To resolve internal domain names to IPv6 addresses.
What to Learn Next
- Single Point of Failure (SPOF) — Identifying and Eliminating SPOFs: Learn how to make reverse proxy tiers highly available.
- API Gateway — Edge Entry for Microservices: Explore advanced reverse proxies with JWT auth and rate limiting.
- Load Balancing — Algorithms and Layers: Master load distribution algorithms across reverse proxy upstreams.
Track: Engineering Foundations
Previous: OSI Model — Seven Layers as a Debugging Map
By Shubham Jain