63

I understand it's a standard practice to look at both these variables. Of course they can easily be spoofed. I'm curious how often can you expect these values (especially the HTTP_X_FORWARDED_FOR) to contain genuine information and not just be scrambled or have their values stripped away?

Anyone with the experience or statistics on this stuff?

Is there anything else that can be useful for the task of getting the client's IP address?

4

7 に答える 7

64

に加えてREMOTE_ADDRHTTP_X_FORWARDED_FOR次のような設定可能なヘッダーが他にもいくつかあります。

  • HTTP_CLIENT_IP
  • HTTP_X_FORWARDED_FORIP のカンマ区切りのリストにすることができます
  • HTTP_X_FORWARDED
  • HTTP_X_CLUSTER_CLIENT_IP
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED

次のサイトのコードが役に立ちました:
http://www.grantburton.com/?p=97

于 2009-05-27T14:47:55.050 に答える
31

サイトの性質によって異なります。

私はたまたま IP 追跡が重要なちょっとしたソフトウェアに取り組んでおり、パートナー サイトによって消費されるフィールド内で、リクエストの約 20% から 40% が検出可能なスプーフィングされた IP であるか、ヘッダーが空白になっていると推測します。日と彼らがどこから来たのか。オーガニック トラフィックを取得する (つまり、パートナー経由ではない) サイトの場合、適切な IP の割合がはるかに高くなると予想されます。

Kosi が言ったように、これを行う際には注意が必要です。IP は、ユニークな訪問者を特定するための信頼できる方法ではありません。

于 2009-02-09T10:41:38.830 に答える
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)
    };
}
于 2012-03-27T04:38:33.523 に答える
7

あなたの質問に対する本当の答えはありませんが、
一般的にクライアントのIPアドレスに依存することは、クライアントを一意の方法で識別するのに使用できないため、私の意見では良い方法ではありません.

進行中の問題は、IP が実際にはクライアントに一致しないシナリオが非常に多いことです。

  • Proxy/Webfilter (ほぼすべてをマングル)
  • Anonymizer ネットワーク (ここでもチャンスはありません)
  • NAT (内部 IP はあまり役に立ちません)
  • ...

平均的に信頼できるIP アドレスの数に関する統計を提供することはできませんが、特定の IP アドレスが実際のクライアント アドレスであるかどうかを判断することはほとんど不可能であると言えます。

于 2009-02-09T10:28:04.137 に答える
2

IP +「ユーザーエージェント」は、ユニークな訪問者にとってより良いかもしれません。

于 2009-02-09T12:02:05.033 に答える
1

プロキシの背後にいる場合は、次を使用する必要がありますX-Forwarded-For: http://en.wikipedia.org/wiki/X-Forwarded-For

これは、幅広いサポートを備えたIETF ドラフト標準です。

X-Forwarded-For フィールドは、Squid、Apache mod_proxy、Pound、HAProxy、Varnish キャッシュ、IronPort Web セキュリティ アプライアンス、AVANU WebMux、ArrayNetworks、Radware の AppDirector および Alteon ADC、ADC-VX、および ADC- を含むほとんどのプロキシ サーバーでサポートされています。 VA、F5 Big-IP、Blue Coat ProxySG、Cisco Cache Engine、McAfee Web Gateway、Phion Airlock、Finjan の Vital Security、NetApp NetCache、jetNEXUS、Crescendo Networks の Maestro、Web Adjuster、および Websense Web Security Gateway。

そうでない場合は、私が見た他のいくつかの一般的なヘッダーを次に示します。

  • X クライアント IP ( Apache )
  • X-Real-IP ( Nginx )
于 2014-04-01T19:26:11.640 に答える