¿Cómo obtengo la dirección IP del cliente en ASP.NET CORE?

202

¿Puede decirme cómo obtener la dirección IP del cliente en ASP.NET cuando no se utiliza MVC 6. Request.ServerVariables["REMOTE_ADDR"]?

Eadam
fuente
Ejemplo:httpContext.GetFeature<IHttpConnectionFeature>().RemoteIpAddress
Kiran Challa
El motivo de retención está disponible en la parte inferior de la pregunta: "Hay demasiadas respuestas posibles, o las buenas respuestas serían demasiado largas para este formato. Agregue detalles para limitar el conjunto de respuestas o para aislar un problema que puede responderse en unos pocos párrafos ".
Kevin Brown
12
No creo que la respuesta sea lo suficientemente larga. Es algo simple que hacemos en las versiones anteriores de MVC. Solo pregunté cómo hacerlo en la última versión beta. En segundo lugar, si hay muchas respuestas, ¿por qué nadie me señala la UNA? De hecho, MVC 6 es beta y creo que ni siquiera leyeron la pregunta correctamente antes de sostenerla.
Eadam
Edite su pregunta mostrando más de lo que ha intentado y una entrada / salida clara. no te quejes solo de que tu pregunta se cerró sin al menos intentar mejorarla.
10
Solo los programadores del mismo dominio deben cerrar la pregunta. Cualquiera que trabaje en asp.net 5.0 simplemente sabrá lo que estoy preguntando en fracción de segundo. El resto de ustedes me está castigando por publicar solo una pregunta simple.
Eadam

Respuestas:

271

La API ha sido actualizada. No estoy seguro de cuándo cambió, pero según Damien Edwards a fines de diciembre, ahora puede hacer esto:

var remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress;
David Peden
fuente
9
El RemoteIpAddresses siempre nullpara mí, cuando publico que el sitio web en IIS y log esto en un archivo.
A-Sharabiani
3
Parece que el problema se solucionó en el rc 2
Jon
12
Siempre obtengo 127.0.0.1 incluso cuando me conecto de forma remota
frostymarvelous el
32
Esto me devuelve ":: 1", que es el formato IPv6. ¿Cómo ven los demás 127.0.0.1?
Derek Greer
44
¿Alguien más recibe la dirección IP local de su servidor IIS?
dave317
73

En project.json agregue una dependencia a:

"Microsoft.AspNetCore.HttpOverrides": "1.0.0"

En Startup.cs, en el Configure()método agregue:

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

Y por supuesto:

using Microsoft.AspNetCore.HttpOverrides;

Entonces, podría obtener la ip usando:

Request.HttpContext.Connection.RemoteIpAddress

En mi caso, al depurar en VS siempre obtuve el host local IpV6, pero cuando lo implementaba en un IIS siempre obtenía la IP remota.

Algunos enlaces útiles: ¿Cómo obtengo la dirección IP del cliente en ASP.NET CORE? y RemoteIpAddress siempre es nulo

El ::1es quizás debido a:

Las conexiones terminan en IIS, que luego reenvía a Kestrel, el servidor web v.next, por lo que las conexiones al servidor web son de hecho de localhost. ( https://stackoverflow.com/a/35442401/5326387 )

Johna
fuente
66
Esta es la respuesta correcta, que también está documentada en la documentación oficial sobre proxies inversos: docs.microsoft.com/en-us/aspnet/core/host-and-deploy/…
Melvyn
8
es necesario señalar que "app.UseForwardsHeaders ..." debe agregarse antes que app.UseAuthentication (); línea, en caso de que use identidad
netfed
1
Esto funcionó perfectamente y lo he probado en IIS alojado localmente y en Azure. Funciona en ambos lugares.
ThomasCle
72

Se puede agregar alguna lógica de respaldo para manejar la presencia de un equilibrador de carga.

Además, a través de la inspección, el X-Forwarded-Forencabezado se establece de todos modos, incluso sin un equilibrador de carga (¿posiblemente debido a una capa de cernícalo adicional?):

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);
}

Supuestos _httpContextAccessorfueron proporcionados a través de DI.

crokusek
fuente
2
Esta es la respuesta correcta. No hay una sola forma de recuperar la dirección IP, especialmente cuando su aplicación está detrás de un Nginx, un equilibrador de carga o algo así. ¡Gracias!
Feu
tipo @feu, ya que AspNetCore puede anular la propiedad RemoteIpAddress con encabezados como X-Forward-For.
Mark Lopez
@crokusek ... tratando de adaptar su solución, pero VS me obliga a la clase que encapsula este código estático. ¿Tiene este código en su proyecto de aplicación web o en una biblioteca de clase en la solución?
dinotom
Los primeros 2 métodos deben estar en una instancia que proporcione __httpContextAccessor (o adaptarlo). Los segundos 2 métodos de cadena se extrajeron de una clase de extensiones estáticas separadas.
crokusek
Esta es una buena solución, especialmente cuando su aplicación usa Kestrel y está alojada con Nginx en Linux.
Timothy Macharia
16

Puede usar el IHttpConnectionFeaturepara obtener esta información.

var remoteIpAddress = httpContext.GetFeature<IHttpConnectionFeature>()?.RemoteIpAddress;
Kiran Challa
fuente
¡Gracias por la respuesta!
Eadam
2
¿Funciona para Kestrel hosting? En mi demo, httpContext.GetFeature<IHttpConnectionFeature>()siempre se null.
Jerry Bian
2
@JerryBian según este documento: github.com/aspnet/Docs/blob/master/aspnet/fundamentals/… , IHttpConnectionFeature no es compatible con Kestrel (todavía).
qbik
@JerryBian es ahora
David Peden
Debe haber quedado en desuso - la versión @feradz funciona para mí en RC-1
fiat
12
var remoteIpAddress = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;
feradz
fuente
66
Demasiado complicado MVC ya lo llama internamente y lo somete HttpContext.Connection.RemoteIpAddress.
Fred
@Fred: tu versión vuelve nula para mí en RC-1 - IIS y Kestrel
fiat
7

En ASP.NET 2.1, en StartUp.cs, agregue estos servicios:

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

y luego haz 3 pasos:

  1. Defina una variable en su controlador MVC

    private IHttpContextAccessor _accessor;
  2. DI en el constructor del controlador

    public SomeController(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }
  3. Recuperar la dirección IP

    _accessor.HttpContext.Connection.RemoteIpAddress.ToString()

Así es como se hace.

hojjat.mi
fuente
2
Esto me da :: 1. Asp.Net Core 2.2., En localhost.
Stian
::1es localhost en IPv6. El equivalente IPv4 de127.0.0.1
Andy
6

Esto funciona para mí (DotNetCore 2.1)

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

En mi caso, tengo la aplicación web DotNet Core 2.2 ejecutándose en DigitalOcean con docker y nginx como proxy inverso. Con este código en Startup.cs puedo obtener la IP del cliente

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 era la ip que estaba recibiendo antes de usar

Request.HttpContext.Connection.RemoteIpAddress.ToString();
gorums
fuente
2

Primero, en .Net Core 1.0 Agregar using Microsoft.AspNetCore.Http.Features;al controlador Luego dentro del método relevante:

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

Leí varias otras respuestas que no se pudieron compilar porque estaba usando un httpContext en minúscula, lo que llevó al VS a agregar usando Microsoft.AspNetCore.Http, en lugar del uso apropiado, o con HttpContext (el compilador también es engañoso).

Chico
fuente
2

obtener ipaddress y hostname en .net core

poner este código en el controlador

Sigue estos pasos:

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

Descubrí que algunos de ustedes descubrieron que la dirección IP que obtienen es ::: 1 o 0.0.0.1

Este es el problema porque intenta obtener IP de su propia máquina y la confusión de C # que intenta devolver IPv6.

Entonces, implemento la respuesta de @Johna ( https://stackoverflow.com/a/41335701/812720 ) y @David ( https://stackoverflow.com/a/8597351/812720 ), ¡Gracias a ellos!

y aquí a la solución:

  1. agregue el paquete Microsoft.AspNetCore.HttpOverrides en sus referencias (dependencias / paquetes)

  2. agregue esta línea en 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. para obtener IPAddress, use este código en cualquiera de sus 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();
    }

y ahora puede obtener la dirección IPv4 de remoteIpAddress o resultado

Sruit A.Suk
fuente
1

prueba esto.

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

Ejecutar .NET core(3.1.4) IISdetrás de un equilibrador de carga no funcionó con otras soluciones sugeridas.

Lectura manual del X-Forwarded-Forencabezado hace.

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();
    ip = IPAddress.Parse(header);
}
else
{
    // this will always have a value (running locally in development won't have the header)
    ip = Request.HttpContext.Connection.RemoteIpAddress;
}

Estoy ejecutando un paquete autónomo usando el paquete de alojamiento .

Aage
fuente
0

Al ejecutar ASP.NET Core 2.1 detrás de un proxy inverso de Traefik en Ubuntu, necesito configurar su IP de puerta de enlace KnownProxiesdespués de instalar el Microsoft.AspNetCore.HttpOverridespaquete oficial

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

De acuerdo con la documentación , esto es necesario si el proxy inverso no se ejecuta en localhost. El docker-compose.ymlde Traefik ha asignado una dirección IP estática:

networks:
  my-docker-network:
    ipv4_address: 192.168.3.2

Alternativamente, debería ser suficiente para asegurarse de que una red conocida esté definida aquí para especificar su puerta de enlace en .NET Core.

León
fuente