So itβs the opposite of what the normal behavior is, meaning the real client IP is guaranteed to be the last in the list. I probably should have a condition to get the IP based on this logic only if the app is hosted in heroku, then use the standard express way otherwise.
> meaning the real client IP is guaranteed to be the last in the list.
The last entry in the list is simply the IP address of whatever is making the request to Heroku. In my example, that's Cloudflare, being a proxy. Heroku simply appends the originating IP address (coming from a proxy) to the header which is what you would expect.
The Stack Overflow answer is addressing X-Forwarded-For spoofing, something you don't care about for geoip lookup. Someone could prefix 8.8.8.8 to the header before making their request, thus "X-Forwarded-For: 8.8.8.8, <Real IP>, <Cloudflare IP>", and it's inconsequential that your service will return results for 8.8.8.8 instead of <Real IP>.
The SO answer is wrong that this is Heroku-specific behavior. Heroku is simply appending the originating IP address to the header.
Obviously you can push a route to production that logs req.headers to see for yourself to nip this in the bud.
If we extend the scenario from
hombre_fatal's example to include IP spoofing like in that wikipedia article you linked, you end up with
IP: <Heroku's load balancer addr>
X-Forwarded-For: <Spoofed addr>, <Real user addr>, <Cloudflare addr>
So you either need to know the number of proxies that you trust that are in between you and the user, or you need to know the IP addresses of those trusted proxies, in order to determine which parts of X-Forwaded-For to trust.
Example, if your app was on Heroku behind Cloudflare, the request will look like this:
IP: <Heroku's load balancer addr>
X-Forwarded-For: <Real user addr>, <Cloudflare addr>
Your code, as written, will be geolocating the Cloudflare node.