Obtendo o endereço IP do cliente: REMOTE_ADDR, HTTP_X_FORWARDED_FOR, o que mais poderia ser útil?
-
22-08-2019 - |
Pergunta
Eu entendo que é uma prática padrão de olhar para estas duas variáveis. Claro que eles podem ser facilmente falsificado. Estou curioso para saber quantas vezes você pode esperar que esses valores (especialmente o HTTP_X_FORWARDED_FOR
) para conter informação verdadeira e não apenas ser mexidos ou têm seus valores arrancada?
Qualquer pessoa com a experiência ou estatísticas sobre isso?
É mais lá qualquer coisa que possa ser útil para a tarefa de obter o endereço IP do cliente?
Solução
Depende da natureza do seu site.
Acontece que eu trabalho em um pouco de software em que o rastreamento IP é importante, e dentro de um campo consumido por sites parter eu acho que cerca de 20% - 40% dos pedidos são tanto IPs ou cabeçalhos detectável falsificados apagado, dependendo a hora do dia e de onde vieram. Para um site que recebe tráfego orgânico (ou seja, não através de parceiros) eu esperaria uma proporção muito maior de bons IPs.
Como Kosi disse, cuidado com o que você está fazendo com isso -. IPs são de modo algum uma forma confiável para identificar visitantes únicos
Outras dicas
Além de REMOTE_ADDR
e HTTP_X_FORWARDED_FOR
existem alguns outros cabeçalhos que podem ser definidas como:
-
HTTP_CLIENT_IP
-
HTTP_X_FORWARDED_FOR
pode ser lista delimitada por vírgula de IPs -
HTTP_X_FORWARDED
-
HTTP_X_CLUSTER_CLIENT_IP
-
HTTP_FORWARDED_FOR
-
HTTP_FORWARDED
Eu encontrei o código no local a seguinte útil:
http://www.grantburton.com/?p=97
Eu tenho portado código PHP de Grant Burton a um exigível método estático ASP.Net contra o HttpRequestBase. Vai opcionalmente pular através de quaisquer faixas 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)
};
}
Sem verdadeira resposta para sua pergunta, mas:
Geralmente contando com os clientes endereço IP é na minha opinião não é uma boa prática, uma vez que não é utilizável para identificar clientes de uma forma única.
Problemas na estrada são de que há muito cenários lote onde o IP realmente não se alinham a um cliente:
- Proxy / Webfilter (mangle quase tudo)
- rede Anonymizer (nenhuma chance aqui também)
- NAT (um IP interno não é muito útil para você)
- ...
Eu não posso oferecer quaisquer estatísticas sobre quantos endereços IP são , em média, confiável, mas o que eu posso te dizer que é quase impossível dizer se um determinado endereço IP é o endereço de clientes real.
IP + "User Agent" podia ser melhor para o visitante único.
Se você estiver atrás de um proxy, você deve usar X-Forwarded-For
: http: // en .wikipedia.org / wiki / X-Forwarded-For
É um IETF projecto padrão com amplo apoio:
O X-Forwarded-For campo é suportado pela maioria dos servidores proxy, Incluindo Squid, Apache mod_proxy, Pound, HAProxy, cache do Varnish, IronPort Web Security Appliance, AVANU WebMux, ArrayNetworks, AppDirector da Radware e Alteon ADC, ADC-VX, e ADC-VA, F5 Big-IP, Blue Coat ProxySG, Motor de cache Cisco, McAfee Web Gateway, Phion Airlock, Vital Segurança da Finjan, NetApp NetCache, jetNEXUS, Crescendo Maestro Networks, Web Ajustador e Websense Web Security Gateway.
Se não, aqui estão algumas outras cabeçalhos comuns que eu vi:
Chamada a seguir método de ação do seu arquivo JS (Para obter o endereço IP IPv4).
[HttpGet]
public string GetIP()
{
IPAddress[] ipv4Addresses = Array.FindAll(
Dns.GetHostEntry(string.Empty).AddressList,
a => a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
return ipv4Addresses.ToString();
}
Verifique após manter Breakpoint, e uso como por sua exigência. Sua multa trabalhando para mim.