asp.net - mvc - obtener ip cliente asp net c#
Obtener la dirección IP del cliente: REMOTE_ADDR, HTTP_X_FORWARDED_FOR, ¿qué más podría ser útil? (6)
Además de REMOTE_ADDR
y HTTP_X_FORWARDED_FOR
hay otros encabezados que pueden establecerse como:
-
HTTP_CLIENT_IP
-
HTTP_X_FORWARDED_FOR
puede ser una lista delimitada por comas de direcciones IP -
HTTP_X_FORWARDED
-
HTTP_X_CLUSTER_CLIENT_IP
-
HTTP_FORWARDED_FOR
-
HTTP_FORWARDED
Encontré el código en el siguiente sitio útil:
http://www.grantburton.com/?p=97
Entiendo que es una práctica estándar mirar estas dos variables. Por supuesto, pueden ser falsificados fácilmente. Tengo curiosidad de cuán a menudo puede esperar que estos valores (especialmente el HTTP_X_FORWARDED_FOR
) contengan información genuina y que no solo se codifiquen o que se eliminen sus valores.
¿Alguien con la experiencia o estadísticas sobre esto?
¿Hay algo más que pueda ser útil para la tarea de obtener la dirección IP del cliente?
Depende de la naturaleza de tu sitio.
Resulta que trabajo en un poco de software donde el seguimiento de IP es importante, y dentro de un campo consumido por sitios de parter, supongo que un 20% - 40% de las solicitudes son direcciones IP detectables o encabezados borrados, dependiendo del tiempo de día y de dónde vinieron. Para un sitio que recibe tráfico orgánico (es decir, no a través de socios) esperaría una proporción mucho más alta de buenas IP.
Como dijo Kosi, tenga cuidado con lo que está haciendo con esto: los IP de ninguna manera son una forma confiable de identificar visitantes únicos.
He transferido el código PHP de Grant Burton a un método estático de ASP.Net que se puede llamar contra HttpRequestBase. Omitirá de manera opcional a través de cualquier rango de IP privado.
public static class ClientIP
{
// based on http://www.grantburton.com/2008/11/30/fix-for-incorrect-ip-addresses-in-wordpress-comments/
public static string ClientIPFromRequest(this HttpRequestBase request, bool skipPrivate)
{
foreach (var item in s_HeaderItems)
{
var ipString = request.Headers[item.Key];
if (String.IsNullOrEmpty(ipString))
continue;
if (item.Split)
{
foreach (var ip in ipString.Split('',''))
if (ValidIP(ip, skipPrivate))
return ip;
}
else
{
if (ValidIP(ipString, skipPrivate))
return ipString;
}
}
return request.UserHostAddress;
}
private static bool ValidIP(string ip, bool skipPrivate)
{
IPAddress ipAddr;
ip = ip == null ? String.Empty : ip.Trim();
if (0 == ip.Length
|| false == IPAddress.TryParse(ip, out ipAddr)
|| (ipAddr.AddressFamily != AddressFamily.InterNetwork
&& ipAddr.AddressFamily != AddressFamily.InterNetworkV6))
return false;
if (skipPrivate && ipAddr.AddressFamily == AddressFamily.InterNetwork)
{
var addr = IpRange.AddrToUInt64(ipAddr);
foreach (var range in s_PrivateRanges)
{
if (range.Encompasses(addr))
return false;
}
}
return true;
}
/// <summary>
/// Provides a simple class that understands how to parse and
/// compare IP addresses (IPV4) ranges.
/// </summary>
private sealed class IpRange
{
private readonly UInt64 _start;
private readonly UInt64 _end;
public IpRange(string startStr, string endStr)
{
_start = ParseToUInt64(startStr);
_end = ParseToUInt64(endStr);
}
public static UInt64 AddrToUInt64(IPAddress ip)
{
var ipBytes = ip.GetAddressBytes();
UInt64 value = 0;
foreach (var abyte in ipBytes)
{
value <<= 8; // shift
value += abyte;
}
return value;
}
public static UInt64 ParseToUInt64(string ipStr)
{
var ip = IPAddress.Parse(ipStr);
return AddrToUInt64(ip);
}
public bool Encompasses(UInt64 addrValue)
{
return _start <= addrValue && addrValue <= _end;
}
public bool Encompasses(IPAddress addr)
{
var value = AddrToUInt64(addr);
return Encompasses(value);
}
};
private static readonly IpRange[] s_PrivateRanges =
new IpRange[] {
new IpRange("0.0.0.0","2.255.255.255"),
new IpRange("10.0.0.0","10.255.255.255"),
new IpRange("127.0.0.0","127.255.255.255"),
new IpRange("169.254.0.0","169.254.255.255"),
new IpRange("172.16.0.0","172.31.255.255"),
new IpRange("192.0.2.0","192.0.2.255"),
new IpRange("192.168.0.0","192.168.255.255"),
new IpRange("255.255.255.0","255.255.255.255")
};
/// <summary>
/// Describes a header item (key) and if it is expected to be
/// a comma-delimited string
/// </summary>
private sealed class HeaderItem
{
public readonly string Key;
public readonly bool Split;
public HeaderItem(string key, bool split)
{
Key = key;
Split = split;
}
}
// order is in trust/use order top to bottom
private static readonly HeaderItem[] s_HeaderItems =
new HeaderItem[] {
new HeaderItem("HTTP_CLIENT_IP",false),
new HeaderItem("HTTP_X_FORWARDED_FOR",true),
new HeaderItem("HTTP_X_FORWARDED",false),
new HeaderItem("HTTP_X_CLUSTER_CLIENT_IP",false),
new HeaderItem("HTTP_FORWARDED_FOR",false),
new HeaderItem("HTTP_FORWARDED",false),
new HeaderItem("HTTP_VIA",false),
new HeaderItem("REMOTE_ADDR",false)
};
}
IP + "User Agent" podría ser mejor para un visitante único.
No hay una respuesta real a su pregunta, pero:
En mi opinión, no es una buena práctica confiar en la dirección IP del cliente, ya que no se puede identificar a los clientes de una manera única.
Los problemas en el camino son que hay muchos escenarios donde el IP realmente no se alinea con un cliente:
- Proxy / Webfilter (destruye casi todo)
- Red de anonimizadores (ninguna posibilidad aquí tampoco)
- NAT (una IP interna no es muy útil para usted)
- ...
No puedo ofrecer ninguna estadística sobre cuántas direcciones IP son en promedio confiables, pero puedo decirle que es casi imposible decir si una dirección IP determinada es la dirección real del cliente.
Si está detrás de un proxy, debe usar X-Forwarded-For
: http://en.wikipedia.org/wiki/X-Forwarded-For
Es un borrador del IETF con amplio soporte:
El campo X-Forwarded-For es compatible con la mayoría de los servidores proxy, incluidos Squid, Apache mod_proxy, Pound, HAProxy, Varnish Cache, IronPort Web Security Appliance, AVANU WebMux, ArrayNetworks, Radware''s AppDirector y Alteon ADC, ADC-VX y ADC- VA, F5 Big-IP, Blue Coat ProxySG, Cisco Cache Engine, McAfee Web Gateway, Phion Airlock, Finjan''s Vital Security, NetApp NetCache, jetNEXUS, Crescendo Networks ''Maestro, Web Adjuster y Websense Web Security Gateway.
Si no, aquí hay un par de otros encabezados comunes que he visto: