How do I get the correct IP from HTTP_X_FORWARDED_FOR if it contains multiple IP Addresses?

If Request.ServerVariables["HTTP_X_FORWARDED_FOR"] returns multiple ip's, which one do I take and how would I do it in c#? It is my understanding that if it is blank or null, then the client computer is not going through a proxy and I can just get their ip from Request.ServerVariables["REMOTE_ADDR"]. Is this a correct statement?

By "which one do I take", I mean do I take the first IP in the list or the last IP and is all I have to do is just split it into an array and take the one I want. I am not really sure how HTTP_X_FORWARDED_FOR works.


According to this, the format of X-Forwarded-For HTTP header is:

X-Forwarded-For: client1, proxy1, proxy2, ...

So the IP address of the client that you want should be the first one in the list


A further note on the reliability subject:

Anyone can forge HTTP_X_FORWARDED_FOR by using a tool such as the Firefox plugin "Tamper Data" or their own local proxy (e.g. Privoxy). This means that the entire string might be fake, and REMOTE_ADDR is the actual original host. It might also mean that the first "client1" address is faked, and then the client connected through a proxy, resulting in proxy1 being the client's IP address and REMOTE_ADDR being the single proxy used.

If you are looking to deny access based on IP, I would suggest checking every IP address in the XFF header as well as REMOTE_ADDR.

If you're looking to grant access based on the region of an IP, I'd suggest allowing access only if XFF is blank and the IP is from the proper area.

As Mastermind already noted, however, there are proxies which will hide the chain of proxies. For instance, the Tor network will make a request appear as if it came from the final proxy machine, rather than the original IP. Anonymizing proxies will often claim they are forwarding for the same IP as reported in REMOTE_ADDR.

IP based filtering is generally a pretty crude, last-resort mechanism of access control.


I asked some time ago a very similar question.

Getting the client IP address: REMOTE_ADDR, HTTP_X_FORWARDED_FOR, what else could be useful?

As correctly pointed out, you can take the first value considering it to be the client's IP address. But it may as well be company gateway IP.

And anonymous proxies will wipe out information in this header anyway, so it is useful but not reliable.


The actual client IP should be the left-most IP address in the header value. You can extract it into an environment variable using a regex:

SetEnvIf X-Forwarded-For "^(\d{1,3}+\.\d{1,3}+\.\d{1,3}+\.\d{1,3}+).*" XFFCLIENTIP=$1

Note the use of $1 to set the XFFCLIENTIP environment variable to hold the contents of the first group in the regex (in the parentheses).

As an example of using this, you can define a log format that uses the variable: this example is one we use internally at nearmap.com, so it logs extra information, but the bit you want is the %{XFFCLIENTIP}e at the beginning. Note the env=XFFCLIENTIP at the end of the line, which means this format is only used if the environment variable is set.

CustomLog /var/log/apache2/access.log "%{XFFCLIENTIP}e \"%{session}C\" \"%{nearmapuid}C\" %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" env=XFFCLIENTIP