How do I get client IP address in ASP.NET Core?

C#asp.net Coreasp.net Core-Mvc

C# Problem Overview


Can you please let me know how to get client IP address in ASP.NET when using MVC 6. Request.ServerVariables["REMOTE_ADDR"] does not work.

C# Solutions


Solution 1 - C#

The API has been updated. Not sure when it changed but according to Damien Edwards in late December, you can now do this:

var remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress;

Solution 2 - C#

In project.json add a dependency to:

"Microsoft.AspNetCore.HttpOverrides": "2.2.0"

In Startup.cs, in the Configure() method add:

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor |
    ForwardedHeaders.XForwardedProto
});  

And, of course:

using Microsoft.AspNetCore.HttpOverrides;

Then, I could get the ip by using:

Request.HttpContext.Connection.RemoteIpAddress

In my case, when debugging in VS I got always IpV6 localhost, but when deployed on an IIS I got always the remote IP.

Some useful links: https://stackoverflow.com/questions/28664686/how-do-i-get-client-ip-address-in-asp-net-core and https://stackoverflow.com/questions/35441521/remoteipaddress-is-always-null?noredirect=1&lq=1

The ::1 is maybe because of:

> Connections termination at IIS, which then forwards to Kestrel, the v.next web server, so connections to the web server are indeed from localhost. (https://stackoverflow.com/a/35442401/5326387)

Edit 12/2020: Thanks to SolidSnake: as of Dec 2020 the latest version is 2.2.0

Edit 06/2021: Thanks to Hakan Fıstık: In .NET 5 the namespace is Microsoft.AspNetCore.Builder

Solution 3 - C#

Some fallback logic can be added to handle the presence of a Load Balancer.

Also, through inspection, the X-Forwarded-For header happens to be set anyway even without a Load Balancer (possibly because of additional Kestrel layer?):

public string GetRequestIP(bool tryUseXForwardHeader = true)
{
    string ip = null;

    // todo support new "Forwarded" header (2014) https://en.wikipedia.org/wiki/X-Forwarded-For

    // X-Forwarded-For (csv list):  Using the First entry in the list seems to work
    // for 99% of cases however it has been suggested that a better (although tedious)
    // approach might be to read each IP from right to left and use the first public IP.
    // http://stackoverflow.com/a/43554000/538763
    //
    if (tryUseXForwardHeader)
        ip = GetHeaderValueAs<string>("X-Forwarded-For").SplitCsv().FirstOrDefault();

    // RemoteIpAddress is always null in DNX RC1 Update1 (bug).
    if (ip.IsNullOrWhitespace() && _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress != null)
        ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();

    if (ip.IsNullOrWhitespace())
        ip = GetHeaderValueAs<string>("REMOTE_ADDR");

    // _httpContextAccessor.HttpContext?.Request?.Host this is the local host.
            
    if (ip.IsNullOrWhitespace())
        throw new Exception("Unable to determine caller's IP.");

    return ip;
}
    
public T GetHeaderValueAs<T>(string headerName)
{
    StringValues values;

    if (_httpContextAccessor.HttpContext?.Request?.Headers?.TryGetValue(headerName, out values) ?? false)
    {
        string rawValues = values.ToString();   // writes out as Csv when there are multiple.

        if (!rawValues.IsNullOrWhitespace())
            return (T)Convert.ChangeType(values.ToString(), typeof(T));
    }
    return default(T);
}

public static List<string> SplitCsv(this string csvList, bool nullOrWhitespaceInputReturnsNull = false)
{
    if (string.IsNullOrWhiteSpace(csvList))
        return nullOrWhitespaceInputReturnsNull ? null : new List<string>();

    return csvList
        .TrimEnd(',')
        .Split(',')
        .AsEnumerable<string>()
        .Select(s => s.Trim())
        .ToList();
}

public static bool IsNullOrWhitespace(this string s)
{
    return String.IsNullOrWhiteSpace(s);
}

Assumes _httpContextAccessor was provided through DI.

Solution 4 - C#

You can use the IHttpConnectionFeature for getting this information.

var remoteIpAddress = httpContext.GetFeature<IHttpConnectionFeature>()?.RemoteIpAddress;

Solution 5 - C#

In ASP.NET 2.1, In StartUp.cs Add This Services:

services.AddHttpContextAccessor();
services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();

and then do 3 step:

  1. Define a variable in your MVC controller

     private IHttpContextAccessor _accessor;
    
  2. DI into the controller's constructor

    public SomeController(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }
    
  3. Retrieve the IP Address

     _accessor.HttpContext.Connection.RemoteIpAddress.ToString()
    

This is how it is done.

Solution 6 - C#

I found that, some of you found that the IP address you get is :::1 or 0.0.0.1

This is the problem because of you try to get IP from your own machine, and the confusion of C# that try to return IPv6.

So, I implement the answer from @Johna (https://stackoverflow.com/a/41335701/812720) and @David (https://stackoverflow.com/a/8597351/812720), Thanks to them!

and here to solution:

  1. add Microsoft.AspNetCore.HttpOverrides Package in your References (Dependencies/Packages)

  2. add this line in Startup.cs

     public void Configure(IApplicationBuilder app, IHostingEnvironment env)
     {
         // your current code
    
         // start code to add
         // to get ip address
         app.UseForwardedHeaders(new ForwardedHeadersOptions
         {
         ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
         });
         // end code to add
    
     }
    
  3. to get IPAddress, use this code in any of your Controller.cs

     IPAddress remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;
     string result = "";
     if (remoteIpAddress != null)
     {
         // If we got an IPV6 address, then we need to ask the network for the IPV4 address 
         // This usually only happens when the browser is on the same machine as the server.
         if (remoteIpAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
         {
             remoteIpAddress = System.Net.Dns.GetHostEntry(remoteIpAddress).AddressList
     .First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
         }
         result = remoteIpAddress.ToString();
     }
    

and now you can get IPv4 address from remoteIpAddress or result

Solution 7 - C#

var remoteIpAddress = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;

Solution 8 - C#

This works for me (DotNetCore 2.1)

[HttpGet]
public string Get() 
{
    var remoteIpAddress = HttpContext.Connection.RemoteIpAddress;
    return remoteIpAddress.ToString();
}

Solution 9 - C#

In my case, I have DotNet Core 2.2 Web App running on DigitalOcean with docker and nginx as reverse proxy. With this code in Startup.cs I can get the client IP

app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.All,
            RequireHeaderSymmetry = false,
            ForwardLimit = null,
            KnownNetworks = { new IPNetwork(IPAddress.Parse("::ffff:172.17.0.1"), 104) }
        });

::ffff:172.17.0.1 was the ip that I was getting before using

Request.HttpContext.Connection.RemoteIpAddress.ToString();

Solution 10 - C#

As of September 2021 - ASP.NET Core (5.x) MVC project allowed me to get the IP Address this way in my controller:

Request.HttpContext.Connection.RemoteIpAddress

Quite a bit more simple now than in the past, it seems.

Solution 11 - C#

In .NET 5 I use this to retrieve the client IP via a container on AWS fargate.

public static class HttpContextExtensions
{
    //https://gist.github.com/jjxtra/3b240b31a1ed3ad783a7dcdb6df12c36

    public static IPAddress GetRemoteIPAddress(this HttpContext context, bool allowForwarded = true)
    {
        if (allowForwarded)
        {
            string header = (context.Request.Headers["CF-Connecting-IP"].FirstOrDefault() ?? context.Request.Headers["X-Forwarded-For"].FirstOrDefault());
            if (IPAddress.TryParse(header, out IPAddress ip))
            {
                return ip;
            }
        }
        return context.Connection.RemoteIpAddress;
    }
}

You call it like this:

var ipFromExtensionMethod = HttpContext.GetRemoteIPAddress().ToString();

Source

Solution 12 - C#

Running .NET core (3.1.4) on IIS behind a Load balancer did not work with other suggested solutions.

Manually reading the X-Forwarded-For header does. This code assumes this header contains one IP.

IPAddress ip;
var headers = Request.Headers.ToList();
if (headers.Exists((kvp) => kvp.Key == "X-Forwarded-For"))
{
    // when running behind a load balancer you can expect this header
    var header = headers.First((kvp) => kvp.Key == "X-Forwarded-For").Value.ToString();
    // in case the IP contains a port, remove ':' and everything after
    ip = IPAddress.Parse(header.Remove(header.IndexOf(':')));
}
else
{
    // this will always have a value (running locally in development won't have the header)
    ip = Request.HttpContext.Connection.RemoteIpAddress;
}

Thanks to @JawadAlShaikh and @BozoJoe for pointing out the IP can contain a port and the X-Forwarded-For can contain multiple IPs.

Solution 13 - C#

First, in .Net Core 1.0 Add using Microsoft.AspNetCore.Http.Features; to the controller Then inside the relevant method:

var ip = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress?.ToString();

I read several other answers which failed to compile because it was using a lowercase httpContext, leading the VS to add using Microsoft.AspNetCore.Http, instead of the appropriate using, or with HttpContext (compiler is also mislead).

Solution 14 - C#

Running ASP.NET Core 2.1 behind a Traefik reverse Proxy on Ubuntu, I need to set its gateway IP in KnownProxies after installing the official Microsoft.AspNetCore.HttpOverrides package

        var forwardedOptions = new ForwardedHeadersOptions {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor,
        };
        forwardedOptions.KnownProxies.Add(IPAddress.Parse("192.168.3.1"));
        app.UseForwardedHeaders(forwardedOptions);

According to the documentation, this is required if the reverse proxy is not running on localhost. The docker-compose.yml of Traefik has assigned a static IP address:

networks:
  my-docker-network:
    ipv4_address: 192.168.3.2

Alternatively, it should be enough to make sure a known network is defined here to specify its gateway in .NET Core.

Solution 15 - C#

As per the official documentation, if you are using Apache or Nginx integration, following code should be added to the Startup.ConfigureServices method.

// using Microsoft.AspNetCore.HttpOverrides;

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | 
            ForwardedHeaders.XForwardedProto;
        // Only loopback proxies are allowed by default.
        // Clear that restriction because forwarders are enabled by explicit 
        // configuration.
        options.KnownNetworks.Clear();
        options.KnownProxies.Clear();
    });

and then on top of everything, in Configure method use

app.UseForwardedHeaders();

Further suppose in nginx conf file, inside a location, use

proxy_set_header   Host $host;
proxy_set_header   X-Real-IP $remote_addr;
proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header   X-Forwarded-Host $server_name;

Now the first entry in the X-Forwarded-For will be the real client IP.

IMPORTANT: If you want to secure the app and not allow an attacker inject X-Forwarded-For, Please read this answer.

Please see Forward the scheme for Linux and non-IIS reverse proxies, Configure Nginx and Dealing with invalid headers

Solution 16 - C#

First Add

Microsoft.AspNetCore.Http
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

in ConfigureServices in Startup.cs Then Add the following code in your controller

   private IHttpContextAccessor _accessor;
    
  public LoginController(IHttpContextAccessor accessor)
            {
              _accessor = accessor;
            }

  public IEnumerable<string> Get()
        {
         var ip = _accessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
         return new string[] { ip, "value" };
        }

Hope this will work for you

Solution 17 - C#

try this:

string remoteHost = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}";

Solution 18 - C#

From this link, there is a better solution.

In Startup.cs, we need to add service-

public void ConfigureServices(IServiceCollection services)
{
    ........
    services.AddHttpContextAccessor();
    ........
}

Then in any controller or any place, we need to use it via dependency injection like this-

private IHttpContextAccessor HttpContextAccessor { get; }

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IWebHostEnvironment env, IHttpContextAccessor httpContextAccessor)
        : base(options)
{
    Environment = env;
    HttpContextAccessor = httpContextAccessor;
    //this.Database.EnsureCreated();
}

And then get IP like this-

IPAddress userIp = HttpContextAccessor.HttpContext.Connection.RemoteIpAddress;

Solution 19 - C#

Short version of @crokusek's answer

public string GetUserIP(HttpRequest req)
{
	var ip = req.Headers["X-Forwarded-For"].FirstOrDefault();

	if (!string.IsNullOrWhiteSpace(ip)) ip = ip.Split(',')[0];

	if (string.IsNullOrWhiteSpace(ip)) ip = Convert.ToString(req.HttpContext.Connection.RemoteIpAddress);

	if (string.IsNullOrWhiteSpace(ip)) ip = req.Headers["REMOTE_ADDR"].FirstOrDefault();

	return ip;
}

Solution 20 - C#

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;

public string GetClientIPAddress(HttpContext context)
	{
		string ip = string.Empty;
if (!string.IsNullOrEmpty(context.Request.Headers["X-Forwarded-For"]))
		{
			ip = context.Request.Headers["X-Forwarded-For"];
		}
		else
		{
			ip = context.Request.HttpContext.Features.Get<IHttpConnectionFeature>().RemoteIpAddress.ToString();
		}
		return ip;
	}

Where you want to get Ip address;

GetClientIPAddress(HttpContext);

Solution 21 - C#

try this.

var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily == AddressFamily.InterNetwork)
            {
                 ipAddress = ip.ToString();
            }
        }

Solution 22 - C#

To get IP address and hostname in .NET Core, put the following code in the controller:

var addlist = Dns.GetHostEntry(Dns.GetHostName());
string GetHostName = addlist.HostName.ToString();
string GetIPV6 = addlist.AddressList[0].ToString();
string GetIPV4 = addlist.AddressList[1].ToString();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioneadamView Question on Stackoverflow
Solution 1 - C#David PedenView Answer on Stackoverflow
Solution 2 - C#JohnaView Answer on Stackoverflow
Solution 3 - C#crokusekView Answer on Stackoverflow
Solution 4 - C#KiranView Answer on Stackoverflow
Solution 5 - C#hojjat.miView Answer on Stackoverflow
Solution 6 - C#Sruit A.SukView Answer on Stackoverflow
Solution 7 - C#feradzView Answer on Stackoverflow
Solution 8 - C#MC9000View Answer on Stackoverflow
Solution 9 - C#gorumsView Answer on Stackoverflow
Solution 10 - C#raddevusView Answer on Stackoverflow
Solution 11 - C#CodingYourLifeView Answer on Stackoverflow
Solution 12 - C#AageView Answer on Stackoverflow
Solution 13 - C#GuyView Answer on Stackoverflow
Solution 14 - C#LionView Answer on Stackoverflow
Solution 15 - C#Sayyed DawoodView Answer on Stackoverflow
Solution 16 - C#Ali MumtazView Answer on Stackoverflow
Solution 17 - C#lianggan13View Answer on Stackoverflow
Solution 18 - C#Abrar JahinView Answer on Stackoverflow
Solution 19 - C#Mehdi DehghaniView Answer on Stackoverflow
Solution 20 - C#Semih Can BilgenView Answer on Stackoverflow
Solution 21 - C#Kunal BurangiView Answer on Stackoverflow
Solution 22 - C#Shreyash BanawalaView Answer on Stackoverflow