クライアントの IP アドレスを取得します。REMOTE_ADDR、HTTP_X_FORWARDED_FOR、他に役立つものは何でしょうか?
-
22-08-2019 - |
質問
これら両方の変数を確認するのが標準的な方法であることは理解しています。もちろん、簡単になりすますことができます。どのくらいの頻度でこれらの値が期待できるのか興味があります (特に、 HTTP_X_FORWARDED_FOR
)単にスクランブルされたり、価値が剥奪されたりするのではなく、本物の情報を含めるためですか?
この件に関する経験や統計を持っている人はいますか?
クライアントの IP アドレスを取得するタスクに役立つものは他にありますか?
解決
それはあなたのサイトの性質によって異なります。
私は、IPトラッキングが重要であるソフトウェアのビットで動作するように起こる、と区分けサイトで消費されるフィールド内で私はいくつかの20%を推測したい - 要求の40%がいずれかの検出可能に偽装されているIPアドレスやヘッダがに応じて、打ち抜か一日の時間、どこから来たの。 (すなわちないパートナーを通じて)オーガニック検索のトラフィックを取得するサイトのために私は良いIPアドレスのはるかに高い割合を期待したい。
コシが言ったように、あなたはこれでやっていることに注意してください - 。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
私はHttpRequestBaseに対する呼び出し可能なASP.Net静的メソッドに移植されたグラント・バートンのPHPコードをしました。それは、必要に応じて任意のプライベート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 がクライアントと実際には一致しないシナリオが非常に多いことです。
- プロキシ/Webフィルター (ほぼすべてをマングル)
- アノニマイザーネットワーク (ここでもチャンスはありません)
- NAT (内部 IP はあまり役に立ちません)
- ...
IP アドレスの数に関する統計は提供できません。 平均して 信頼性は高いですが、私が言えることは、特定の IP アドレスが実際のクライアントのアドレスであるかどうかを見分けることはほとんど不可能です。
IP + "ユーザーエージェントは" ユニーク訪問者のためのより良いかもしれない。
プロキシの背後にいる場合は、次を使用する必要があります X-Forwarded-For
: http://en.wikipedia.org/wiki/X-Forwarded-For
それは IETF規格草案 幅広い支持を得て:
X-Forward-forフィールドは、Squid、Apache Mod_Proxy、Pound、Haproxy、Varnish Cache、Ironport Web Securityアプライアンス、Avanu WebMux、ArrayNetworks、RadwareのAppdirector and Alteon ADC、ADC-VX、ADC-など、ほとんどのプロキシサーバーでサポートされています。 VA、F5 Big-IP、Blue Coat ProxySG、Cisco Cache Engine、McAfee Web Gateway、Phion Airlock、Finjan's Vital Security、NetApp Netcache、JetNexus、Crescendo Networks 'Maestro、Web Adjuster、Websense Webセキュリティゲートウェイ。
そうでない場合は、私が見た他の一般的なヘッダーをいくつか示します。
(IPv4のIPアドレスを取得するには)あなたのJSファイルからアクションメソッドの下に呼び出します。
[HttpGet]
public string GetIP()
{
IPAddress[] ipv4Addresses = Array.FindAll(
Dns.GetHostEntry(string.Empty).AddressList,
a => a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
return ipv4Addresses.ToString();
}
ブレークポイントを保持した後チェックして、あなたの要件ごとに使用しています。 その私のために正常に動作します。