代码之家  ›  专栏  ›  技术社区  ›  User

获取客户端IP地址:REMOTE\u ADDR、HTTP\u X\u FORWARDED\u,还有什么有用的?

  •  56
  • User  · 技术社区  · 17 年前

    HTTP_X_FORWARDED_FOR )包含真实的信息,而不仅仅是被打乱或剥夺他们的价值观?

    6 回复  |  直到 8 年前
        1
  •  63
  •   Jeff Atwood    16 年前

    除了 REMOTE_ADDR HTTP_X_FORWARDED_FOR 可以设置其他一些标题,例如:

    • HTTP_CLIENT_IP
    • HTTP\u X\u转发\u用于 可以是以逗号分隔的IP列表
    • HTTP_X_FORWARDED
    • HTTP_X_CLUSTER_CLIENT_IP
    • HTTP_FORWARDED_FOR
    • HTTP_FORWARDED

    我发现以下站点上的代码很有用:
    http://www.grantburton.com/?p=97

        2
  •  30
  •   annakata    17 年前

    这取决于网站的性质。

    我碰巧在一个IP跟踪很重要的软件上工作,在合作伙伴网站使用的领域内,我猜大约20%-40%的请求要么是可检测到的欺骗IP,要么是被屏蔽的头,这取决于一天中的时间和它们来自何处。对于一个获得有机流量(即不是通过合作伙伴)的网站,我希望获得更高比例的好IP。

    正如Kosi所说的,小心你在用它做什么——IPs绝对不是识别独特访客的可靠方法。

        3
  •  10
  •   Kevin Doyon Zephaniah Grunschlag    10 年前

    我已经将Grant Burton的PHP代码移植到一个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)
        };
    }
    
        4
  •  7
  •   Kosi2801    17 年前


    在我看来,通常依赖客户的IP地址不是一个好的做法,因为它无法以独特的方式识别客户。

    道路上的问题是,在很多情况下,IP并不真正与客户端对齐:

    • 代理/Webfilter(几乎破坏所有内容)
    • ...

    我不能提供任何关于有多少IP地址的统计数据 平均而言 可靠但我可以告诉你的是,几乎不可能判断给定的IP地址是否是真正的客户端地址。

        5
  •  2
  •   Mahesh    17 年前

        6
  •  1
  •   Community Mohan Dere    4 年前

    如果你支持代理,你应该使用 X-Forwarded-For : http://en.wikipedia.org/wiki/X-Forwarded-For

    IETF draft standard

    IronPort Web安全设备、AVANU WebMux、ArrayNetworks、, Radware的AppDirector和Alteon ADC、ADC-VX和ADC-VA、F5大IP、, 气闸、Finjan的重要安全、NetApp NetCache、jetNEXUS、Crescendo Networks的Maestro、Web调节器和Websense Web安全网关。

        7
  •  0
  •   TauFeeQ    7 年前

        [HttpGet]
        public string GetIP()
        {
            IPAddress[] ipv4Addresses = Array.FindAll(
                Dns.GetHostEntry(string.Empty).AddressList,
                a => a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
            return ipv4Addresses.ToString();
        }
    

    保留断点后检查,并根据需要使用。 这对我来说很好。

    推荐文章