Topic Overview
Proxy vs Reverse Proxy
Understand the difference between forward proxies (client-side) and reverse proxies (server-side), their use cases, and when to use each.
Proxies act as intermediaries between clients and servers. Forward proxies represent clients, while reverse proxies represent servers. Understanding the difference is crucial for network architecture and security.
Forward Proxy (Client-Side Proxy)
Definition: A forward proxy sits between clients and the internet, representing clients to servers.
Direction: Client → Proxy → Internet
Client Forward Proxy Internet
| | |
|---Request--------->| |
| |---Request------->|
| |<--Response-------|
|<--Response---------| |
Characteristics:
- Client knows proxy: Client is configured to use proxy
- Server doesn't know client: Server sees proxy's IP, not client's
- Hides client identity: Client IP is hidden from servers
- Client-side: Located near clients or in client network
Reverse Proxy (Server-Side Proxy)
Definition: A reverse proxy sits between the internet and servers, representing servers to clients.
Direction: Internet → Reverse Proxy → Servers
Internet Reverse Proxy Backend Servers
| | |
|---Request--------->| |
| |---Request------->|
| |<--Response-------|
|<--Response---------| |
Characteristics:
- Client doesn't know backend: Client thinks it's talking to reverse proxy
- Server knows proxy: Backend servers see proxy's IP
- Hides server identity: Backend server IPs are hidden from clients
- Server-side: Located in front of servers
Key Differences
| Aspect | Forward Proxy | Reverse Proxy |
|---|---|---|
| Location | Client-side | Server-side |
| Represents | Clients | Servers |
| Client awareness | Client knows proxy | Client doesn't know backend |
| Server awareness | Server doesn't know client | Server knows proxy |
| Hides | Client IP from servers | Server IPs from clients |
| Use case | Privacy, filtering, caching | Load balancing, SSL termination, security |
Forward Proxy Use Cases
1. Privacy and Anonymity
Hide client IP addresses from servers.
Client (192.168.1.100) → Proxy (203.0.113.1) → Server
Server sees: 203.0.113.1 (proxy's IP)
Server doesn't see: 192.168.1.100 (client's IP)
2. Content Filtering
Block access to certain websites.
Client → Proxy → Internet
Proxy checks: Is website allowed?
If blocked: Return error
If allowed: Forward request
3. Caching
Cache frequently accessed content.
Client → Proxy → Internet
Proxy checks: Is content cached?
If cached: Return from cache
If not: Fetch from internet, cache, return
4. Bypass Restrictions
Access content restricted by location.
Client (Country A) → Proxy (Country B) → Server
Server sees: Proxy in Country B
Client can access: Content available in Country B
Reverse Proxy Use Cases
1. Load Balancing
Distribute requests across multiple backend servers.
Client → Reverse Proxy → Backend Servers
├─ Server 1
├─ Server 2
└─ Server 3
2. SSL Termination
Terminate SSL/TLS at reverse proxy.
Client (HTTPS) → Reverse Proxy (decrypts) → Backend (HTTP)
3. Caching
Cache responses from backend servers.
Client → Reverse Proxy → Backend
(cached response)
4. Security
Hide backend server IPs, provide DDoS protection.
Client → Reverse Proxy (public IP) → Backend (private IP)
5. Request Routing
Route requests to different backend services.
Client → Reverse Proxy → /api/users → user-service
→ /api/orders → order-service
Examples
Forward Proxy (Squid)
# Squid forward proxy configuration
http_port 3128
# Access control
acl local_net src 192.168.1.0/24
http_access allow local_net
http_access deny all
# Caching
cache_dir ufs /var/spool/squid 100 16 256
cache_mem 256 MB
# Logging
access_log /var/log/squid/access.log
Client configuration:
# Set proxy in browser or environment
export http_proxy=http://proxy.example.com:3128
export https_proxy=http://proxy.example.com:3128
Reverse Proxy (Nginx)
# Nginx reverse proxy configuration
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# SSL termination
listen 443 ssl;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
}
Forward Proxy Implementation
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.request
class ForwardProxyHandler(BaseHTTPRequestHandler):
def do_GET(self):
# Get target URL from request
target_url = self.path
# Forward request to target
try:
response = urllib.request.urlopen(target_url)
# Send response to client
self.send_response(200)
self.send_header('Content-Type', response.headers.get('Content-Type'))
self.end_headers()
self.wfile.write(response.read())
except Exception as e:
self.send_error(500, str(e))
def log_message(self, format, *args):
# Log client IP (hidden from target server)
print(f"Client {self.client_address[0]} requested {args[0]}")
# Start forward proxy server
server = HTTPServer(('0.0.0.0', 8080), ForwardProxyHandler)
server.serve_forever()
Reverse Proxy Implementation
from http.server import HTTPServer, BaseHTTPRequestHandler
import requests
from urllib.parse import urlparse
class ReverseProxyHandler(BaseHTTPRequestHandler):
backend_servers = [
'http://192.168.1.10:8080',
'http://192.168.1.11:8080',
'http://192.168.1.12:8080'
]
current_server = 0
def do_GET(self):
# Select backend server (round robin)
backend = self.backend_servers[self.current_server]
self.current_server = (self.current_server + 1) % len(self.backend_servers)
# Forward request to backend
try:
target_url = f"{backend}{self.path}"
response = requests.get(target_url, headers=dict(self.headers))
# Send response to client
self.send_response(response.status_code)
for header, value in response.headers.items():
self.send_header(header, value)
self.end_headers()
self.wfile.write(response.content)
except Exception as e:
self.send_error(502, str(e))
# Start reverse proxy server
server = HTTPServer(('0.0.0.0', 80), ReverseProxyHandler)
server.serve_forever()
Common Pitfalls
- Confusing forward and reverse: Not understanding which represents what. Fix: Forward = client-side, Reverse = server-side
- Not handling X-Forwarded-For: Backend doesn't know real client IP. Fix: Set X-Forwarded-For header
- SSL termination issues: Backend expects HTTPS but receives HTTP. Fix: Configure backend for HTTP when using SSL termination
- Session affinity: Requests not routed to same backend. Fix: Use sticky sessions (cookie-based or IP-based)
- Health checks: Not monitoring backend health. Fix: Implement health checks, remove unhealthy backends
- Caching issues: Stale content served. Fix: Set appropriate cache headers, implement cache invalidation
Interview Questions
Beginner
Q: What is the difference between a forward proxy and a reverse proxy?
A:
Forward Proxy (Client-Side):
- Location: Between clients and internet
- Represents: Clients to servers
- Client awareness: Client knows proxy (configured to use it)
- Server awareness: Server doesn't know real client (sees proxy's IP)
- Hides: Client IP from servers
- Use case: Privacy, content filtering, caching, bypass restrictions
Reverse Proxy (Server-Side):
- Location: Between internet and servers
- Represents: Servers to clients
- Client awareness: Client doesn't know backend servers
- Server awareness: Backend servers see proxy's IP
- Hides: Backend server IPs from clients
- Use case: Load balancing, SSL termination, security, caching
Example:
Forward Proxy:
Client → Proxy → Internet
(Client knows proxy, server doesn't know client)
Reverse Proxy:
Internet → Proxy → Backend Servers
(Client doesn't know backend, backend knows proxy)
Intermediate
Q: When would you use a forward proxy vs a reverse proxy? Explain with examples.
A:
Use Forward Proxy When:
-
Privacy/Anonymity
# Hide client IP from servers Client (192.168.1.100) → Proxy → Server Server sees: Proxy's IP, not client's IP -
Content Filtering
# Corporate network: Block social media Client → Proxy → Internet Proxy checks: Is website allowed? If blocked: Deny access -
Caching
# Cache frequently accessed content Client → Proxy → Internet If cached: Return from cache (fast) If not: Fetch, cache, return -
Bypass Geo-restrictions
# Access content from different country Client (US) → Proxy (UK) → Server Server sees: UK IP, serves UK content
Use Reverse Proxy When:
-
Load Balancing
# Distribute requests across servers Client → Reverse Proxy → Backend Servers ├─ Server 1 ├─ Server 2 └─ Server 3 -
SSL Termination
# Terminate SSL at proxy Client (HTTPS) → Reverse Proxy (decrypts) → Backend (HTTP) -
Security
# Hide backend IPs, DDoS protection Client → Reverse Proxy (public) → Backend (private) -
Request Routing
# Route to different services /api/users → user-service /api/orders → order-service
Key Difference:
- Forward Proxy: Client-side, hides client from servers
- Reverse Proxy: Server-side, hides servers from clients
Senior
Q: Design a proxy architecture for a large organization that needs both forward proxies for employee internet access and reverse proxies for internal services. How do you handle scaling, security, and monitoring?
A:
class EnterpriseProxyArchitecture {
private forwardProxies: ForwardProxy[];
private reverseProxies: ReverseProxy[];
private securityLayer: SecurityLayer;
private monitoring: MonitoringSystem;
constructor() {
// Forward proxies for employee internet access
this.forwardProxies = [
new ForwardProxy({ region: 'us-east' }),
new ForwardProxy({ region: 'us-west' }),
new ForwardProxy({ region: 'eu-west' })
];
// Reverse proxies for internal services
this.reverseProxies = [
new ReverseProxy({ tier: 'web' }),
new ReverseProxy({ tier: 'api' }),
new ReverseProxy({ tier: 'internal' })
];
this.securityLayer = new SecurityLayer();
this.monitoring = new MonitoringSystem();
}
// Forward Proxy Architecture
class ForwardProxy {
private cache: Cache;
private filter: ContentFilter;
private auth: Authentication;
async handleRequest(request: ClientRequest): Promise<Response> {
// 1. Authentication
const user = await this.auth.authenticate(request);
if (!user) {
return this.deny(401);
}
// 2. Content Filtering
if (!this.filter.isAllowed(request.url, user)) {
return this.deny(403, 'Content blocked');
}
// 3. Caching
const cached = await this.cache.get(request.url);
if (cached) {
return cached;
}
// 4. Forward to internet
const response = await this.forwardToInternet(request);
// 5. Cache response
if (this.cache.shouldCache(response)) {
await this.cache.set(request.url, response);
}
return response;
}
}
// Reverse Proxy Architecture
class ReverseProxy {
private loadBalancer: LoadBalancer;
private sslTerminator: SSLTerminator;
private healthMonitor: HealthMonitor;
async handleRequest(request: InternetRequest): Promise<Response> {
// 1. SSL Termination
if (request.isHTTPS()) {
request = await this.sslTerminator.terminate(request);
}
// 2. Security Checks
if (!this.securityLayer.isAllowed(request)) {
return this.deny(403);
}
// 3. Route to backend
const backend = await this.loadBalancer.select(request);
// 4. Health check
if (!this.healthMonitor.isHealthy(backend)) {
// Try next backend
backend = await this.loadBalancer.selectNext(request);
}
// 5. Forward to backend
const response = await backend.handle(request);
// 6. Add headers
response.setHeader('X-Proxy', 'reverse-proxy');
return response;
}
}
// Security Layer
class SecurityLayer {
async isAllowed(request: Request): Promise<boolean> {
// DDoS protection
if (await this.isDDoS(request)) {
return false;
}
// Rate limiting
if (await this.isRateLimited(request)) {
return false;
}
// WAF (Web Application Firewall)
if (await this.waf.isBlocked(request)) {
return false;
}
return true;
}
}
// Monitoring
class MonitoringSystem {
async monitor(): Promise<Metrics> {
return {
forwardProxy: {
requests: await this.getForwardProxyMetrics(),
cacheHitRate: await this.getCacheHitRate(),
blockedRequests: await this.getBlockedRequests()
},
reverseProxy: {
requests: await this.getReverseProxyMetrics(),
backendHealth: await this.getBackendHealth(),
latency: await this.getLatency()
}
};
}
}
}
Architecture:
Internet Access (Forward Proxy):
Employees → Forward Proxies → Internet
(Filtering, Caching, Privacy)
Internal Services (Reverse Proxy):
Internet → Reverse Proxies → Internal Services
(Load Balancing, SSL, Security)
Features:
- Forward proxies: Employee internet access with filtering and caching
- Reverse proxies: Internal service exposure with load balancing
- Security: DDoS protection, WAF, rate limiting
- Monitoring: Track metrics, health, performance
- Scaling: Multiple proxies per region/tier
- High availability: Redundancy, failover
Key Takeaways
- Forward Proxy: Client-side, represents clients, hides client IP from servers
- Reverse Proxy: Server-side, represents servers, hides server IPs from clients
- Forward proxy use cases: Privacy, content filtering, caching, bypass restrictions
- Reverse proxy use cases: Load balancing, SSL termination, security, request routing
- Key difference: Forward = client knows proxy, Reverse = client doesn't know backend
- Implementation: Use appropriate headers (X-Forwarded-For), handle SSL termination, implement health checks
- Best practices: Monitor performance, implement security layers, use caching appropriately, ensure high availability