HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Get host ip address behind load balancer or without lb

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withoutaddressgethostloadbalancerbehind

Problem

Description

Aplication type: WEB API

.NET Framework: 4.5

MVC: 5

I need caller host ip in my custom action filter and then in action. On some enviroments we have configured load balancer which stores caller ip in header "HTTP_X_FORWARDED_FOR". I nedd my code works with LB or without.

CODE

Filter

using System.Collections.Generic;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace FAPTest.TestApp.ActionFilters
{
    public class AccessControlFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            string ip = HttpContext.Current.Request.UserHostAddress;

            string sourceIp = HttpContext.Current.Request.ServerVariables.Get("HTTP_X_FORWARDED_FOR");

            string ipAddress = ip;

            if (!string.IsNullOrEmpty(sourceIp))
            {
                ipAddress = sourceIp;
            }

            actionContext.Request.Properties.Add(new KeyValuePair("ipAddress", ipAddress));                 
        }        
    }
}


Controller

using System.Web.Http;

namespace FAPTest.TestApp.Controllers
{
    public class TestController : ApiController
    {
        [HttpGet]
        public string Test()
        {
            object o = null;
            string ipAddress = null;

            if (Request.Properties.TryGetValue("ipAddress", out o))
            {
                ipAddress = (string)o;
            }

            return ipAddress;
        }
    }
}


Filter registration:

```
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using FAPTest.TestApp.ActionFilters;

namespace FAPTest.TestApp
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.Regi

Solution

Here is a pattern I've used successfully. However, you need to be aware that the X-FORWARDED-FOR header may contain a comma separated list of ip addresses. This solution also helps with protocol sniffing, because most secure sites will need to force the web browser to SSL, and if you are using SSL OFFLOADING, you'll need to use the x-forwarded-proto header to determine if a redirect is required.

string ipAddress = string.Empty;
        string protocol = string.Empty;
        string port = string.Empty;

        if (Request.RequestContext.HttpContext.Request.Headers.GetValues("X-Forwarded-For") != null)
        {
            protocol = (Request.RequestContext.HttpContext.Request.Headers.GetValues("X-Forwarded-Proto")).FirstOrDefault();
            ipAddress = (Request.RequestContext.HttpContext.Request.Headers.GetValues("X-Forwarded-For")).FirstOrDefault();
            port = Request.RequestContext.HttpContext.Request.Headers.GetValues("X-Forwarded-Port").FirstOrDefault();
        }

        if (string.IsNullOrWhiteSpace(protocol))
        {
            protocol = (this.Request.IsSecureConnection ? "HTTPS" : "HTTP");
            ipAddress = this.Request.UserHostAddress;
        }


Example format of header value:

X-Forwarded-For: client, proxy1, proxy2


See https://en.wikipedia.org/wiki/X-Forwarded-For

Code Snippets

string ipAddress = string.Empty;
        string protocol = string.Empty;
        string port = string.Empty;

        if (Request.RequestContext.HttpContext.Request.Headers.GetValues("X-Forwarded-For") != null)
        {
            protocol = (Request.RequestContext.HttpContext.Request.Headers.GetValues("X-Forwarded-Proto")).FirstOrDefault();
            ipAddress = (Request.RequestContext.HttpContext.Request.Headers.GetValues("X-Forwarded-For")).FirstOrDefault();
            port = Request.RequestContext.HttpContext.Request.Headers.GetValues("X-Forwarded-Port").FirstOrDefault();
        }

        if (string.IsNullOrWhiteSpace(protocol))
        {
            protocol = (this.Request.IsSecureConnection ? "HTTPS" : "HTTP");
            ipAddress = this.Request.UserHostAddress;
        }
X-Forwarded-For: client, proxy1, proxy2

Context

StackExchange Code Review Q#136068, answer score: 3

Revisions (0)

No revisions yet.