我理解查看这两个变量是一种标准做法。当然,他们很容易被欺骗。我很好奇你多久会期望这些值(特别是HTTP_X_FORWARDED_FOR
)包含真实的信息而不仅仅是被扰乱或者它们的价值被剥夺了?
有这方面经验或统计数据的人吗?
还有什么对获取客户端IP地址的任务有用吗?
答案 0 :(得分:60)
除了REMOTE_ADDR
和HTTP_X_FORWARDED_FOR
之外,还有一些其他标题可以设置,例如:
HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR
可以是逗号分隔的IP列表HTTP_X_FORWARDED
HTTP_X_CLUSTER_CLIENT_IP
HTTP_FORWARDED_FOR
HTTP_FORWARDED
我发现以下网站上的代码很有用:
http://www.grantburton.com/?p=97
答案 1 :(得分:28)
这取决于您网站的性质。
我碰巧在一些IP跟踪很重要的软件上工作,并且在分区网站消耗的字段中,我猜大概有20% - 40%的请求是可检测到的欺骗性IP或标头消隐,具体取决于一天中的时间和他们来自哪里。对于获得有机流量的网站(即不通过合作伙伴),我期望良好IP的比例要高得多。
正如Kosi所说,小心你正在做的事情 - 知识产权绝不是识别独特访客的可靠方式。
答案 2 :(得分:10)
我已经将Grant Burton的PHP代码移植到可以针对HttpRequestBase调用的ASP.Net静态方法中。它可以选择跳过任何私有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)
};
}
答案 3 :(得分:7)
对你的问题没有真正的答案但是:
一般来说,依赖客户端的IP地址并不是一个好的做法,因为它无法以独特的方式识别客户。
道路上存在的问题是,在很多情况下,IP并没有真正与客户保持一致:
我无法提供有关平均平均的IP地址数量的任何统计信息,但我可以告诉您,几乎不可能判断给定的IP地址是否是真实的客户端地址。
答案 4 :(得分:2)
IP +“用户代理”对于唯一身份访问者来说可能更好。
答案 5 :(得分:1)
如果您在代理服务器后面,则应使用X-Forwarded-For
:http://en.wikipedia.org/wiki/X-Forwarded-For
这是IETF draft standard广泛的支持:
大多数代理服务器都支持X-Forwarded-For字段, 包括Squid,Apache mod_proxy,Pound,HAProxy,Varnish缓存, IronPort网络安全设备,AVANU WebMux,ArrayNetworks, Radware的AppDirector和Alteon ADC,ADC-VX和ADC-VA,F5 Big-IP, Blue Coat ProxySG,思科缓存引擎,McAfee Web Gateway,Phion Airlock,Finjan的Vital Security,NetApp NetCache,jetNEXUS,Crescendo Networks的Maestro,Web Adjuster和Websense Web Security Gateway。
如果没有,这里有几个我见过的常见标题:
答案 6 :(得分:0)
从JS文件中调用“以下操作方法”(以获取ipv4 ip地址)。
[HttpGet]
public string GetIP()
{
IPAddress[] ipv4Addresses = Array.FindAll(
Dns.GetHostEntry(string.Empty).AddressList,
a => a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
return ipv4Addresses.ToString();
}
在保留断点后检查,并根据需要使用。 对我来说很好。