ASP.NET Request.ServerVariables yields local IP address not remote IP

10,108

Solution 1

It depends on your network structure. Simply a firewall or load balancer can change the variables which you are checking.

if you are using a load balancer check this: How to get visitor IP on load balancing machine using asp.net

if your sever is behind a firewall check this: Find if request was forwarded from firewall to IIS

Solution 2

If the HTTP_X_FORWARDED_FOR header is truly supported, then I think this would not be either forward or reverse proxy server causing this, but more likely Dynamic Network Address Translation or Dynamic Port Address Translation, which is happening below the application layer on the TCP/IP stack and thus would not affect an HTTP request header.

There are many ways to configure NAT, most of which would not cause these symptoms, but it is certainly possible to configure NAT in a way that would present this problem. Dynamic NAT or Dynamic PAT would be two such examples, and I would suggest this is what you ask your network administrators.

For more on Dynamic NAT/PAT, with good examples, you could review: http://www.cisco.com/en/US/docs/security/asa/asa82/configuration/guide/nat_dynamic.html

In a typical NAT scenario, the request packets reach the NAT device (firewall or router) as: FROM - 5.5.5.5 (public address of the client) TO - 6.6.6.6 (the public address of the server)

The "typical" NAT configuration would rewrite only the destination, as follows: FROM - 5.5.5.5 TO - 192.168.6.6 (the private address of the server)

In this typical case, the server would still see REMOTE_ADDR as 5.5.5.5, as that is the source address on the incoming request. Then, the packets would be returned to 5.5.5.5, and the response would return to the client successfully.

Now, in the case of dynamic PAT, for example, the request would reach the NAT device as follows: FROM - 5.5.5.5 TO - 6.6.6.6

Then, the NAT device would rewrite both source and destination packets, maintaining this "dynamic" mapping for only the lifetime of the request: FROM - 192.168.1.1:12345 (the dynamic PAT address) TO - 192.168.6.6 (the private address of the server)

Now, when the server sees this request, it appears to be from private address 192.168.1.1. In fact, with a strict PAT all requests will appear to be from this address. In your case, there are 2 or 3 of these addresses, probably because you may have enough traffic that you risk running out of ports if you use only a single dynamic PAT address.

So, your REMOTE_ADDR is 192.168.1.1, because that is actually the source address on the request packets. There is no HTTP_X_FORWARDED_FOR, because the Dynamic PAT is occurring at a lower TCP/IP layer (address and not application).

Finally, the response is sent back to 192.168.1.1:12345, which routs to the NAT device, which for the duration of the request/response (see the Cisco documentation above) maps it back to 5.5.5.5, and then drops the "dynamic" mapping.

Everything worked perfectly, the client gets the response back, except that you have no idea of the actual client address from the viewpoint of the server. And if it is dynamic NAT in play, I don't see how you could get this information from the server.

Fortunately, you did exactly the right thing to get the information in javascript on the client, so this likely solves your problem as well as it could be solved.

Share:
10,108

Related videos on Youtube

Ernie S
Author by

Ernie S

Full time developer at Liquidnet in NYC which specializes in financial software. Stack involves .NET/C#/WPF as well as web technologies in HTML5 and JavaScript involving high-frequency Trading applications. Ernie [email protected]

Updated on May 25, 2022

Comments

  • Ernie S
    Ernie S almost 2 years

    Got an asp.net web page in c#. One thing we would like to do is track hits to the site including their IP address. I implemented some code (thanks to SO) but the logged IP address always seem to be local, ie: 192.168.x.x. I have tried it from a variety of devices, even my phone and Version MiFi just to make sure its not something weird with the ISP but the log always list the same 2-3 different internal ip addresses (seems to change a little as the day goes on).

    Here is my function that gets the IP (again thanks to postings here on SO):

    protected IPAddress GetIp(HttpRequest request)
    {
        string ipString;
        if (string.IsNullOrEmpty(request.ServerVariables["HTTP_X_FORWARDED_FOR"]))
            ipString = request.ServerVariables["REMOTE_ADDR"];
        else
            ipString = request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
    
        IPAddress result;
        if (!IPAddress.TryParse(ipString, out result))
            result = IPAddress.None;
    
        return result;
    }
    
    public void logHit()
    {
        IPAddress ip = GetIp(Request);
        string sIP = ip.ToString();
    }
    

    I tried this as well which yields the same result:

    HttpContext.Current.Request.UserHostAddress;
    

    When I do a call on the client side using something like the service on appspot, it works just fine:

    <script type="application/javascript">
        function getip(json) {
            //txtIP is a input box on the form
            document.getElementById("txtIP").value = json.ip;
        }
    </script>
    
    <script type="application/javascript" src="http://jsonip.appspot.com/?callback=getip"></script>
    

    I suppose I could do a round-about way by hitting that appspot link and parse it out but that seems like a whole lot of trouble for something that should be simple.

    Could it be the IIS on the server? Some kind of redirect going on? The ip addresses logged are NOT the servers. The problem is I dont have direct access to it so I have to talk to the guys that admin it and would like to give them some direction before they just start changing things.

    Thanks

    Ernie

    • jbl
      jbl about 11 years
      You may give a try to "X-Forwarded-For" header, instead of (or in addition to ) "HTTP_X_FORWARDED_FOR". Anyway, if your app is hosted behind a reverse proxy, you might have an issue, because not all RP implement *X_FORWARDED_FOR correctly.
    • MethodMan
      MethodMan about 11 years
      Ernie take a look at this stackoverflow posting and try the answer provided by @algreat stackoverflow.com/questions/735350/…
    • Ernie S
      Ernie S about 11 years
      @jbl:Thanks for the response. I tried that but it comes back null.
    • Ernie S
      Ernie S about 11 years
      @DJKRAZE: Thanks for the link. I actually read that previously and tried all of the mentioned answers. All come back with the same ip addresses. I even created a test page the loops trough all of the entries in ServerVariables and the DNS AddressList and dumps them to the client side html to see if there was another var that might have it, unfortunately nothing did. The only thing that works is the javascript. Ernie
    • Laszlo Boke
      Laszlo Boke about 11 years
      I was only curious, and checked with my ISP. xeondev.weblapportal.hu/Webform1.aspx "HTTP_X_FORWARDED_FOR" is supported , maybe some IIS setting ? ....
  • Ernie S
    Ernie S about 11 years
    Thanks, your mentioning of the firewall got me to the right answer. Our web server is not really a pure web server but does other functions as well so it sits inside our company firewall.
  • Ernie S
    Ernie S about 11 years
    Thanks, your answer was very informative although ultimately I thing my problem was a plain old firewall issue. I would give you a bump but I dont have the points for it :(.