web-dev-qa-db-fra.com

Obtenir l'adresse IP du client: REMOTE_ADDR, HTTP_X_FORWARDED_FOR, quoi d'autre pourrait être utile?

Je comprends que l’examen de ces deux variables est une pratique courante. Bien sûr, ils peuvent facilement être usurpés. Je suis curieux de savoir combien de fois pouvez-vous vous attendre à ces valeurs (en particulier le HTTP_X_FORWARDED_FOR) contenir des informations authentiques et ne pas se contenter d’être brouillés ou de voir leurs valeurs dépouillées?

Quelqu'un avec l'expérience ou des statistiques sur ce genre de choses?

Y a-t-il autre chose qui puisse être utile pour obtenir l'adresse IP du client?

58
User

Cela dépend de la nature de votre site.

Je travaille sur un peu de logiciel où le suivi IP est important, et dans un domaine consommé par des sites de parter, je suppose que 20% à 40% des demandes sont des IP falsifiées de manière détectable ou des en-têtes masqués, selon le moment de jour et d'où ils venaient. Pour un site qui génère du trafic organique (c'est-à-dire sans passer par des partenaires), je m'attendrais à un ratio beaucoup plus élevé de bonnes adresses IP.

Comme Kosi l'a dit, faites attention à ce que vous faites avec ceci - les adresses IP ne constituent en aucun cas un moyen fiable d'identifier des visiteurs uniques.

29
annakata

En plus de REMOTE_ADDR et HTTP_X_FORWARDED_FOR il existe d’autres en-têtes pouvant être définis, tels que:

  • HTTP_CLIENT_IP
  • HTTP_X_FORWARDED_FOR peut être une liste d'adresses IP séparées par des virgules
  • HTTP_X_FORWARDED
  • HTTP_X_CLUSTER_CLIENT_IP
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED

J'ai trouvé le code sur le site suivant utile:
http://www.grantburton.com/?p=97

61
ejunker

J'ai porté le code de Grant Burton PHP) sur une méthode statique ASP.Net appelable sur HttpRequestBase. Elle ignorera éventuellement les plages d'adresses IP privées.

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

Pas de vraie réponse à votre question mais:
De manière générale, s’appuyer sur l’adresse IP du client n’est, à mon avis, pas une bonne pratique, car il n’est pas utilisable d’identifier les clients de manière unique.

Les problèmes sur la route sont qu’il existe de nombreux scénarios dans lesquels l’adresse IP ne s’aligne pas vraiment sur un client:

  • Proxy/Webfilter (presque tout)
  • Réseau Anonymizer (aucune chance ici non plus)
  • NAT (une adresse IP interne ne vous est pas très utile)
  • ...

Je ne peux offrir aucune statistique sur le nombre d'adresses IP en moyenne fiables, mais ce que je peux vous dire, c'est qu'il est presque impossible de dire si une adresse IP donnée est l'adresse réelle du client.

7
Kosi2801

IP + "User Agent" pourrait être meilleur pour un visiteur unique.

2
Mahesh

Si vous êtes derrière un proxy, vous devriez utiliser X-Forwarded-For: http://en.wikipedia.org/wiki/X-Forwarded-For

C'est un projet de norme IETF avec un large support:

Le champ X-Forwarded-For est pris en charge par la plupart des serveurs proxy, notamment Squid, Apache mod_proxy, Pound, HAProxy, cache Varnish, Appliance de sécurité Web IronPort, AVANU WebMux, ArrayNetworks, AppDirector et Alteon ADC de Radware, ADC-VX et ADC. VA, F5 Big-IP, Blue Coat ProxySG, moteur de cache Cisco, passerelle McAfee Web Gateway, Phion Airlock, sécurité essentielle de Finjan, NetApp NetCache, jetNEXUS, Maestro, ajusteur Web et passerelle Websense Web Security de Crescendo Networks.

Sinon, voici quelques autres en-têtes communs que j'ai vus:

1
lmsurprenant

Appelez la méthode d'action ci-dessous à partir de votre fichier JS (pour obtenir l'adresse IP ipv4).

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

Vérifiez après avoir gardé le point d'arrêt et utilisez-le selon vos besoins. Cela fonctionne bien pour moi.

0
TauFeeQ