jelius/infra

CDN & Origin Shielding

Edge caching and strict origin access control using AWS CloudFront.

View on Git

My infrastructure uses AWS CloudFront as the CDN in front of web traffic that needs edge caching—specifically, the static assets served from cdn.jelius.dev. CloudFront does the usual CDN magic: it terminates the TLS connection geographically close to the user, serves from the cache, and only bothers my actual VPS on a cache miss.

This is great for latency, but it introduces a fun new problem: once you have a shiny CDN acting as your front door, you have to make absolutely sure nobody can sneak in through the back window (reaching the origin server directly).

Quick tangent: All my actual HTML/page traffic sits separately behind Cloudflare in orange-cloud (proxied) mode. That is a completely distinct path from this CloudFront setup. They just both happen to point to the same poor underlying VPS.

Domain Configuration

  • CDN Domain: cdn.jelius.dev — This is CloudFront's CNAME, covered by an AWS ACM certificate so visitors see a secure, matching hostname.
  • Origin Domain: Instead of minting some obvious origin.jelius.dev DNS record, I just point CloudFront to the exact same subdomain I use for my secure shell access. It just hits it over HTTPS (port 443) instead of TCP port 69. Reusing an existing A record means one less DNS entry for me to maintain. CloudFront doesn't care what the hostname is, as long as it resolves and has a valid cert behind it.

Origin TLS & Certificate Rotation

  • Issuance: I use certbot in standalone mode to get the origin's certificate. Standalone mode means certbot briefly spins up its own tiny web server to complete the HTTP-01 ACME challenge. Usually, the catch here is that you have to shut down your reverse proxy to free up the port. But I cheat. I configured Caddy to explicitly disable HTTP-to-HTTPS redirects (auto_https disable_redirects), meaning Caddy only listens on port 443 for HTTPS. Port 80 sits entirely empty—seriously, lsof -i :80 returns absolutely nothing—and is exclusively reserved for Certbot.
  • Automation: A cron job handles the renewals. Let's Encrypt certificates last 90 days, and by convention, certbot renew only actually does anything if the cert is expiring in the next 30 days. And because I permanently left port 80 vacant, the cron job can quietly spin up Certbot in the background whenever it needs to, without ever having to shut down Caddy or drop active origin connections.

For the exact underlying renewal logic, just read the official Certbot Renewal Documentation. I'm not going to reproduce it here because they maintain it better than I ever will.

Origin Shielding (Direct Access Prevention)

Even with a CDN in front, my origin's IP and direct hostname aren't actually secret. Certificate Transparency logs are essentially public snitches—the moment a cert is issued for my origin, it gets logged for the whole internet to see. Origin shielding is how I make finding the origin completely useless.

The Verification Handshake

  1. Edge Injection: CloudFront is configured to inject a pre-shared cryptographic secret into a custom HTTP header on every single request it forwards to my origin.
  2. Origin Inspection: My origin's reverse proxy (Caddy) intercepts every inbound HTTPS request and checks for that exact header and secret value before it does anything else.
  3. Aggressive Drop: If a request is missing the header, or the secret is wrong, Caddy does not give you a polite 403 Forbidden. Instead, it aggressively closes the underlying socket/file descriptor, violently resetting the TCP connection mid-handshake.

Why not just use a normal HTTP error code? Because returning a 403 proves to automated scanners that a server exists, is configured, and is willing to speak HTTP over TLS. It's fingerprintable. Dropping the connection outright denies them that confirmation. To a scanner, my server just looks dead. (If you are coming from the Nginx world, this is basically the non-standard return 444; pseudo-status).

Simulating a Bypass Attempt

If you try to bypass CloudFront and hit the origin directly with curl, here is exactly what happens:

$ curl -I https://<ORIGIN_DOMAIN>
curl: (92) HTTP/2 stream 1 was not closed cleanly: INTERNAL_ERROR (err 2)

That INTERNAL_ERROR is curl's way of crying that the server slammed the door at the TCP/stream level before it could even finish the HTTP exchange.

Defense in Depth

Is this bulletproof? No. If someone manages to leak my custom header value, they can bypass the CDN and hit the origin directly. But this mechanism is really just about hiding the server from blind scanning and casual discovery. I am not serving classified state secrets through a CDN; I'm serving static assets. If someone bypasses it, the only real threat is a "denial-of-wallet" attack by running up my VPS egress costs.

On this page