Question

I currently have a RESTful C# web service that gets the client's IP address. This was working fine until load-balancing was implemented. So now the web service is sitting behind a load balancer.

Now, every time I try to get the user's IP address, I get the IP address of the load balancer instead. Here is what the code looks like...

System.Web.HttpContext context = System.Web.HttpContext.Current;
        if (context.Request.ServerVariables.AllKeys.Contains("HTTP_CLIENT_IP") && CheckIP(context.Request.ServerVariables["HTTP_CLIENT_IP"]))
            return new Model(context.Request.ServerVariables["HTTP_CLIENT_IP"]);

        if (context.Request.ServerVariables.AllKeys.Contains("HTTP_X_FORWARDED_FOR"))
            foreach (string ip in context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(','))
                if (CheckIP(ip.Trim()))
                    return new Model(ip.Trim());

        if (context.Request.ServerVariables.AllKeys.Contains("HTTP_X_FORWARDED") && CheckIP(context.Request.ServerVariables["HTTP_X_FORWARDED"]))
            return new Model(context.Request.ServerVariables["HTTP_X_FORWARDED"]);

        if (context.Request.ServerVariables.AllKeys.Contains("HTTP_X_CLUSTER_CLIENT_IP") && CheckIP(context.Request.ServerVariables["HTTP_X_CLUSTER_CLIENT_IP"]))
            return new Model(context.Request.ServerVariables["HTTP_X_CLUSTER_CLIENT_IP"]);

        if (context.Request.ServerVariables.AllKeys.Contains("HTTP_FORWARDED_FOR") && CheckIP(context.Request.ServerVariables["HTTP_FORWARDED_FOR"]))
            return new Model(context.Request.ServerVariables["HTTP_FORWARDED_FOR"]);

        if (context.Request.ServerVariables.AllKeys.Contains("HTTP_FORWARDED") && CheckIP(context.Request.ServerVariables["HTTP_FORWARDED"]))
            return new Model(context.Request.ServerVariables["HTTP_FORWARDED"]);

        return new Model(context.Request.ServerVariables["REMOTE_ADDR"]);

Despite this, I am still ultimately getting the wrong IP address. Any thoughts? Ideas? Am I missing something?

Was it helpful?

Solution

A well-behaved load balancer should place one or more IP addresses in the X_FORWARDED_FOR header. Your code is checking HTTP_FORWARDED_FOR and two other variables that aren't quite right.

Not all load-balancers are well behaved, and some can be configured to include that header if it is not currently in there.

If there are multiple forwarding points, there will be multiple IP addresses in the header. In that case, the first one listed is the client IP

X-Forwarded-For: client, proxy1, proxy2

OTHER TIPS

        string sIpaddress = "";
        if (Request.Headers["True-Client-IP"] != null)
        {
            sIpaddress = Request.Headers["True-Client-IP"]; //if the user is behind a proxy server
        }
        if (sIpaddress == "")
        {
            if (Request.Headers["CF-CONNECTING-IP"] != null)
                sIpaddress = Request.Headers["CF-CONNECTING-IP"];
        }
        if (sIpaddress == "")
        {
            if (Request.Headers["X-Forwarded-For"] != null)
                sIpaddress = Request.Headers["X-Forwarded-For"];
        }
        if (sIpaddress == "")
        {
            if (Request.ServerVariables["REMOTE_ADDR"] != null)
                sIpaddress = Request.ServerVariables["REMOTE_ADDR"];
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top