A Gotcha Identifying the User's IP Address

Recently I wrote a .NET based Akismet API component for Subtext.  In attempting to make as clean as interface as possible, I made the the type of the property to store the commenter’s IP address of type IPAddress.

This sort of falls in line with the Framework Design Guidelines, which mention using the Uri class in your public interface rather than a string to represent an URL.  I figured this advice equally applied to IP Addresses as well.

To obtain the user’s IP Address, I simply used the UserHostAddress property of the HttpRequest object like so.

HttpContext.Current.Request.UserHostAddress

The UserHostAddress property is simply a wrapper around the REMOTE_ADDR server variable which can be accessed like so.

HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]

For users behind a proxy (or router), this returns only one IP Address, the IP Address of the proxy (or router).  After some more digging, I learned that many large proxy servers will append their IP Address to a list maintained within another HTTP Header, HTTP_X_FORWARDED_FOR or HTTP_FORWARDED.

For example, if you make a request from a country outside of the U.S., your proxy server might add the header HTTP_X_FORWARDED_FOR and put in your real IP and append its own IP Address to the end. If your request then goes through yet another proxy server, it may append its IP Address to the end.  Note that not all proxy servers follow this convention, the notable exception being anonymizing proxies.

Thus to get the real IP address for the user, it makes sense to check the value of this first:

HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]

If that value is empty or null, then check the UserHostAddress property.

So what does this mean for my Akismet implementation?  I could simply change that property to be a string and return the entire list of IP addresses.  That’s probably the best choice, but I am not sure whether or not Akismet accepts multiple IPs.  Not only that, I’m really tired and lazy, and this change would require that I change the Subtext schema since we store the commenter’s IP in a field just large enough to hold a single IP address.

So unless smart slap me upside the head and call me crazy for this approach, I plan to look at the HTTP_X_FORWARDED_FOR header first and take the first IP address in the list if there are any.  Otherwise I will grab the value of UserHostAddress.  As far as I am concerned, it’s really not that important that I am 100% accurate in identifying the remote IP, I just need something consistent to pass to Akismet.

What others have said

Requesting Gravatar... Keyvan Nayyeri Oct 11, 2006 11:23 AM
# re: A Gotcha Identifying the User's IP Address
Nice point :-)

But I think IP doesn't have an important role in Akismet. Probably they need to block 1-2% of spams that come from amateur spammers :-D

It's my personal experience with them. Akismet blocked almost 99.5% of my spams and I'm sure the component that is used to write my Akismet Add-in hasn't attended to this point.
Requesting Gravatar... Kamran Shahid Oct 11, 2006 1:05 PM
# re: A Gotcha Identifying the User's IP Address
Fantastic information.
Great man.
Requesting Gravatar... Nicholas Paldino [.NET/C# MVP] Oct 11, 2006 11:00 PM
# re: A Gotcha Identifying the User's IP Address
I don't understand why you would choose what to send and what not to send. My impression of Akismet is that when you send a request, you send as much information as possible about the request that came in.

That's why in my implementation, I actually dump all the headers in the request to Akismet. The more information they have, the better decision they can make, the better they can tweak their heuristics.
Requesting Gravatar... Keyvan Nayyeri Oct 11, 2006 11:12 PM
# re: A Gotcha Identifying the User's IP Address
Phil,

Have you implemented the functionality to report a spam via blog control panel or not?

That's a great feature which we can't use with CS since it needs some core modification. Recently we got some valid comments that were flagged as spam and we couldn't report them.
Requesting Gravatar... Haacked Oct 12, 2006 1:45 AM
# re: A Gotcha Identifying the User's IP Address
@Nicolas: Good point, no good answer other than I made the IPAddress column where we store a comment to only be as wide as an IPAddress.

@Keyvan: Yes, that's why it took me so long. I wanted Subtext users to be able to report false-positives and false-negatives.
Requesting Gravatar... Jason Haley Oct 12, 2006 2:40 PM
# Interesting Finds: October 12, 2006
Requesting Gravatar... Joshua Flanagan Oct 13, 2006 5:37 AM
# re: A Gotcha Identifying the User's IP Address
♠As Keyvan's first post alluded to, I think it depends on how other Akismet implementations handle it. Since it makes its decision based on feedback from all of its users, it really depends on what that feedback contains. If everyone reports a spam using the proxy server of the user, then that becomes the identifying characteristic (in addition to others, I'm sure). So it really doesn't add any value if you provide the "real" ip address of the user, if every other Akismet user is providing the proxy IP address from HTTP_REMOTE_ADDR.
Requesting Gravatar... TAG Oct 18, 2006 3:21 PM
# re: A Gotcha Identifying the User's IP Address
Beware - using those headers for security without using others values can lead to trouble.
Anybody can set values for those headers to any value they wish while connecting.

So - you have to check all values - not only one. And block users if ANY of them will be in your blacklist.
Requesting Gravatar... JD Aug 25, 2007 7:05 AM
# re: A Gotcha Identifying the User's IP Address
This is closely related to my work. I work for a mystery shopping based company which needs to gather stats for consumers without being detected. I researched dozens of ip hiders for windows servers. Anonymizer didn't meet our needs. I can recommend netconceal if you need to go thurther down the rout of tracing header/routes and how this is viable. (You might will keep in me in work someday) Meantime back to Saturday night television.
Requesting Gravatar... Ola Lindberg Sep 19, 2007 10:55 PM
# re: A Gotcha Identifying the User's IP Address
I have a problem where the website I'm running the web application on is behind some kind of load balancer. The result is that I get the external IP address for the load balancer instead of the client when using the methods described here.

I have yet no solution for this. All ideas are welcome!
Requesting Gravatar... Sandip Rohokale Dec 11, 2008 10:23 PM
# re: A Gotcha Identifying the User's IP Address
I am using
HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] to get the IP Address of device connected in network but getting error
System.NullReferenceException: Object reference not set to an instance of an object

Will you please tell me the solution.
Requesting Gravatar... Jerome Dimairho Feb 01, 2009 7:02 PM
# re: A Gotcha Identifying the User's IP Address
@Sandip: I also encountered the same issue then I realised that the HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] is null when a request doesn't come through a proxy server. First do a check to see if this server variable is empty, if it's not null, the assign it to a variable.

If HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] is null just use the HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] server variable since the request isn't coming through a proxy server.
Requesting Gravatar... DotNetSpark Apr 07, 2009 3:56 AM
# re: A Gotcha Identifying the User's IP Address
Well HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] works for me but i am not sure about HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]
Thanks for sharing information.
Requesting Gravatar... Vidhya Oct 26, 2010 6:01 AM
# re: A Gotcha Identifying the User's IP Address
Thanks for sharing info.

I am trying following in production, but somehow following code is not working. I am clueless can you please guide me? Its a burning question and nowhere i found a true solution on web.

if (HttpContext.Current == null)
{
strUserIp = "127.0.0.1";
}
else if (string.IsNullOrEmpty(HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]))
{
//Users IP Address.
strUserIp = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();
}
else
{
//To get the IP address of the machine and not the proxy
string IPAddresses = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
string [] ipArray = IPAddresses.Split(new char[] {','});
strUserIp = ipArray[0];
}

Thanks
Vidhya
Requesting Gravatar... Bal Nov 08, 2010 8:59 PM
# re: A Gotcha Identifying the User's IP Address
HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] is always returning null even though having the proxy for my LAN.
I deployed website in my own LAN.
HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] is working but always returning the Proxy ip.
How to get the exact IP of the system within the LAN.
Any ideas is greatly appreciated please leave the answer.

Thanks
Balu
Requesting Gravatar... Sunil Jun 18, 2011 11:27 AM
# re: A Gotcha Identifying the User's IP Address
Hi,

HttpContext.Current.Request.ServerVariable["HTTP_X_FORWARDED_FOR"] is returning null..please help me.

Regards
Sunil

What do you have to say?

(will show your gravatar)
Please add 2 and 8 and type the answer here: