Como obtenho o endereço IP do cliente no ASP.NET CORE?

202

Você pode me informar como obter o endereço IP do cliente no ASP.NET ao usar o MVC 6. Request.ServerVariables["REMOTE_ADDR"]não funciona.

eadam
fonte
Exemplo:httpContext.GetFeature<IHttpConnectionFeature>().RemoteIpAddress
Kiran Challa 23/02
O motivo da retenção está disponível na parte inferior da pergunta: "Existem muitas respostas possíveis ou boas respostas seriam muito longas para esse formato. Adicione detalhes para restringir o conjunto de respostas ou isolar um problema que pode ser respondido em alguns parágrafos ".
Kevin Brown
12
Não acho que a resposta seja longa o suficiente. É uma coisa simples que fazemos nas versões mais antigas do MVC. Eu apenas perguntei como fazê-lo na versão beta mais recente. Em segundo lugar, se há muitas respostas, por que alguém simplesmente não me aponta para uma delas? De fato, o MVC 6 é beta e acho que eles nem leram a pergunta corretamente antes de segurá-la.
24515 eadam
Edite sua pergunta mostrando mais do que você tentou e uma entrada / saída clara. não reclame apenas que sua pergunta foi encerrada sem ao menos tentar melhorá-la.
10
Somente programadores do mesmo domínio devem fechar a questão. Qualquer pessoa que trabalhe no asp.net 5.0 simplesmente saberá o que estou perguntando em uma fração de segundo. O resto de vocês está me punindo por postar apenas uma pergunta simples.
eadam

Respostas:

271

A API foi atualizada. Não sabe ao certo quando foi alterado, mas de acordo com Damien Edwards no final de dezembro, agora você pode fazer isso:

var remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress;
David Peden
fonte
9
O RemoteIpAddressé sempre nullpara mim, quando publico o site no IIS e o registro em um arquivo.
A-Sharabiani
3
Parece que o problema foi corrigido no rc 2
Jon
12
Eu sempre obter 127.0.0.1 mesmo quando eu conectar remotamente
frostymarvelous
32
Isso está retornando ":: 1" para mim, que é o formato IPv6. Como os outros estão vendo o 127.0.0.1?
Drek Greer
4
Mais alguém recebe o endereço IP local do servidor IIS retornado?
Dave317
73

No project.json, adicione uma dependência para:

"Microsoft.AspNetCore.HttpOverrides": "1.0.0"

Em Startup.cs, no Configure()método, adicione:

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

E claro:

using Microsoft.AspNetCore.HttpOverrides;

Então, eu poderia obter o ip usando:

Request.HttpContext.Connection.RemoteIpAddress

No meu caso, ao depurar no VS, sempre obtive o host local IpV6, mas quando implantado em um IIS obtive sempre o IP remoto.

Alguns links úteis: Como obtenho o endereço IP do cliente no ASP.NET CORE? e RemoteIpAddress é sempre nulo

A ::1é talvez por causa de:

Terminação de conexões no IIS, que encaminha para o Kestrel, o servidor da Web v.next, para que as conexões com o servidor da Web sejam realmente do localhost. ( https://stackoverflow.com/a/35442401/5326387 )

Johna
fonte
6
Esta é a resposta correta, que também está documentada na documentação oficial sobre proxies reversos: docs.microsoft.com/en-us/aspnet/core/host-and-deploy/…
Melvyn
8
é necessário salientar que o "app.UseForwardedHeaders ..." precisa ser adicionado antes do app.UseAuthentication (); linha, no caso de você usar indentity
netfed
1
Isso funcionou perfeitamente e eu testei no IIS hospedado localmente e no Azure. Trabalha nos dois lugares.
ThomasCle
72

Alguma lógica de fallback pode ser adicionada para lidar com a presença de um Load Balancer.

Além disso, através da inspeção, o X-Forwarded-Forcabeçalho é definido de qualquer maneira, mesmo sem um Load Balancer (possivelmente por causa da camada adicional do Kestrel?):

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

Supõe que _httpContextAccessorfoi fornecido através do DI.

crokusek
fonte
2
Esta é a resposta certa. Não há uma maneira única de recuperar o endereço IP, especialmente quando seu aplicativo está protegido por um Nginx, um balanceador de carga ou algo assim. Obrigado!
Feu
@feu, pois o AspNetCore pode substituir a propriedade RemoteIpAddress por cabeçalhos como X-Forwarded-For.
Mark Lopez
@ crokusek ... tentando adaptar sua solução, mas VS me forçando a classe que encapsula esse código estático. Você tem esse código no seu projeto de aplicativo da web ou em uma biblioteca de classes na solução?
Dinotom #
Os 2 primeiros métodos devem estar em uma instância que forneça __httpContextAccessor (ou adapte-o). Os segundos métodos de duas cadeias foram extraídos de uma classe de extensões estáticas separada.
crokusek
Essa é uma boa solução, especialmente quando seu aplicativo usa o Kestrel e está hospedado no Nginx no Linux.
Timothy Macharia
16

Você pode usar o IHttpConnectionFeaturepara obter essas informações.

var remoteIpAddress = httpContext.GetFeature<IHttpConnectionFeature>()?.RemoteIpAddress;
Kiran Challa
fonte
Obrigado pela resposta!
eadam
2
Isso funciona para hospedagem Kestrel? Na minha demo, httpContext.GetFeature<IHttpConnectionFeature>()seja sempre null.
Jerry Bian
2
@JerryBian de acordo com este documento: github.com/aspnet/Docs/blob/master/aspnet/fundamentals/… , IHttpConnectionFeature ainda não é suportado no Kestrel.
Qbik
@JerryBian is now
David Peden
Deve ter sido preterido - Works versão @feradz para mim em RC-1
fiat
12
var remoteIpAddress = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;
feradz
fonte
6
Excessivamente complicado. O MVC já chama isso internamente e o coloca abaixo HttpContext.Connection.RemoteIpAddress.
22416 Fred
@Fred - sua versão retorna nulo para mim em RC-1 - IIS e Kestrel
fiat
7

No ASP.NET 2.1, no StartUp.cs, adicione este serviço:

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

e depois faça 3 etapas:

  1. Defina uma variável no seu controlador MVC

    private IHttpContextAccessor _accessor;
  2. DI no construtor do controlador

    public SomeController(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }
  3. Recuperar o endereço IP

    _accessor.HttpContext.Connection.RemoteIpAddress.ToString()

É assim que se faz.

hojjat.mi
fonte
2
Isso me dá :: 1. Asp.Net Core 2.2., No host local.
Stian
::1é localhost no IPv6. O equivalente ao IPv4 de127.0.0.1
Andy
6

Isso funciona para mim (DotNetCore 2.1)

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

No meu caso, tenho o DotNet Core 2.2 Web App em execução no DigitalOcean com docker e nginx como proxy reverso. Com esse código em Startup.cs, posso obter o IP do 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 foi o ip que eu estava recebendo antes de usar

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

Primeiro, no .Net Core 1.0 Adicione using Microsoft.AspNetCore.Http.Features;ao controlador Em seguida, dentro do método relevante:

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

Li várias outras respostas que não foram compiladas porque estava usando um httpContext em minúsculas, levando o VS a adicionar usando Microsoft.AspNetCore.Http, em vez do uso apropriado, ou com HttpContext (o compilador também é enganoso).

Cara
fonte
2

obtenha ipaddress e hostname no núcleo .net

coloque esse código no controlador

Siga esses passos:

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
fonte
2

Descobri que alguns de vocês descobriram que o endereço IP obtido é ::: 1 ou 0.0.0.1

Esse é o problema porque você tenta obter IP da sua própria máquina e a confusão de C # que tenta retornar o IPv6.

Portanto, implementei a resposta de @Johna ( https://stackoverflow.com/a/41335701/812720 ) e @David ( https://stackoverflow.com/a/8597351/812720 ), obrigado a eles!

e aqui para solução:

  1. adicione Microsoft.AspNetCore.HttpOverrides Package nas suas referências (dependências / pacotes)

  2. adicione esta linha em 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 obter o IPAddress, use esse código em qualquer um dos seus 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();
    }

e agora você pode obter o endereço IPv4 de remoteIpAddress ou result

Sruit A.Suk
fonte
1

tente isso.

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

Executando .NET core(3.1.4) emIIS atrás de um balanceador de carga não funcionou com outras soluções sugeridas.

A leitura manual do X-Forwarded-Forcabeçalho faz.

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

Estou executando um pacote independente usando o pacote de hospedagem .

Aage
fonte
0

Executando o ASP.NET Core 2.1 atrás de um Proxy reverso Traefik no Ubuntu, preciso definir o IP do gateway KnownProxiesdepois de instalar o Microsoft.AspNetCore.HttpOverridespacote oficial

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

De acordo com a documentação , isso é necessário se o proxy reverso não estiver em execução no host local. O docker-compose.ymlTraefik atribuiu um endereço IP estático:

networks:
  my-docker-network:
    ipv4_address: 192.168.3.2

Como alternativa, deve ser suficiente garantir que uma rede conhecida seja definida aqui para especificar seu gateway no .NET Core.

Leão
fonte