¿Cómo obtener la dirección IP del cliente de un usuario en ASP.NET?

Tenemos Request.UserHostAddress para obtener la dirección IP en ASP.NET, pero esta suele ser la dirección IP del usuario del ISP, no exactamente la dirección IP de la máquina del usuario que, por ejemplo, hizo clic en un enlace. ¿Cómo puedo obtener la dirección IP real?

Por ejemplo, en un perfil de usuario de Desbordamiento de stack, es: “Actividad de la última cuenta: hace 4 horas desde 86.123.127.8” , pero la dirección IP de mi máquina es un poco diferente. ¿Cómo obtiene Stack Overflow esta dirección?

En algunos sistemas web hay una verificación de dirección IP para algunos propósitos. Por ejemplo, con una determinada dirección IP, por cada 24 horas, ¿puede el usuario tener solo 5 clics en los enlaces de descarga? Esta dirección IP debe ser única, no para un ISP que tenga una gran variedad de clientes o usuarios de Internet.

¿Entendí bien?

Como otros han dicho, no puedes hacer lo que estás preguntando. Si describes el problema que intentas resolver, ¿alguien puede ayudar? Por ejemplo, ¿estás tratando de identificar de manera única a tus usuarios? ¿Podría usar una cookie, o la ID de sesión quizás en lugar de la dirección IP?

Editar La dirección que ve en el servidor no debe ser la dirección del ISP, ya que dice que sería un rango enorme. La dirección de un usuario doméstico en banda ancha será la dirección en su enrutador, por lo que cada dispositivo dentro de la casa aparecerá en el exterior para ser el mismo, pero el enrutador usa NAT para garantizar que el tráfico se enrute a cada dispositivo correctamente. Para los usuarios que acceden desde un entorno de oficina, la dirección puede ser la misma para todos los usuarios. Los sitios que usan la dirección IP para la identificación corren el riesgo de equivocarse: los ejemplos que usted brinda son buenos y a menudo fallan. Por ejemplo, mi oficina está en el Reino Unido, el punto de ruptura (donde “parezco” estar en Internet) es en otro país donde está nuestra principal instalación de TI, por lo que desde mi oficina parece que mi dirección IP no está en el Reino Unido. Por este motivo, no puedo acceder al contenido web exclusivo del Reino Unido, como BBC iPlayer. En un momento dado, habría cientos, o incluso miles, de personas en mi empresa que parecían acceder a la web desde la misma dirección IP.

Cuando escribe el código del servidor, nunca puede estar seguro de a qué se refiere la dirección IP que ve. A algunos usuarios les gusta de esta manera. Algunas personas usan deliberadamente un proxy o VPN para confundirte aún más.

Cuando dice que la dirección de su máquina es diferente a la dirección IP que se muestra en StackOverflow, ¿cómo está averiguando la dirección de su máquina? Si solo está buscando localmente usando ipconfig o algo así, esperaría que fuera diferente por las razones que describí anteriormente. Si quieres verificar dos veces lo que el mundo exterior piensa, echa un vistazo a whatismyipaddress.com/ .

Este enlace de Wikipedia en NAT le proporcionará algunos antecedentes sobre esto.

A menudo querrás saber la dirección IP de alguien que visita tu sitio web. Si bien ASP.NET tiene varias formas de hacerlo, una de las mejores formas que hemos visto es mediante el uso de “HTTP_X_FORWARDED_FOR” de la colección ServerVariables.

Este es el por qué…

A veces, sus visitantes están detrás de un servidor proxy o un enrutador y el Request.UserHostAddress estándar solo captura la dirección IP del servidor proxy o del enrutador. Cuando este es el caso, la dirección IP del usuario se almacena en la variable del servidor (“HTTP_X_FORWARDED_FOR”).

Entonces, lo que queremos hacer es verificar primero “HTTP_X_FORWARDED_FOR” y si eso está vacío, simplemente devolvemos ServerVariables("REMOTE_ADDR") .

Si bien este método no es infalible, puede conducir a mejores resultados. A continuación se muestra el código ASP.NET en VB.NET, tomado de la publicación de blog de James Crowley “Gotcha: HTTP_X_FORWARDED_FOR devuelve varias direcciones IP”

DO#

 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 

ACTUALIZACIÓN: Gracias a Bruno Lopes. Si pueden aparecer varias direcciones IP, entonces necesita 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"]; } 

¿Qué otra cosa considera la dirección IP del usuario? Si desea la dirección IP del adaptador de red, me temo que no hay forma posible de hacerlo en una aplicación web. Si su usuario está detrás de NAT u otras cosas, tampoco puede obtener la IP.

Actualización : si bien hay sitios web que usan IP para limitar al usuario (como rapidshare), no funcionan correctamente en entornos NAT.

Creo que debería compartir mi experiencia con todos ustedes. Bueno, veo que en algunas situaciones REMOTE_ADDR NO te conseguirá lo que estás buscando. Por ejemplo, si tiene un Load Balancer detrás de la escena y está tratando de obtener la IP del Cliente, entonces tendrá problemas. Lo comprobé con mi software de enmascaramiento de IP y también verifiqué que mis colegas estaban en diferentes continentes. Así que aquí está mi solución.

Cuando quiero saber la IP de un cliente, trato de elegir todas las pruebas posibles para poder determinar si son únicas:

Aquí encontré otro servidor de seguridad que podría ayudarlos a todos si desea obtener la IP exacta del lado del cliente. entonces estoy usando: HTTP_X_CLUSTER_CLIENT_IP

HTTP_X_CLUSTER_CLIENT_IP siempre obtiene la IP exacta del cliente. En cualquier caso, si no le da el valor, debe buscar HTTP_X_FORWARDED_FOR, ya que es el segundo mejor candidato para obtener la IP del cliente y luego REMOTE_ADDR var, que puede devolverle el IP o no, pero que yo tenga todos estos tres es lo que encuentro lo mejor para controlarlos.

Espero que esto ayude a algunos muchachos.

Si es c # ver de esta manera, es muy simple

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

Puedes usar:

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

Las direcciones IP son parte de la capa de red en la “stack de siete capas”. La capa de red puede hacer lo que quiera con la dirección IP. Eso es lo que sucede con un servidor proxy, NAT, retransmisión o lo que sea.

La capa de Aplicación no debe depender de la dirección IP de ninguna manera. En particular, una Dirección IP no pretende ser un identificador de nada más que el idenfitier de un extremo de una conexión de red. Tan pronto como se cierra una conexión, debe esperar que cambie la dirección IP (del mismo usuario).

Si está utilizando CloudFlare, puede probar este Método de extensión :

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

entonces

 string IPAddress = Request.GetIPAddress(); 
 string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress; 

Lo que puede hacer es almacenar la IP del enrutador de su usuario y también la IP reenviada e intentar que sea confiable utilizando tanto las IP [Público externo como interno privado]. Pero, de nuevo, después de algunos días, el cliente puede tener asignada una nueva IP interna desde el enrutador, pero será más confiable.

Todas las respuestas hasta ahora tienen en cuenta el encabezado X-Forwarded-For no estandarizado, pero muy común. Hay un encabezado Forwarded estandarizado que es un poco más difícil de analizar. Algunos ejemplos son los siguientes:

 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 

He escrito una clase que toma estos dos encabezados en cuenta al determinar la dirección IP de un 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; } } } 

A continuación hay algunas pruebas unitarias que utilicé para validar mi solución:

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

usar en el archivo 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"]; } 

Combinando las respuestas de @Tony y @mangokun , he creado el siguiente método de extensión:

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

utilizar esta

 Dns.GetHostEntry(Dns.GetHostName()) 

Tratar:

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