Networking Tutorial · Routing and Network Services · Lesson 20 of 28
Proxies and CDNs
Forward and reverse proxies, CDNs and edge caching, and the headers that carry the real client IP.
Forward and reverse proxies
- A forward proxy acts for clients: a company proxy that all outbound web traffic goes through.
- A reverse proxy acts for servers: NGINX, Envoy, a load balancer or a CDN that receives requests and forwards them to your app. It can terminate TLS, compress, cache, rate limit and route.
CDNs
A CDN (content delivery network) such as Amazon CloudFront, Azure Front Door, Google Cloud CDN or
Cloudflare runs reverse proxies in hundreds of locations. Users connect to a nearby edge, which serves cached
content or forwards the request to your origin over a fast, warm connection. Cache behaviour is controlled by
Cache-Control headers from your app.
The real client IP
Behind a proxy, your app sees the proxy's IP as the connection's source. Proxies add the original address
to a header, usually X-Forwarded-For (a comma-separated list, one entry per proxy) or the standard
Forwarded header. Clients can send fake values, so trust only the entries added by your own proxies:
import ipaddress
TRUSTED_PROXIES = [ipaddress.ip_network("10.0.0.0/16")] # our load balancers
def client_ip(peer, x_forwarded_for):
chain = [p.strip() for p in x_forwarded_for.split(",")] + [peer]
for hop in reversed(chain): # walk back from the closest hop
if not any(ipaddress.ip_address(hop) in net for net in TRUSTED_PROXIES):
return hop
return chain[0]
# A client tries to spoof 1.2.3.4; our load balancer (10.0.0.12) appended the real address.
print(client_ip("10.0.0.12", "1.2.3.4, 203.0.113.50"))
print(client_ip("10.0.0.12", "198.51.100.8"))
Output
203.0.113.50 198.51.100.8
Test yourself
Why shouldn't you use the first entry of X-Forwarded-For as the client IP?
Clients can put any value there; only entries added by your own proxies can be trustedIt is always the load balancer's IPIt contains ports, not IPsIt is encrypted
Show answer
Answer: Clients can put any value there; only entries added by your own proxies can be trusted
Each proxy appends to the header. Walk from the right, skipping your own proxies, to find the first address you didn't add.