caw caw - 1 year ago 172
HTTP Question

Get client's real IP address on Heroku

On Heroku Cedar, I wanted to get the client's IP. First attempt:


This does not work, of course, because all requests are passed through proxies. So the alternative was to use:


But this is not quite safe, is it?

If it contains only one value, I take this. If it contains more than one value (comma-separated), I could take the first one.

But what if someone manipulates this value? I cannot trust
as I could with
. And there is no list of trusted proxies that I could use, either.

But there must be some way to reliably get the client's IP address, always. Do you know one?

In their docs, Heroku describes that
is "the originating IP address of the client connecting to the Heroku router".

This sounds as if Heroku could be overwriting the
with the originating remote IP. This would prevent spoofing, right? Can someone verify this?

caw caw
Answer Source

From Jacob, Heroku's Director of Security at the time:

The router doesn't overwrite X-Forwarded-For, but it does guarantee that the real origin will always be the last item in the list.

This means that, if you access a Heroku app in the normal way, you will just see your IP address in the X-Forwareded-For header:

$ curl
  "origin": "",

If you try to spoof the IP, your alleged origin is reflected, but - critically - so is your real IP. Obviously, this is all we need, so there's a clear and secure solution for getting the client's IP address on Heroku:

$ curl -H"X-Forwarded-For:"
  "origin": ","

This is just the opposite of what is described on Wikipedia, by the way.

PHP implementation:

function getIpAddress() {
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ipAddresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        return trim(end($ipAddresses));
    else {
        return $_SERVER['REMOTE_ADDR'];
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download