Skip to content
DnsLister Forum

Where domain hunters compare notes

Building a dynamic reverse proxy for AI bots almost handed our internal AWS metadata to an SSRF exploit. Here is how we hard-blocked it in Go.

We were trying to solve a seemingly simple routing problem and almost built a massive footgun.

The baseline requirement was straightforward: we needed a reverse proxy at the edge. If human traffic hits the domain, pass it intact to our legacy backend. If an AI crawler (Claude, Perplexity) knocks, intercept it and serve a structured AEO payload like llms.txt.

Our initial iteration just inspected the User-Agent and relied on the Host and X-Forwarded-Host headers to construct the upstream TARGET_URL. Huge mistake.

Within days of testing, we noticed malicious scrapers manipulating the headers, attempting to force our proxy to fetch 169.254.169.254/latest/meta-data/ (AWS instance credentials) and scan our internal 10.x.x.x subnets. We were basically building a free SSRF pivot point for attackers to map our VPC.

We had a "nuke it from orbit" eureka moment. Application-level regex sanitization wasn't going to cut it. The runtime itself needed to be entirely hostile to the attacker.

Here is how we completely locked down the execution boundary:

Strict Route Sanitization in Go We threw out the regex soup. We hardcoded a strict, deterministic allowlist for upstream routing and explicitly stripped outbound host headers. If the payload destination doesn't match the exact internal IP of the legacy backend, the Go engine drops the connection (403) before allocating memory. No DNS resolution fallbacks, no dynamic parsing.

The Scratch Container Dead-End This was the real lifesaver. We ditched Debian and Alpine entirely. We compiled our Go engine as a statically linked binary and shoved it into a sub-20MB scratch Docker image. If an SSRF payload somehow bypasses the routing logic, there is literally nothing to execute in the container. No /bin/sh, no curl, no wget. It is a total dead end for lateral movement.

Manual TLS Certificate Injection The absolute biggest PITA with scratch images is doing secure HTTPS egress, because you have no OS package manager to handle root CAs. We had to manually inject ca-certificates natively into the Docker build step to enforce external TLS connections without opening any OS-level attack vectors.

We ended up packaging this entire locked-down proxy into a deployable middleware in our lab (we call it AgentBridge), because patching legacy proxies to handle crawler routing without introducing SSRF holes was becoming a massive time sink for our senior devs.

How are you guys isolating your reverse proxies when routing inbound bot traffic? Are you just leaning heavily on external WAFs, or are you strictly hardening the container runtime at the edge?

Source: r/aeo · by /u/Forsaken-Internal-33

Leave a Reply

Your email address will not be published. Required fields are marked *