29

I'm working on ASP.Net Core 2.1 with Angular Template provided by Microsoft Visual Studio 2017. My Client App is working fine. After competition of User Authentication, I want to start User Session Management in which I store client user IP Address. I've already searched for this on the internet but so far not found any solution.

Below are some ref links which I already visited:

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

Get Client IP Address in ASP.NET Core 2.0

Get a user remote IP Address in ASP.Net Core

In my ValuesController.cs I also tried below code:

private IHttpContextAccessor _accessor;

public ValuesController(IHttpContextAccessor accessor)
{
    _accessor = accessor;
}

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

wherein ip variable I get null value and getting this error

Request.HttpContext.Connection.RemoteIpAddress.Address threw an exception of Type 'System.Net.Sockets.SocketException'

enter image description here

enter image description here

Can you please let me know how to get client IP address in ASP.NET Core 2.1.

Pac0
  • 21,465
  • 8
  • 65
  • 74
Ahmer Ali Ahsan
  • 5,636
  • 16
  • 44
  • 81
  • Is it `null` as well if you use `_accessor.HttpContext.Connection.RemoteIpAddress`? – Camilo Terevinto Jun 30 '18 at 16:01
  • I am using this code for client IP address. `_context.Features.Get()?.RemoteIpAddress.ToString();` – SLYN Jun 30 '18 at 16:02
  • 1
    Are you trying to identify a user by an IP address? That is unreliable. Two people on your site connecting to public wifi at a library, coffee shop, hotel, etc will have the same IP address. – Crowcoder Jun 30 '18 at 17:02
  • 2
    How are you calling this code? You should be able to do just `HttpContext.Connection.RemoteIpAddress` in a controller. No need to go through `Request` or to use a HttpContextAccessor there. – poke Jun 30 '18 at 17:07
  • 1
    how the remote ip address is resolved has a lot to do with the specifics of the hosting environment https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1 – Joe Audette Jun 30 '18 at 17:15
  • This does not solve the issue, but note that the fact that `ip` is null on your debugger screenshot is perfectly normal. This line *has not been executed yet*, so the variable has not been assigned. – Pac0 Jun 30 '18 at 17:52
  • @SLYN your code is showing same error in my case. – Ahmer Ali Ahsan Jul 01 '18 at 06:12
  • @Crowcoder No, I m not trying to identify user by using IP Address. I m creating session management in my app so I need to store user IP Address of logged in user with loggin time and logged in session id. – Ahmer Ali Ahsan Jul 01 '18 at 06:17
  • 1
    @poke your solution is not working in my case. – Ahmer Ali Ahsan Jul 01 '18 at 06:19
  • I request to all of you kindly see my answer. Hope you all find it useful. Thanks – Ahmer Ali Ahsan Jul 01 '18 at 12:52
  • Possible duplicate of [How to get a user's client IP address in ASP.NET?](https://stackoverflow.com/questions/735350/how-to-get-a-users-client-ip-address-in-asp-net) – Dmitry Pavlov Jul 02 '18 at 11:12

7 Answers7

23

In your Startup.cs, make sure you have a method to ConfigureServices, passing in the IServiceCollection, then register IHttpContextAccessor as a singleton as follows:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

After registering the IHttpContextAccessor in your Startup.cs file, you can inject the IHttpContextAccessor in your controller class and use it like so:

private IHttpContextAccessor _accessor;

public ValuesController(IHttpContextAccessor accessor)
{
    _accessor = accessor;
}

public IEnumerable<string> Get()
{
    var ip = _accessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
    return new string[] { ip, "value2" };
}
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
zdub
  • 671
  • 6
  • 10
  • 12
    ToString value is "::1" for me while running on localhost machine. – Mrunal Nov 19 '18 at 09:38
  • What is the purpose of `value2` in `return new string[] { ip, "value2" };`? – ebhh2001 Sep 16 '21 at 03:57
  • `value2` is simply returned here to match the code that was provided in the initial question and does not serve any purpose for retrieving the client IP. This same block could also be written as follows: `public string Get() { return _accessor.HttpContext?.Connection?.RemoteIpAddress?.ToString(); }` – zdub Sep 16 '21 at 16:16
22

It's possible to use the following code:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});

string remoteIpAddress = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
if (Request.Headers.ContainsKey("X-Forwarded-For"))
    remoteIpAddress = Request.Headers["X-Forwarded-For"];
pomo_mondreganto
  • 2,028
  • 2
  • 28
  • 56
giox
  • 221
  • 2
  • 2
  • 1
    Is there any difference bewtween your answer and using: app.UseForwardedHeaders(new ForwardedHeadersOptions{ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto}); ? – Hossein Apr 14 '19 at 10:32
  • @desmati, I did not get real ip address of client if I do not check Request.Headers.ContainsKey("X-Forwarded-For") , even if i only use app.UseForwardedHeaders(new ForwardedHeadersOptions{ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto}); – Shojaeddin Aug 22 '19 at 12:44
  • @Liam, I have the same issue. According to article https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-3.1#forwarded-headers-middleware-options , it should work directly from context.Connection.RemoteIpAddress. Unfortunately, I also have to fetch client ip from context.Request.Headers[_xForwardedForHeader]. – vishal shah May 27 '20 at 11:56
  • The "x-forwarded-for" header can also contain the port the website it is being hosted on (e.g. 10.0.120:6529). To remove this (assuming it's an IPv4 address), you could use the following instead to remove it: remoteIpAddress = Request.Headers["X-Forwarded-For"].ToString().Split(":")[0]; – Pelle Ravn Jul 20 '20 at 11:42
7

If your Kestrel sits behind a reverse proxy like IIS make sure to forward the headers containing the client IP.
This goes into startup:

app.UseForwardedHeaders(new ForwardedHeadersOptions{ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto});
Yush0
  • 1,547
  • 18
  • 22
3

If I use the Binding Address Localhost:5000 then the IP is returned as "::1" (Localhost IPv6 address). If I bind my Webapi on the IP Address and try to reach it from another client computer, I get Client's IP Address in API Response. There is no need for HTTPAccessor i believe. As per the documentation https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1, the HttpContext.Connection.RemoteIpAddress is set by XForwardedFor header.

If your application (WEBAPI) is behind a NGINX/Apache Reverse Proxy, you should enable those REV Proxies to send X-Forwarded-For Header address which contains the real IP address of the Client, if you don't setup or process X-Forwarded-For Header, then you would always get either Nulls or Reverse-Proxy Server's IP Address.

The GetHostEntry above has no relation to the HTTP Request directly. GetHostEntry is just a NSLookup tool for API programming and it just tells you the IP Addresses reachable for a particular name, but doesn't tell you from which IP address the Request came to WebApi.

Hope that helps

Avinash Barnwal
  • 181
  • 1
  • 7
2

Try this code,

var ipAddress = HttpContext.Connection.RemoteIpAddress;

And if you have another computer in same LAN, try to connect with this pc but use user ip instead of localhost. Otherwise you will get always ::1 result.

Emre SOLUĞAN
  • 193
  • 1
  • 12
-3

After spending some time on searching I found my own question answer. Here I'm also sharing the source link from where I can get my answer and detail explanation for how to query a server to obtain the family addresses and the IP addresses it supports.

Code:

IPHostEntry heserver = Dns.GetHostEntry(Dns.GetHostName());
var ip = heserver.AddressList[2].ToString();

enter image description here

Source

Here is my another Question: How to access server variables in ASP.Net Core 2.x Hope this helps for you all.

Ahmer Ali Ahsan
  • 5,636
  • 16
  • 44
  • 81
  • 3
    I am not sure to understand. It is interesting, but It seems to me that your answer is not giving the *client* ip address from the client that is querying your server, which was your question. – Pac0 Jul 01 '18 at 16:41
  • What you mean to say that above code didn't return client ip address? May be you re right coz I m using localhost and maybe its return me a server ip address. – Ahmer Ali Ahsan Jul 02 '18 at 00:07
  • Yes, it seems to be addresses from the server (the *Host* of the application), corresponding to the server's DNS information, so probably completely unrelated to the client. – Pac0 Jul 02 '18 at 05:56
  • @Pac0 so what can I do now? How can I get Client Ip Address? – Ahmer Ali Ahsan Jul 02 '18 at 05:58
  • I still don't know, unfortunately. In all the situations I know, `HttpContext.Connection.RemoteIpAddress` is the way to go, but for some reason, it doesn't work for you apparently. – Pac0 Jul 02 '18 at 06:08
  • it not necessary your IP address will be in AddressList[2] index. – ANJYR Apr 15 '19 at 11:57
-6

This works for me on .Net Core 2.2:

IPHostEntry heserver = Dns.GetHostEntry(Dns.GetHostName());

var ipAddress = heserver.AddressList.ToList().Where(p => p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).FirstOrDefault().ToString();
tomerpacific
  • 4,704
  • 13
  • 34
  • 52
Gopal
  • 1