클라이언트 IP 주소 가져 오기 : Remote_addr, http_x_forwarded_for, 다른 유용한 것은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/527638

문제

이 두 변수를 모두 보는 것이 표준 관행이라는 것을 이해합니다. 물론 그들은 쉽게 스푸핑 될 수 있습니다. 이 값을 얼마나 자주 기대할 수 있는지 궁금합니다 (특히 HTTP_X_FORWARDED_FOR) 진정한 정보를 포함하고 단지 스크램블하거나 가치를 제거하는 것이 아니라?

이 물건에 대한 경험이나 통계가있는 사람이 있습니까?

클라이언트의 IP 주소를 얻는 작업에 유용 할 수있는 다른 것이 있습니까?

도움이 되었습니까?

해결책

사이트의 특성에 따라 다릅니다.

IP 추적이 중요한 약간의 소프트웨어에서 작업하고 있으며, 파터 사이트에서 소비 한 필드 내에서 요청의 약 20% -40%가 IPS를 스푸핑하거나 헤더가 비워진 시간에 따라 비워진 헤더가 꺼져 있다고 생각합니다. 날과 그들이 어디에서 왔는지. 유기농 트래픽을받는 사이트 (즉, 파트너를 통하지 않는)의 경우, IPS의 비율이 훨씬 높을 것으로 예상됩니다.

Kosi가 말했듯이, 당신이하고있는 일을 조심하십시오 - IP는 결코 고유 한 방문자를 식별 할 수있는 신뢰할 수있는 방법이 아닙니다.

다른 팁

에 추가 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

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)
    };
}

귀하의 질문에 대한 실제 답변은 없지만 :
일반적으로 클라이언트 IP 주소에 의존하는 것은 고유 한 방식으로 클라이언트를 식별 할 수 없기 때문에 좋은 관행이 아닙니다.

도로의 문제는 IP가 실제로 클라이언트와 정렬되지 않는 많은 시나리오가 있다는 것입니다.

  • 프록시/웹 필터 (거의 모든 것을 망글)
  • 익명 제 네트워크 (여기도 기회 없음)
  • NAT (내부 IP는 귀하에게별로 유용하지 않습니다)
  • ...

IP 주소 수에 대한 통계를 제공 할 수 없습니다. 평균적으로 신뢰할 수 있지만 말할 수있는 것은 주어진 IP 주소가 실제 클라이언트 주소인지 알 수 없습니다.

IP + "사용자 에이전트"는 고유 방문자에게 더 나을 수 있습니다.

프록시 뒤에 있다면 사용해야합니다 X-Forwarded-For: http://en.wikipedia.org/wiki/x-forwarded-for

이것은 IETF 초안 표준 광범위한 지원 :

X-Forwarded-FOR 필드는 Squid, Apache Mod_proxy, Pound, Haproxy, Varnish Cache, Ironport Web Security Appliance, Avanu Webmux, Apraynetworks, Radware의 AppDirector 및 Alteon ADC, ADC-VX 및 ADC- 등 대부분의 프록시 서버에서 지원됩니다. VA, F5 BIG-IP, BLUE COAT PROXYSG, CISCO 캐시 엔진, McAfee 웹 게이트웨이, Phion Airlock, Finjan의 중요한 보안, NetApp NetCache, Jetnexus, Crescendo Networks 'Maestro, 웹 조절기 및 웹 리더 보안 게이트웨이.

그렇지 않다면 여기에 내가 본 몇 가지 다른 일반적인 헤더가 있습니다.

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();
    }

중단 점을 유지 한 후 확인하고 요구 사항에 따라 사용하십시오. 그것은 나를 위해 잘 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top