it-swarm-ko.tech

ASP.NET에서 사용자의 클라이언트 IP 주소를 얻는 방법은 무엇입니까?

우리는 ASP.NET에서 IP 주소를 가져 오기 위해 Request.UserHostAddress를 가지고 있지만 일반적으로이 주소는 예를 들어 링크를 클릭 한 사용자의 컴퓨터 IP 주소가 아니라 사용자의 ISP의 IP 주소입니다. 어떻게하면 실제 IP 주소를 얻을 수 있습니까?

예를 들어, Stack Overflow 사용자 프로파일에서 다음과 같습니다. "Last account activity : 4 hours ago from 86.123.127.8"하지만 컴퓨터의 IP 주소가 약간 다릅니다. 스택 오버플로는 어떻게이 주소를 얻습니까?

일부 웹 시스템에는 일부 용도로 IP 주소 확인 기능이 있습니다. 예를 들어 특정 IP 주소로 24 시간마다 다운로드 링크를 5 번만 클릭 할 수 있습니까? 이 IP 주소는 고유해야하며 광대 한 범위의 클라이언트 또는 인터넷 사용자가있는 ISP가 아닙니다.

나는 잘 이해 했는가?

358
Mehdi

다른 사람들이 당신이 요구하는 것을 할 수 없다고 말했기 때문에. 어쩌면 누군가가 도울 수있는 문제를 설명하면 어떨까요? 예 : 사용자를 고유하게 식별하려고합니까? IP 주소 대신 쿠키 또는 세션 ID를 사용할 수 있습니까?

편집 서버에 표시되는 주소는 ISP의 주소가 아니어야합니다. 광대역에있는 가정 사용자의 주소는 라우터에있는 주소 일 것이므로 집 안의 모든 장치는 외부에 동일하게 나타나지만 라우터는 NAT를 사용하여 트래픽이 각 장치로 라우팅되도록합니다 바르게. 사무실 환경에서 액세스하는 사용자의 경우 모든 사용자가 동일한 주소를 사용할 수 있습니다. ID에 대한 IP 주소를 사용하는 사이트는 매우 잘못 될 위험이 있습니다. 예를 들어주는 것이 좋으며 종종 실패합니다. 예를 들어 나의 사무실은 영국에 있고, 탈출구 (인터넷에있는 것처럼 보이는 곳)는 주요 IT 시설이있는 다른 나라에 있으므로 내 사무실에서 내 IP 주소가 영국에없는 것 같습니다. 이런 이유로 영국 BBC iPlayer와 같은 웹 콘텐츠에만 액세스 할 수 없습니다. 주어진 시간에 동일한 IP 주소에서 웹에 액세스하는 것으로 보이는 내 회사 직원이 수백 명 또는 수천 명이됩니다.

서버 코드를 작성할 때 사용자가 보는 IP 주소가 무엇인지를 알 수 없습니다. 일부 사용자는이 방법을 좋아합니다. 어떤 사람들은 의도적으로 당신을 혼란에 빠뜨리기 위해 프록시 나 VPN을 사용합니다.

컴퓨터 주소가 StackOverflow에 표시된 IP 주소와 다르다면 컴퓨터 주소를 찾는 방법은 무엇입니까? ipconfig 또는 이와 유사한 것을 사용하여 로컬에서 찾고 있다면 위의 설명과 다른 이유가있을 것입니다. 외부 세계가 생각하는 것을 두 번 확인하려면 whatismyipaddress.com/ )를보십시오.

NAT에 대한 위키 피 디아 링크 는 여기에 대한 배경 지식을 제공 할 것입니다.

133
Steve Haigh

종종 귀하의 웹 사이트를 방문하는 사람의 IP 주소를 알고 싶을 것입니다. ASP.NET은이 작업을 수행하는 여러 가지 방법이 있지만 ServerVariables 컬렉션의 "HTTP_X_FORWARDED_FOR"를 사용하는 것이 가장 좋은 방법 중 하나입니다.

여기 왜 ...

때로는 방문자가 프록시 서버 또는 라우터 뒤에 있으며 표준 Request.UserHostAddress는 프록시 서버 또는 라우터의 IP 주소 만 캡처합니다. 이 경우 사용자의 IP 주소는 서버 변수 ( "HTTP_X_FORWARDED_FOR")에 저장됩니다.

그래서 우리가하고 싶은 것은 먼저 "HTTP_X_FORWARDED_FOR"를 체크하고 그것이 비어 있다면 간단히 ServerVariables("REMOTE_ADDR")을 반환합니다.

이 방법은 절대 안전한 것은 아니지만 더 나은 결과를 이끌어 낼 수 있습니다. 다음은 VB.NET의 ASP.NET 코드입니다. James Crowley의 블로그 게시물 인 "Gotcha : HTTP_X_FORWARDED_FOR는 여러 IP 주소를 반환합니다."

C #

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
418
mangokun

업데이트 : Bruno Lopes에게 감사드립니다. 여러 개의 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"];
    }
70
algreat

그 외에 사용자 IP 주소를 어떻게 생각하십니까? 네트워크 어댑터의 IP 주소를 원한다면 웹 앱에서 IP 주소를 사용할 수있는 방법이 없습니다. 사용자가 NAT 또는 다른 것들보다 뒤처진 경우 IP를받을 수 없습니다.

Update : IP를 사용하여 사용자를 제한하는 웹 사이트 (예 : rapidshare)는 NAT 환경에서 제대로 작동하지 않습니다.

23
Mehrdad Afshari

만약 C #이 방법을보고, 매우 간단합니다

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

나는 내 경험을 모두 당신과 공유해야한다고 생각합니다. 어떤 상황에서는 REMOTE_ADDR이 (가) 찾고있는 것을 얻지 못합니다. 예를 들어 장면 뒤에 Load Balancer가 있고 클라이언트의 IP를 얻으려는 경우 문제가 발생합니다. IP 마스킹 소프트웨어를 사용하여 확인한 다음 다른 대륙에있는 동료와도 확인했습니다. 그래서 여기에 내 해결책이있다.

클라이언트의 IP를 알고 싶을 때 모든 가능한 증거를 선택하여 고유한지 여부를 결정할 수 있습니다.

여기서 나는 클라이언트 측의 정확한 IP를 원한다면 당신을 도울 수있는 다른 서버를 발견했다. 그래서 사용하고 있습니다 : HTTP_X_CLUSTER_CLIENT_IP

HTTP_X_CLUSTER_CLIENT_IP는 항상 클라이언트의 정확한 IP를 가져옵니다. 어떤 경우이든 값을 제공하지 않으면 HTTP_X_FORWARDED_FOR를 찾아야 클라이언트 IP를 얻는 데 두 번째로 적합한 후보이고 REMOTE_ADDR var는 반환 할 수도 있고 돌려주지 않을 수도 있습니다 이 IP를 가지고 있지만이 세 가지를 모두 가지고있는 것은 내가 그들을 모니터하는 최선의 방법입니다.

나는 이것이 어떤 사람들을 돕기를 바랍니다.

21
KMX

당신이 사용할 수있는:

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

IP 주소는 "7 층 스택"의 네트워크 계층의 일부입니다. 네트워크 계층은 IP 주소로 원하는 모든 작업을 수행 할 수 있습니다. 프록시 서버, NAT, 릴레이 등에서 이러한 현상이 발생합니다.

응용 프로그램 계층은 어떤 식 으로든 IP 주소에 의존해서는 안됩니다. 특히, IP 주소는 네트워크 연결의 한쪽 끝의 ID 이외의 식별자가 될 수 없습니다. 연결이 닫히 자마자, (동일한 사용자의) IP 주소가 변경 될 것을 기대해야합니다.

13
John Saunders

CloudFlare를 사용하는 경우이 Extension Method 를 사용해보십시오.

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();
9
Tony

지금까지의 모든 응답은 표준화되지 않았지만 매우 공통, 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; }
        }
    }
}
8
dana
string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;
8
GorkemHalulu

할 수있는 일은 사용자의 라우터 IP와 전달 된 IP를 저장하고 두 IP [외부 공개 및 내부 사설] 모두를 사용하여 신뢰할 수있게하려고합니다. 그러나 며칠 후 클라이언트는 라우터로부터 새로운 내부 IP를 할당받을 수 있지만 더 신뢰할 수 있습니다.

7
Shahid

@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;
    }
}
4
Nitesh

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"];
}
3
Behnam Mohammadi

안녕 얘들 아 당신이 찾을 수있는 코드의 대부분은 당신에게 클라이언트 IP 주소가 아닌 서버 IP 주소를 반환합니다.이 코드는 올바른 클라이언트 IP 주소를 반환합니다. 시도해보십시오. 더 많은 정보를 원하시면이 부분을 확인하십시오.

https://www.youtube.com/watch?v=Nkf37DsxYjI

자바 스크립트를 사용하여 로컬 IP 주소를 얻으려면이 코드를 스크립트 태그 안에 넣으십시오.

<script>
    var RTCPeerConnection = /*window.RTCPeerConnection ||*/
     window.webkitRTCPeerConnection || window.mozRTCPeerConnection;

         if (RTCPeerConnection) (function () {
             var rtc = new RTCPeerConnection({ iceServers: [] });
             if (1 || window.mozRTCPeerConnection) {      
                 rtc.createDataChannel('', { reliable: false });
             };

             rtc.onicecandidate = function (evt) {

                 if (evt.candidate)
                     grepSDP("a=" + evt.candidate.candidate);
             };
             rtc.createOffer(function (offerDesc) {
                 grepSDP(offerDesc.sdp);
                 rtc.setLocalDescription(offerDesc);
             }, function (e) { console.warn("offer failed", e); });


             var addrs = Object.create(null);
             addrs["0.0.0.0"] = false;
             function updateDisplay(newAddr) {
                 if (newAddr in addrs) return;
                 else addrs[newAddr] = true;
                 var displayAddrs = Object.keys(addrs).filter(function
(k) { return addrs[k]; });
                 document.getElementById('list').textContent =
displayAddrs.join(" or perhaps ") || "n/a";
             }

             function grepSDP(sdp) {
                 var hosts = [];
                 sdp.split('\r\n').forEach(function (line) { 
                     if (~line.indexOf("a=candidate")) {   
                         var parts = line.split(' '),   
                             addr = parts[4],
                             type = parts[7];
                         if (type === 'Host') updateDisplay(addr);
                     } else if (~line.indexOf("c=")) {      
                         var parts = line.split(' '),
                             addr = parts[2];
                         updateDisplay(addr);
                     }
                 });
             }
         })(); else
         {
             document.getElementById('list').innerHTML = "<code>ifconfig| grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
             document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";

         }




</script>
<body>
<div id="list"></div>
</body>

공개 IP 주소를 얻으려면이 코드를 스크립트 태그 안에 넣으십시오.

  function getIP(json) {
    document.write("My public IP address is: ", json.ip);
  }


<script type="application/javascript" src="https://api.ipify.org?format=jsonp&callback=getIP"></script>
0
Shubham