TL;DR
You can normally find the real client IP as the first entry in the X-Forwarded-For
header, but you cannot trust it.
When using Cloud Run (or Cloud Functions gen 2), you can only trust the last entry (appended by the Cloud Run orchestrator itself).
Additionally, I can't find any way to trust the IP address if you are proxying Firebase Hosting.
If you need to trust the IP address
As explained by this answer https://stackoverflow.com/a/48032910/1513557, you can normally find the client's IP address by taking the first address from the X-Forwarded-For
header, which is a comma-separated list of addresses, where each proxy along the way appends the client address it sees.
However the requester can (maliciously) add the X-Forwarded-For
header themselves, and each proxy will append to it. In this way the requester can tell you whatever IP address they want.
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 by the requester or any untrusted proxy along the way.
If you are using Firebase Hosting
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.
You may then be tempted to verify that the request is actually coming from Fastly/Firebase Hosting CDN by checking that the last IP address in the list is a trusted server (it appears that the request from the Fastly CDN to Cloud Run uses one of Google's IP ranges), but that doesn't rule out that the request could be coming from a malicious client hosted on Fastly or Google Cloud services.
This means you can't do it. You can only trust that last address, so you cannot proxy via Firebase Hosting. Unless the GCP/Firebase Hosting teams provide some "trusted header" in the future.