Hi everyone,
I’m building a small Node.js service on Cloud Run and want to limit how many
requests one client IP can make. I’m trying to understand which address I can
trust, since callers can supply their own X-Forwarded-For header.
Requests go directly to Cloud Run’s default run.app URLs. I haven’t added a
load balancer, Firebase Hosting rewrite, custom domain or reverse proxy. The
test service uses gen1 in us-central1, with HTTP/1.1 to the container.
I tested both default URL forms: the one containing the project number and the
hash-based a.run.app URL. Both gave the same pattern:
Header I sent: (none)
Header received: OBSERVED_IP
Header I sent: 192.0.2.1
Header received: 192.0.2.1, OBSERVED_IP
Header I sent: 192.0.2.1, 198.51.100.2
Header received: 192.0.2.1, 198.51.100.2, OBSERVED_IP
The example addresses are deliberately fake. OBSERVED_IP replaces the actual
address in the results; I haven’t independently confirmed it is my outgoing
public IP. The socket’s remote address was an internal address.
**Is the last address in this header added by Cloud Run in a way the caller
cannot forge, and is it safe to use that address for IP-based rate limiting?
**
My test service currently requires IAM authentication. The eventual mobile
endpoint would allow requests through Cloud Run IAM and validate Firebase App
Check in the application. Does that change the answer? Are there differences
between the two default URLs, or with IPv6 or HTTP/2 clients?
I’ve read the Cloud Run container contract
and the load-balancer header documentation,
but I’m unsure which rule applies to direct run.app requests.
I’d appreciate a documentation link or clarification of the supported behavior.
If using the last address isn’t reliable, what would you recommend for this
setup?
Thanks for your help!