Getting The Real Client IP Address On A Heroku Hosted NodeJS App

I was building a new report for SignalLeaf last weekend, to get the RSS Subscriber count for a given podcast. Along the way, I was doing some research in to the best way to track that information. It turned out to be mostly simple: track the IP address for every machine that gets the RSS feed for a given podcast, along with the user-agent for each (and a few other bits of info). Once you take out the known list of bots and crawlers, you can use a “distinct” combination of IP and user-agent to get a good idea of how many subscribers a podcast has. 

I was rocking the code, getting data tracked and analyzed, and I got the first version of the report published. So naturally, I went out to my own podcast that I have set up and started refreshing the RSS feed from my browser and from curl commands. I wanted to see what would happen in the staging and production environments, on Heroku.

To my horror, I found my RSS subscriber count increasing by 1 every time I refreshed the feed!

Screen Shot 2013 12 04 at 9 27 15 AM

Digging In To The Issue

Now this wasn’t happening on my local machine… I was properly counting distinct IP addresses as 1 subscriber… but when I deployed my code to my staging or production environments, it was not working as expected. Like any good JavaScript developer, I did the only reasonable thing: add some console.log statements to see if I can figure out what’s going on and re-deploy.

By adding a console.log on the IP address that I was tracking, I found out that I was getting a new IP address for every refresh, all within the 10.##.###.### IP Address range. I know this is a private IP range, used internally on networks, so this didn’t make sense to me at all.

A few quick searches later, and I found some info that told me how Heroku uses an internal routing system to forward the original request to any of the actual machines running your process. The IP address that your process actually receives is not the original requesting IP address, but the internal router or proxy or whatever it is. 

Getting The Real IP Address

Fortunately, there is a way to get the real IP Address for a client that is connected to your app. Heroku attaches a “x-forwarded-for” header to requests, and gives you an array of IP Addresses as the value. All you need to do is read this array by splitting the raw string at “,” and then find the last item in the array. This will be the real IP address of the client.

So in my app, I added this code:

  var ipAddr = req.headers["x-forwarded-for"];
  if (ipAddr){
    var list = ipAddr.split(",");
    ipAddr = list[list.length-1];
  } else {
    ipAddr = req.connection.remoteAddress;
  }

And now I have the real IP address to track RSS activity and produce the right report.

Artificial Bump In Subscribers

Of course, my RSS subscriber history has a large bump in the first day, from all my errant subscriber counts:

Screen Shot 2013 12 04 at 9 27 54 AM

But the good news is that most people aren’t going to sit there, refreshing their RSS feed every few seconds, dozens of times. So no one else really had the problem of an extra bump in subscribers that first day. And as you can see, my count is now leveled out where it should be.

Screen Shot 2013 12 04 at 9 34 27 AM

Hopefully I’ll be able to bump that number back up … legitimately … as I produce more episodes, though. :)


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Heroku, Javascript, Metrics, Podcast, SignalLeaf. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Artur

    Wikipedia says that the original client ip is the first one, not the last one on the list.
    See http://en.wikipedia.org/wiki/X-Forwarded-For

  • http://www.menagenet.co.il עמית גור

    Thanks, your code is working for me

  • Anonymous

    THIS IS INCREDIBLY HELPFUL THANKS! Really man, you just saved my app!