Как получить IP-адрес пользовательского клиента в ASP.NET?

У нас есть Request.UserHostAddress, чтобы получить IP-адрес в ASP.NET, но это, как правило, IP-адрес пользователя ISP, а не только IP-адрес пользователя, который, например, нажал ссылку. Как я могу получить реальный IP-адрес?

Например, в профиле пользователя Qaru это: "Последняя активность учетной записи: 4 часа назад от 86.123.127.8" , но мой IP-адрес устройства немного отличается. Как Qaru получает этот адрес?

В некоторых веб-системах для некоторых целей есть проверка IP-адреса. Например, с определенным IP-адресом на каждые 24 часа пользователь может иметь всего 5 кликов по ссылкам загрузки? Этот IP-адрес должен быть уникальным, а не для ISP, который имеет огромный диапазон клиентов или пользователей Интернета.

Я хорошо понял?

Ответ 1

Как говорили другие, вы не можете делать то, что вы просите. Если вы описываете проблему, которую пытаетесь решить, может быть, кто-то может помочь? Например. вы пытаетесь однозначно идентифицировать своих пользователей? Можете ли вы использовать файл cookie или идентификатор сеанса, а не IP-адрес?

Изменить. Адрес, который вы видите на сервере, не должен быть адресом интернет-провайдера, как вы говорите, это будет огромный диапазон. Адрес для домашнего пользователя в широкополосной сети будет адресом на своем маршрутизаторе, поэтому все устройства внутри дома будут отображаться снаружи одинаковыми, но маршрутизатор использует NAT, чтобы гарантировать, что трафик перенаправляется на каждое устройство правильно. Для пользователей, получающих доступ из офисной среды, адрес может быть одинаковым для всех пользователей. Сайты, использующие IP-адрес для идентификатора, рискуют сделать его очень неправильным - примеры, которые вы даете, хороши, и они часто терпят неудачу. Например, мой офис находится в Великобритании, точка прорыва (где я "появляюсь" в Интернете) находится в другой стране, где находится наш главный ИТ-центр, поэтому из моего офиса мой IP-адрес, похоже, не в Великобритании. По этой причине я не могу получить доступ к только веб-контенту в Великобритании, например, iPlayer BBC). В любой момент времени в моей компании будут сотни или даже тысячи людей, которые, как представляется, получают доступ к сети с одного и того же IP-адреса.

Когда вы пишете код сервера, вы никогда не можете быть уверены в том, на что ссылается IP-адрес. Некоторым пользователям это нравится. Некоторые люди намеренно используют прокси-сервер или VPN, чтобы еще больше смутить вас.

Когда вы говорите, что ваш машинный адрес отличается от IP-адреса, указанного в StackOverflow, как вы узнаете свой машинный адрес? Если вы просто смотрите локально с помощью ipconfig или что-то в этом роде, я бы ожидал, что он будет отличаться по причинам, изложенным выше. Если вы хотите проверить, что внешний мир думает, посмотрите whatismyipaddress.com/.

Эта ссылка Wikipedia на NAT предоставит вам некоторые сведения об этом.

Ответ 2

Часто вам нужно знать IP-адрес того, кто посещает ваш сайт. В то время как ASP.NET имеет несколько способов сделать это, одним из лучших способов, которые мы видели, является использование "HTTP_X_FORWARDED_FOR" коллекции ServerVariables.

Вот почему...

Иногда ваши посетители находятся за прокси-сервером или маршрутизатором, а стандартный Request.UserHostAddress только фиксирует IP-адрес прокси-сервера или маршрутизатора. В этом случае IP-адрес пользователя затем сохраняется в переменной сервера ( "HTTP_X_FORWARDED_FOR" ).

Итак, что мы хотим сделать, сначала проверьте "HTTP_X_FORWARDED_FOR" , и если это пусто, мы просто возвращаем ServerVariables("REMOTE_ADDR").

Хотя этот метод не является надежным, он может привести к лучшим результатам. Ниже приведен код ASP.NET в VB.NET, взятый из Сообщение блога Джеймса Кроули "Gotcha: HTTP_X_FORWARDED_FOR возвращает несколько IP-адресов"

С#

protected string GetIPAddress()
{
    System.Web.HttpContext context = System.Web.HttpContext.Current; 
    string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

    if (!string.IsNullOrEmpty(ipAddress))
    {
        string[] addresses = ipAddress.Split(',');
        if (addresses.Length != 0)
        {
            return addresses[0];
        }
    }

    return context.Request.ServerVariables["REMOTE_ADDR"];
}

VB.NET

Public Shared Function GetIPAddress() As String
    Dim context As System.Web.HttpContext = System.Web.HttpContext.Current
    Dim sIPAddress As String = context.Request.ServerVariables("HTTP_X_FORWARDED_FOR")
    If String.IsNullOrEmpty(sIPAddress) Then
        Return context.Request.ServerVariables("REMOTE_ADDR")
    Else
        Dim ipArray As String() = sIPAddress.Split(New [Char]() {","c})
        Return ipArray(0)
    End If
End Function

Ответ 3

UPDATE: Благодаря Бруно Лопесу. Если может возникнуть несколько IP-адресов, необходимо использовать этот метод:

    private string GetUserIP()
    {
        string ipList = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

        if (!string.IsNullOrEmpty(ipList))
        {
            return ipList.Split(',')[0];
        }

        return Request.ServerVariables["REMOTE_ADDR"];
    }

Ответ 4

Что еще вы считаете IP-адресом пользователя? Если вам нужен IP-адрес сетевого адаптера, я боюсь, что нет возможности сделать это в веб-приложении. Если ваш пользователь находится за NAT или другими вещами, вы также не можете получить IP.

Обновить. Хотя веб-сайты, использующие IP-адрес для ограничения пользователя (например, rapidshare), не работают корректно в средах NAT.

Ответ 5

Думаю, я должен поделиться своим опытом со всеми вами. Я вижу, что в некоторых ситуациях REMOTE_ADDR НЕ доставит вам то, что вы ищете. Например, если у вас есть балансировщик нагрузки за сценой, и если вы пытаетесь получить клиентский IP-адрес, у вас будут проблемы. Я проверил его с помощью своего программного обеспечения для маскировки IP-адресов, а также проверил, что мои коллеги находятся на разных континентах. Итак, вот мое решение.

Когда я хочу узнать IP-адрес клиента, я пытаюсь выбрать все возможные доказательства, чтобы определить, являются ли они уникальными:

Здесь я нашел еще один ключ-var, который мог бы помочь вам всем, если вы хотите получить точный IP-адрес на стороне клиента. поэтому я использую: HTTP_X_CLUSTER_CLIENT_IP

HTTP_X_CLUSTER_CLIENT_IP всегда получает точный IP-адрес клиента. В любом случае, если он не дает вам значения, вы должны искать HTTP_X_FORWARDED_FOR, поскольку он является вторым лучшим кандидатом для получения вашего IP-адреса клиента, а затем REMOTE_ADDR var, который может или не может вернуть вам IP-адрес, но для меня все эти три - это то, что я нахожу лучше всего для их наблюдения.

Надеюсь, это поможет некоторым парням.

Ответ 6

Если С# см. этот способ, очень просто

string clientIp = (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? 
                   Request.ServerVariables["REMOTE_ADDR"]).Split(',')[0].Trim();

Ответ 7

Вы можете использовать:

System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList.GetValue(0).ToString();

Ответ 8

IP-адреса являются частью сетевого уровня в "семислойном стеке". Сетевой уровень может делать все, что он хочет сделать с IP-адресом. То, что происходит с прокси-сервером, NAT, реле и т.д.

Уровень приложения не должен зависеть от IP-адреса. В частности, IP-адрес не должен быть идентификатором чего-либо иного, кроме idenfitier одного конца сетевого соединения. Как только соединение будет закрыто, вы должны ожидать, что IP-адрес (того же пользователя) изменится.

Ответ 9

Если вы используете CloudFlare, вы можете попробовать этот метод расширения:

public static class IPhelper
{
    public static string GetIPAddress(this HttpRequest Request)
    {
        if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();

        if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) return Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();

        return Request.UserHostAddress;
    }
}

затем

string IPAddress = Request.GetIPAddress();

Ответ 10

string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;

Ответ 11

Что вы можете сделать, это сохранить IP-адрес маршрутизатора вашего пользователя, а также перенаправленный IP-адрес и попытаться сделать его надежным, используя оба IP-адреса [External Public и Internal Private]. Но через несколько дней клиенту может быть назначен новый внутренний IP-адрес от маршрутизатора, но он будет более надежным.

Ответ 12

Все ответы до сих пор учитывают нестандартизированный, но очень распространенный заголовок X-Forwarded-For. Существует стандартизированный заголовок Forwarded который немного сложнее разобрать. Вот некоторые примеры:

Forwarded: for="_gazonk"
Forwarded: For="[2001:db8:cafe::17]:4711"
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for=198.51.100.17

Я написал класс, который учитывает оба этих заголовка при определении IP-адреса клиента.

using System;
using System.Web;

namespace Util
{
    public static class IP
    {
        public static string GetIPAddress()
        {
            return GetIPAddress(new HttpRequestWrapper(HttpContext.Current.Request));
        }

        internal static string GetIPAddress(HttpRequestBase request)
        {
            // handle standardized 'Forwarded' header
            string forwarded = request.Headers["Forwarded"];
            if (!String.IsNullOrEmpty(forwarded))
            {
                foreach (string segment in forwarded.Split(',')[0].Split(';'))
                {
                    string[] pair = segment.Trim().Split('=');
                    if (pair.Length == 2 && pair[0].Equals("for", StringComparison.OrdinalIgnoreCase))
                    {
                        string ip = pair[1].Trim('"');

                        // IPv6 addresses are always enclosed in square brackets
                        int left = ip.IndexOf('['), right = ip.IndexOf(']');
                        if (left == 0 && right > 0)
                        {
                            return ip.Substring(1, right - 1);
                        }

                        // strip port of IPv4 addresses
                        int colon = ip.IndexOf(':');
                        if (colon != -1)
                        {
                            return ip.Substring(0, colon);
                        }

                        // this will return IPv4, "unknown", and obfuscated addresses
                        return ip;
                    }
                }
            }

            // handle non-standardized 'X-Forwarded-For' header
            string xForwardedFor = request.Headers["X-Forwarded-For"];
            if (!String.IsNullOrEmpty(xForwardedFor))
            {
                return xForwardedFor.Split(',')[0];
            }

            return request.UserHostAddress;
        }
    }
}

Ниже приведены некоторые модульные тесты, которые я использовал для проверки своего решения:

using System.Collections.Specialized;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UtilTests
{
    [TestClass]
    public class IPTests
    {
        [TestMethod]
        public void TestForwardedObfuscated()
        {
            var request = new HttpRequestMock("for=\"_gazonk\"");
            Assert.AreEqual("_gazonk", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv6()
        {
            var request = new HttpRequestMock("For=\"[2001:db8:cafe::17]:4711\"");
            Assert.AreEqual("2001:db8:cafe::17", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv4()
        {
            var request = new HttpRequestMock("for=192.0.2.60;proto=http;by=203.0.113.43");
            Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv4WithPort()
        {
            var request = new HttpRequestMock("for=192.0.2.60:443;proto=http;by=203.0.113.43");
            Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedMultiple()
        {
            var request = new HttpRequestMock("for=192.0.2.43, for=198.51.100.17");
            Assert.AreEqual("192.0.2.43", Util.IP.GetIPAddress(request));
        }
    }

    public class HttpRequestMock : HttpRequestBase
    {
        private NameValueCollection headers = new NameValueCollection();

        public HttpRequestMock(string forwarded)
        {
            headers["Forwarded"] = forwarded;
        }

        public override NameValueCollection Headers
        {
            get { return this.headers; }
        }
    }
}

Ответ 13

использовать в файле ashx

public string getIP(HttpContext c)
{
    string ips = c.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
    if (!string.IsNullOrEmpty(ips))
    {
        return ips.Split(',')[0];
    }
    return c.Request.ServerVariables["REMOTE_ADDR"];
}

Ответ 14

Комбинируя ответы @Tony и @mangokun, я создал следующий метод расширения:

public static class RequestExtensions
{
    public static string GetIPAddress(this HttpRequest Request)
    {
        if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();

        if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
        {
            string ipAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

            if (!string.IsNullOrEmpty(ipAddress))
            {
                string[] addresses = ipAddress.Split(',');
                if (addresses.Length != 0)
                {
                    return addresses[0];
                }
            }
        }

        return Request.UserHostAddress;
    }
}

Ответ 15

используйте этот

Dns.GetHostEntry(Dns.GetHostName())

Ответ 16

Пытаться:

using System.Net;

public static string GetIpAddress()  // Get IP Address
{
    string ip = "";     
    IPHostEntry ipEntry = Dns.GetHostEntry(GetCompCode());
    IPAddress[] addr = ipEntry.AddressList;
    ip = addr[2].ToString();
    return ip;
}
public static string GetCompCode()  // Get Computer Name
{   
    string strHostName = "";
    strHostName = Dns.GetHostName();
    return strHostName;
}