Получение IP-адреса клиента: REMOTE ADDR, HTTP X FORWARDED FOR, что еще может быть полезно?
Я понимаю, что это стандартная практика, чтобы взглянуть на обе эти переменные. Конечно, их можно легко обмануть. Мне любопытно, как часто вы можете ожидать эти значения (особенно HTTP_X_FORWARDED_FOR
) содержать подлинную информацию, а не просто скремблировать или лишить их ценностей?
кто-нибудь с опытом или статистикой по этому вопросу?
что-нибудь еще, что может быть полезно для задачи получения IP-адреса клиента?
6 ответов:
Это зависит от характера вашего сайта.
Я работаю над небольшим количеством программного обеспечения, где важно отслеживание IP - адресов, и в поле, потребляемом сайтами parter, я бы предположил, что некоторые 20% - 40% запросов либо обнаруживаются поддельными IP-адресами, либо заголовками, заглушенными, в зависимости от времени суток и откуда они пришли. Для сайта, который получает органический трафик (т. е. не через партнеров), я бы ожидал гораздо более высокого соотношения хороших IP-адресов.
Как вы сказали, Будьте осторожны, что вы при этом IP-адреса никоим образом не являются надежным способом идентификации уникальных посетителей.
кроме
REMOTE_ADDR
иHTTP_X_FORWARDED_FOR
есть некоторые другие заголовки, которые могут быть установлены, такие как:
HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR
может быть разделен запятыми список IPsHTTP_X_FORWARDED
HTTP_X_CLUSTER_CLIENT_IP
HTTP_FORWARDED_FOR
HTTP_FORWARDED
я нашел код на следующем сайте полезным:
http://www.grantburton.com/?p=97
я портировал PHP-код Гранта Бертона на an ASP.Net статический метод, вызываемый против HttpRequestBase. Он будет дополнительно пропускать через любые частные диапазоны IP.
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-адрес клиентов, на мой взгляд, не является хорошей практикой, поскольку он не может использоваться для идентификации клиентов уникальным образом.проблемы на дороге заключаются в том, что существует довольно много сценариев, в которых IP-адрес не соответствует клиенту:
- Прокси / Webfilter (калечить почти все)
- сеть анонимайзеров (здесь тоже нет шансов)
- NAT (внутренний IP не является очень полезно для вас)
- ...
Я не могу предложить никакой статистики о том, сколько IP-адресов в среднем надежный, но что я могу сказать вам, что это почти невозможно сказать, если данный IP-адрес является реальным адресом клиентов.
Если вы находитесь за прокси, вы должны использовать
X-Forwarded-For
: http://en.wikipedia.org/wiki/X-Forwarded-ForЭто проект стандарта IETF С широкой поддержкой:
поле X-Forwarded-For поддерживается большинством прокси-серверов, в том числе Squid, Apache mod_proxy, Pound, HAProxy, лак кэш, IronPort Web Security Appliance, AVANU WebMux, ArrayNetworks, AppDirector от Radware Alteon и АЦП, АЦП-ЧХ, и АЦП-ва клавишу F5 большой IP, Синий Пальто ProxySG, Cisco Cache Engine, McAfee Web Gateway, Phion Шлюз, жизненно важная безопасность Финджана, NetApp NetCache, jetNEXUS, Crescendo Networks ' Maestro, Web Adjuster и Websense Web Security Gateway.
если нет, вот несколько других общих заголовков, которые я видел: