Trusted headers for client IP address via Firebase Hosting
Context: from a backend running on Cloud Run/Cloud Functions, how to determine client IP address, when you need to TRUST it for IP-address based access restrictions.
You can normally find the real client IP as the first entry in the X-Forwarded-For header, but you cannot trust it.
If you are using Cloud Run (or Cloud Functions gen 2), then as far as I can tell the Cloud Run orchestrator always sits as a proxy in front of your container. This means you can trust the last entry in X-Forwarded-For as this is the client IP seen by Cloud Run itself. The last address is the only address you can trust. Any preceeding addresses in the list could have been provided/spoofed by the requester themselves or any untrusted proxy along the way.
If you are proxying the the Cloud Run container (or Cloud Function) behind Firebase hosting, then the last address in the list is the Fastly CDN proxy, not the original client address. You might be tempted to use the second-to-last address (or the Fastly-Client-IP header), but you cannot trust this.
If the requester learns the direct address of your Cloud Run container (e.g. <your-service>.a.run.app) then they can make the request directly, and spoof either of those headers, telling you whatever address they want to.
In short, there needs to be some coordination between Cloud Run and Firebase Hosting for Cloud Run to provide some "trusted header". When a request reaches Cloud Run via Firebase Hosting the two need to authenticate themselves so that Cloud Run can provide the real client IP as seen by Firebase Hosting, only if the request actually came from legitimate Firebase Hosting.
Without this, Firebase Hosting cannot be used as a proxy when IP-address based authentication is required.
-
Dennis Kugelmann commented
Maybe Firebase Hosting might not be the best solution here...
Cloud Load Balancer or Apigee might provider better controls here