Como obter o endereço IP do cliente de um usuário no ASP.NET?


387

Temos que Request.UserHostAddressobter o endereço IP no ASP.NET, mas esse geralmente é o endereço IP do ISP do usuário, não exatamente o endereço IP da máquina do usuário que, por exemplo, clicou em um link. Como posso obter o endereço IP real?

Por exemplo, em um perfil de usuário do Stack Overflow, é: "Última atividade da conta: há 4 horas de 86.123.127.8" , mas o endereço IP da minha máquina é um pouco diferente. Como o Stack Overflow obtém esse endereço?

Em alguns sistemas web, há uma verificação de endereço IP para alguns propósitos. Por exemplo, com um determinado endereço IP, a cada 24 horas o usuário pode ter apenas 5 cliques nos links de download? Esse endereço IP deve ser exclusivo, não para um provedor de serviços de Internet que tenha uma enorme variedade de clientes ou usuários da Internet.

Eu entendi bem?


4
Eles geralmente fazem a mesma coisa e não funcionam corretamente para endereços IP compartilhados. Não se pode fazer muito nesta área.
Mehrdad Afshari 09/04/09

Qual é o problema que você está tentando resolver aqui, por que você acha que precisa do endereço IP?
1011 Steve

3
Eu tenho um aplicativo que verifica cliques em um link específico e um usuário específico (por IP) não pode clicar no link mais de 5 vezes em um dia. um usuário específico?
Mehdi

Respostas:


142

Como outros já disseram, você não pode fazer o que está pedindo. Se você descrever o problema que está tentando resolver, talvez alguém possa ajudar?

Por exemplo

  • você está tentando identificar exclusivamente seus usuários?
  • Você poderia usar um cookie ou o ID da sessão, talvez, em vez do endereço IP?

EditarO endereço que você vê no servidor não deve ser o endereço do ISP, pois você diz que seria um intervalo enorme. O endereço para um usuário doméstico em banda larga será o endereço no roteador; portanto, todos os dispositivos internos parecerão iguais, mas o roteador usa o NAT para garantir que o tráfego seja roteado corretamente para cada dispositivo. Para usuários acessando de um ambiente de escritório, o endereço pode ser o mesmo para todos os usuários. Os sites que usam o endereço IP para identificação correm o risco de cometer erros muito graves - os exemplos que você dá são bons e geralmente falham. Por exemplo, meu escritório está no Reino Unido, o ponto de interrupção (onde "pareço estar" na Internet) está em outro país onde nossa principal instalação de TI está; portanto, do meu escritório, meu endereço IP parece não estar no Reino Unido. Por esse motivo, não consigo acessar apenas o conteúdo da web do Reino Unido, como o BBC iPlayer). A qualquer momento, centenas ou mesmo milhares de pessoas na minha empresa parecem acessar a web a partir do mesmo endereço IP.

Ao escrever o código do servidor, você nunca pode ter certeza a que se refere o endereço IP que vê. Alguns usuários gostam desta maneira. Algumas pessoas usam deliberadamente um proxy ou VPN para confundi-lo ainda mais.

Quando você diz que o endereço da sua máquina é diferente do endereço IP mostrado no StackOverflow, como está descobrindo o endereço da sua máquina? Se você está apenas procurando localmente usando ipconfigalgo assim, eu esperaria que fosse diferente pelas razões descritas acima. Se você quiser verificar o que o mundo exterior pensa, dê uma olhada no whatismyipaddress.com/ .

Este link da Wikipedia no NAT fornecerá algumas informações sobre isso.


então eu entendi que em aplicativos do lado do servidor não podemos ter certeza sobre o endereço IP. isso significa que a programação do lado do cliente é a solução? quer dizer, por exemplo, com alguns códigos JavaScript, podemos fazer isso?
Mehdi

12
NÃO, isso não faria sentido, o endereço IP que o cliente "pensa" que ele terá será interno à casa ou escritório, não terá sentido no mundo externo. Por exemplo, a maioria dos roteadores domésticos distribui endereços IP no intervalo 192.168.1.xxx; portanto, milhares de máquinas têm o mesmo endereço em suas próprias redes.
1011 Steve

12
Não, não é único. Dois usuários atrás do mesmo roteador usando NAT terão o mesmo endereço IP. Eu realmente acho que você precisa ler sobre isso, veja o link na minha edição.
11409 Steve Steve

11
Então, por que empresas como AWS, Azure etc usam o endereço IP nas regras do grupo de segurança e permitem que apenas esse endereço IP se conecte à VM?

2
@ user5950947: porque o Azure espera que você seja uma empresa com um endereço IP público estático. É seguro supor que sua empresa só acessará seu endereço IP público, por isso é um bom recurso de segurança adicional. Mas os endereços IP podem ser falsificados ou a sua rede pode ser invadida, portanto nunca deve ser a única segurança.
Deantwo

449

Muitas vezes, você deseja saber o endereço IP de alguém que visita seu site. Embora o ASP.NET tenha várias maneiras de fazer isso, uma das melhores maneiras que vimos é usar o "HTTP_X_FORWARDED_FOR" da coleção ServerVariables.

Aqui está o porquê...

Às vezes, seus visitantes estão atrás de um servidor proxy ou de um roteador e o padrão Request.UserHostAddresscaptura apenas o endereço IP do servidor ou roteador proxy. Quando esse for o caso, o endereço IP do usuário será armazenado na variável do servidor ("HTTP_X_FORWARDED_FOR").

Então, o que queremos fazer é primeiro verificar "HTTP_X_FORWARDED_FOR" e, se estiver vazio, simplesmente retornamos ServerVariables("REMOTE_ADDR").

Embora esse método não seja infalível, ele pode levar a melhores resultados. Abaixo está o código ASP.NET no VB.NET, obtido na postagem do blog de James Crowley "Gotcha: HTTP_X_FORWARDED_FOR retorna vários endereços IP"

C #

protected string GetIPAddress()
{
    System.Web.HttpContext context = System.Web.HttpContext.Current; 
    string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

    if (!string.IsNullOrEmpty(ipAddress))
    {
        string[] addresses = ipAddress.Split(',');
        if (addresses.Length != 0)
        {
            return addresses[0];
        }
    }

    return context.Request.ServerVariables["REMOTE_ADDR"];
}

VB.NET

Public Shared Function GetIPAddress() As String
    Dim context As System.Web.HttpContext = System.Web.HttpContext.Current
    Dim sIPAddress As String = context.Request.ServerVariables("HTTP_X_FORWARDED_FOR")
    If String.IsNullOrEmpty(sIPAddress) Then
        Return context.Request.ServerVariables("REMOTE_ADDR")
    Else
        Dim ipArray As String() = sIPAddress.Split(New [Char]() {","c})
        Return ipArray(0)
    End If
End Function

24
Certifique-se de não usar esse código por motivos de segurança, pois qualquer pessoa pode falsificar HTTP_X_FORWARDED_FOR ou cabeçalhos semelhantes. Portanto, se você usar isso para logs de segurança ou verificações de segurança, um invasor poderá ignorá-lo facilmente.
dr. mal

4
No seu link,, what we actually needed to be doing was take the last IP addressmas seu código é o primeiro addresses[0]. Qual é correto?
22619 Nelson Rothermel

4
@NelsonRothermel Baseado em en.wikipedia.org/wiki/X-Forwarded-For#Format, se você deseja o cliente (em vez do proxy anterior), use o primeiro .
Richard

4
@ dr.evil Então, o que você propõe? Porque eu quero definir o acesso aos serviços WCF por IPs especificados.
Krypru

7
addresses.Length != 0não é necessário, uma vez que nunca pode ser 0.
James Wilkins

78

ATUALIZAÇÃO: Obrigado a Bruno Lopes. Se vários endereços IP vierem, é necessário usar este método:

    private string GetUserIP()
    {
        string ipList = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

        if (!string.IsNullOrEmpty(ipList))
        {
            return ipList.Split(',')[0];
        }

        return Request.ServerVariables["REMOTE_ADDR"];
    }

3
Conforme observado em outras respostas, HTTP_X_FORWARDED_FOR pode ser uma lista de IPs, separados por vírgulas.
Bruno Lopes

Em resposta à função, recebo :: 1 todas as vezes. Não consigo obter o endereço IP completo ???
farhangdon

11
retornará :: 1 no host local. experimente-o no ambiente productino e deve ficar bem.
Benny Margalit

11
@farhangdon, o seguinte código irá retornar o endereço IP no host local como @Bat_Programmer escreveu abaixoSystem.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList[1].ToString();
Benny Margalit

NÃO FAÇA ISTO! Cuidado para não usar simplesmente o primeiro endereço IP da lista. Você só deve pular IPs de proxy conhecidos começando na entrada mais à direita para evitar ataques do tipo intermediário e falsificação de cabeçalho.
Jpsy

24

Se for c # veja dessa maneira, é muito simples

string clientIp = (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? 
                   Request.ServerVariables["REMOTE_ADDR"]).Split(',')[0].Trim();

8
Se ambas as variáveis ​​do servidor puderem ser nulas, isso poderá gerar uma exceção.
Michael Freidgeim

O que é Solicitação de Referência aqui? I ServerVariables não encontrado
Brownbagger11

23

O que mais você considera o endereço IP do usuário? Se você deseja o endereço IP do adaptador de rede, receio que não haja maneira possível de fazer isso em um aplicativo Web. Se o seu usuário estiver com NAT ou outras coisas, você também não poderá obter o IP.

Atualização : Embora existam sites que usam IP para limitar o usuário (como o rapidshare), eles não funcionam corretamente em ambientes NAT.


22

Acho que devo compartilhar minha experiência com todos vocês. Bem, em algumas situações, o REMOTE_ADDR NÃO dará o que você está procurando. Por exemplo, se você tiver um Balanceador de Carga nos bastidores e se estiver tentando obter o IP do Cliente, estará em apuros. Eu verifiquei com meu software de máscara de IP e também com meus colegas em diferentes continentes. Então aqui está a minha solução.

Quando quero saber o IP de um cliente, tento escolher todas as evidências possíveis para determinar se elas são únicas:

Aqui encontrei outro sever-var que poderia ajudar a todos, se você deseja obter o IP exato do lado do cliente. então estou usando: HTTP_X_CLUSTER_CLIENT_IP

HTTP_X_CLUSTER_CLIENT_IP sempre fornece o IP exato do cliente. De qualquer forma, se não fornecer o valor, você deve procurar HTTP_X_FORWARDED_FOR , pois é o segundo melhor candidato para obter o IP do cliente e, em seguida, o REMOTE_ADDR var que pode ou não retornar o IP, mas para mim, tendo tudo isso três é o que acho melhor para monitorá-los.

Espero que isso ajude alguns caras.


É preciso dizer que os cabeçalhos http_x _... podem ser facilmente falsificados em relação à variável remote_addr. E, portanto, remote_addr continua sendo a fonte mais confiável para o endereço IP do cliente.
Ciro Corvino

11
@CiroCorvino você está certo, mas quando você tem seu site hospedado em um servidor que está executando atrás do Load Balancer (como eu já mencionei no meu post), o remote_addr não fornecerá o IP que você está procurando. Eu experimentei o que você está dizendo, mas quando descobri a solução, o que afirmei funciona melhor para mim.
KMX

Desculpe @KMX, na verdade eu também uso uma combinação de remote_addr e http_x_forwarded para inferir algumas suposições sobre a origem da solicitação. Se você editar seu post, eu atualizar o meu voto
Ciro Corvino

15

Você pode usar:

System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList.GetValue(0).ToString();

11
obrigado, para mim este é o único método que realmente retorna meu IP no host local.
Benny Margalit

Na verdade, o que eu usei para obter o endereço IP do host local éSystem.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList[1].ToString();
Benny Margalit

11
Esse código funciona apenas para mim e eu posso obter IPv6 e IPv4 usando GetValue (0) e GetValue (1), respectivamente. Obrigado por votar!
Raj Baral 01/01

No entanto, eu estou recebendo um erro durante a execução que no violino Request for the permission of type 'System.Net.DnsPermission, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
vibs2006

OP perguntando como obter o IP do usuário remoto da Web, não o endereço do seu host local.
t.durden

13

Os endereços IP fazem parte da camada de rede na "pilha de sete camadas". A camada de rede pode fazer o que quiser com o endereço IP. É o que acontece com um servidor proxy, NAT, retransmissão ou o que for.

A camada de aplicativo não deve depender do endereço IP de forma alguma. Em particular, um endereço IP não deve ser um identificador de outra coisa senão o identificador mais adequado de uma extremidade de uma conexão de rede. Assim que uma conexão é fechada, você deve esperar que o endereço IP (do mesmo usuário) mude.


11
Tudo bem, mas o que você faz quando um cliente de um sistema multilocatário exige que as contas de seus usuários possam fazer login apenas a partir de um endereço IP especificado?
Ronnie Overby

11
Eles precisam informar qual endereço IP o servidor verá. Se eles precisarem que haja um endereço específico, eles não poderão estar atrás de um NAT ou similar.
John Saunders

@RonnieOverby Estou na mesma situação. Preciso saber de que IP eles estão se conectando e deve estar na minha lista de permissões. Em seguida, o aplicativo pode ativar ou desativar determinadas funcionalidades com base em seu IP. É isso que o cliente deseja.
t.durden

10

Até agora, todas as respostas levam em consideração o cabeçalho não padronizado, mas muito comum X-Forwarded-For. Existe um Forwardedcabeçalho padronizado que é um pouco mais difícil de analisar. Alguns exemplos são os seguintes:

Forwarded: for="_gazonk"
Forwarded: For="[2001:db8:cafe::17]:4711"
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for=198.51.100.17

Eu escrevi uma classe que leva em consideração esses dois cabeçalhos ao determinar o endereço IP de um cliente.

using System;
using System.Web;

namespace Util
{
    public static class IP
    {
        public static string GetIPAddress()
        {
            return GetIPAddress(new HttpRequestWrapper(HttpContext.Current.Request));
        }

        internal static string GetIPAddress(HttpRequestBase request)
        {
            // handle standardized 'Forwarded' header
            string forwarded = request.Headers["Forwarded"];
            if (!String.IsNullOrEmpty(forwarded))
            {
                foreach (string segment in forwarded.Split(',')[0].Split(';'))
                {
                    string[] pair = segment.Trim().Split('=');
                    if (pair.Length == 2 && pair[0].Equals("for", StringComparison.OrdinalIgnoreCase))
                    {
                        string ip = pair[1].Trim('"');

                        // IPv6 addresses are always enclosed in square brackets
                        int left = ip.IndexOf('['), right = ip.IndexOf(']');
                        if (left == 0 && right > 0)
                        {
                            return ip.Substring(1, right - 1);
                        }

                        // strip port of IPv4 addresses
                        int colon = ip.IndexOf(':');
                        if (colon != -1)
                        {
                            return ip.Substring(0, colon);
                        }

                        // this will return IPv4, "unknown", and obfuscated addresses
                        return ip;
                    }
                }
            }

            // handle non-standardized 'X-Forwarded-For' header
            string xForwardedFor = request.Headers["X-Forwarded-For"];
            if (!String.IsNullOrEmpty(xForwardedFor))
            {
                return xForwardedFor.Split(',')[0];
            }

            return request.UserHostAddress;
        }
    }
}

Abaixo estão alguns testes de unidade que eu usei para validar minha solução:

using System.Collections.Specialized;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UtilTests
{
    [TestClass]
    public class IPTests
    {
        [TestMethod]
        public void TestForwardedObfuscated()
        {
            var request = new HttpRequestMock("for=\"_gazonk\"");
            Assert.AreEqual("_gazonk", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv6()
        {
            var request = new HttpRequestMock("For=\"[2001:db8:cafe::17]:4711\"");
            Assert.AreEqual("2001:db8:cafe::17", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv4()
        {
            var request = new HttpRequestMock("for=192.0.2.60;proto=http;by=203.0.113.43");
            Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv4WithPort()
        {
            var request = new HttpRequestMock("for=192.0.2.60:443;proto=http;by=203.0.113.43");
            Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedMultiple()
        {
            var request = new HttpRequestMock("for=192.0.2.43, for=198.51.100.17");
            Assert.AreEqual("192.0.2.43", Util.IP.GetIPAddress(request));
        }
    }

    public class HttpRequestMock : HttpRequestBase
    {
        private NameValueCollection headers = new NameValueCollection();

        public HttpRequestMock(string forwarded)
        {
            headers["Forwarded"] = forwarded;
        }

        public override NameValueCollection Headers
        {
            get { return this.headers; }
        }
    }
}

9

Se você estiver usando o CloudFlare, poderá tentar este método de extensão :

public static class IPhelper
{
    public static string GetIPAddress(this HttpRequest Request)
    {
        if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();

        if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) return Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();

        return Request.UserHostAddress;
    }
}

então

string IPAddress = Request.GetIPAddress();

E usando F5 ou Palo Alto?
Kiquenet 12/12

8
string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;

7

O que você pode fazer é armazenar o IP do roteador do seu usuário e também o IP encaminhado e tentar torná-lo confiável usando os dois IPs [Público externo e Privado interno]. Mas novamente depois de alguns dias, o cliente pode receber um novo IP interno do roteador, mas ele será mais confiável.


5

Combinando as respostas de @Tony e @mangokun , eu criei o método de extensão a seguir:

public static class RequestExtensions
{
    public static string GetIPAddress(this HttpRequest Request)
    {
        if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();

        if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
        {
            string ipAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

            if (!string.IsNullOrEmpty(ipAddress))
            {
                string[] addresses = ipAddress.Split(',');
                if (addresses.Length != 0)
                {
                    return addresses[0];
                }
            }
        }

        return Request.UserHostAddress;
    }
}

Por que você usa HTTP_X_FORWARDED_FORmas não X_FORWARDED_FOR? Eles são os mesmos?
Igor Yalovoy

3

usar no arquivo ashx

public string getIP(HttpContext c)
{
    string ips = c.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
    if (!string.IsNullOrEmpty(ips))
    {
        return ips.Split(',')[0];
    }
    return c.Request.ServerVariables["REMOTE_ADDR"];
}

2
public static class Utility
{
    public static string GetClientIP(this System.Web.UI.Page page)
    {
        string _ipList = page.Request.Headers["CF-CONNECTING-IP"].ToString();
        if (!string.IsNullOrWhiteSpace(_ipList))
        {
            return _ipList.Split(',')[0].Trim();
        }
        else
        {
            _ipList = page.Request.ServerVariables["HTTP_X_CLUSTER_CLIENT_IP"];
            if (!string.IsNullOrWhiteSpace(_ipList))
            {
                return _ipList.Split(',')[0].Trim();
            }
            else
            {
                _ipList = page.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (!string.IsNullOrWhiteSpace(_ipList))
                {
                    return _ipList.Split(',')[0].Trim();
                }
                else
                {
                    return page.Request.ServerVariables["REMOTE_ADDR"].ToString().Trim();
                }
            }
        }
    }
}

Usar;

string _ip = this.GetClientIP();

0

É fácil.Tente:

var remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;

só isso :))


11
Para sua informação, o código acima funciona apenas no Asp.Net Core e não no link
Dobin 19/03

-1

Olá pessoal A maioria dos códigos que você encontrará retornará o endereço IP do servidor e não o endereço IP do cliente. De qualquer forma esse código retornará o endereço IP do cliente correto. Para obter mais informações, basta verificar isso

https://www.youtube.com/watch?v=Nkf37DsxYjI

para obter seu endereço IP local usando javascript, você pode colocar esse código dentro da sua tag de script

<script>
    var RTCPeerConnection = /*window.RTCPeerConnection ||*/
     window.webkitRTCPeerConnection || window.mozRTCPeerConnection;

         if (RTCPeerConnection) (function () {
             var rtc = new RTCPeerConnection({ iceServers: [] });
             if (1 || window.mozRTCPeerConnection) {      
                 rtc.createDataChannel('', { reliable: false });
             };

             rtc.onicecandidate = function (evt) {

                 if (evt.candidate)
                     grepSDP("a=" + evt.candidate.candidate);
             };
             rtc.createOffer(function (offerDesc) {
                 grepSDP(offerDesc.sdp);
                 rtc.setLocalDescription(offerDesc);
             }, function (e) { console.warn("offer failed", e); });


             var addrs = Object.create(null);
             addrs["0.0.0.0"] = false;
             function updateDisplay(newAddr) {
                 if (newAddr in addrs) return;
                 else addrs[newAddr] = true;
                 var displayAddrs = Object.keys(addrs).filter(function
(k) { return addrs[k]; });
                 document.getElementById('list').textContent =
displayAddrs.join(" or perhaps ") || "n/a";
             }

             function grepSDP(sdp) {
                 var hosts = [];
                 sdp.split('\r\n').forEach(function (line) { 
                     if (~line.indexOf("a=candidate")) {   
                         var parts = line.split(' '),   
                             addr = parts[4],
                             type = parts[7];
                         if (type === 'host') updateDisplay(addr);
                     } else if (~line.indexOf("c=")) {      
                         var parts = line.split(' '),
                             addr = parts[2];
                         updateDisplay(addr);
                     }
                 });
             }
         })(); else
         {
             document.getElementById('list').innerHTML = "<code>ifconfig| grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
             document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";

         }




</script>
<body>
<div id="list"></div>
</body>

e Para obter seu endereço IP público, você pode usar esse código dentro da sua tag de script

  function getIP(json) {
    document.write("My public IP address is: ", json.ip);
  }


<script type="application/javascript" src="https://api.ipify.org?format=jsonp&callback=getIP"></script>


-7

Tentar:

using System.Net;

public static string GetIpAddress()  // Get IP Address
{
    string ip = "";     
    IPHostEntry ipEntry = Dns.GetHostEntry(GetCompCode());
    IPAddress[] addr = ipEntry.AddressList;
    ip = addr[2].ToString();
    return ip;
}
public static string GetCompCode()  // Get Computer Name
{   
    string strHostName = "";
    strHostName = Dns.GetHostName();
    return strHostName;
}

Isso retorna o endereço IP do servidor
Sreekumar P

É sobre o asp.net, que é um aplicativo da web, que roda em um servidor, não no computador dos usuários.
Dokman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.