JavaScript를 통해 사용자 로컬 LAN IP 주소를 얻을 수 있습니까?


102

이 질문에 대한 초기 반응은 "아니오", "할 수 없습니다", "필요하지 않아야합니다. 뭔가 잘못하고 있습니다"라는 것을 알고 있습니다. 내가하려는 것은 사용자 LAN IP 주소를 가져 와서 웹 페이지에 표시하는 것입니다. 왜? 이것이 내가 작업중인 페이지의 전부이기 때문에 방문자에 대해 가능한 한 많은 정보를 표시합니다. http://www.whatsmyip.org/more-info-about-you/

따라서 정보 제공 목적으로 사용자에게 표시하는 것 외에는 실제로 IP로 아무것도하지 않습니다. 저는 작은 Java 애플릿을 사용하여이 작업을 수행했습니다. 꽤 잘 작동했습니다. 그러나 요즘 브라우저는 당신이 동의하고 신뢰를 많이해서 아주 사소한 자바 애플릿도 실행하기 때문에 나는 전혀 실행하지 않을 것입니다.

그래서 잠시 동안이 기능을 제거했지만 가능하면 되돌리고 싶습니다. 제가 컴퓨터 컨설턴트로서 실제로 사용하는 것이 었습니다. 이 웹 사이트로 이동하여 네트워크가 실행중인 IP 범위를 확인하는 것이 시스템 환경 설정, 네트워킹 및 활성화 된 인터페이스로 이동하는 것보다 빠릅니다.

그래서 나는 자바 스크립트만으로 할 수있는 방법이 있는지 궁금합니다. 자바 스크립트가 브라우저에 지구상의 지리적 위치가 어디에 있는지 묻는 것과 유사한 방식으로 액세스 할 수있는 새로운 개체 일 수 있습니다. 클라이언트 네트워킹 정보와 비슷한 것이 있습니까? 그렇지 않다면 완전히 다른 방법이 있습니까? 내가 생각할 수있는 유일한 방법은 자바 애플릿 또는 플래시 객체입니다. 차라리 그 중 하나를하지 않을 것입니다.


1
당신은 답을 알고 있습니다. 그럼 왜 물어? Java 애플릿 또는 플래시 개체는 사용자가 허용하지 않을 가능성이 높으므로 (인터넷을 처음 접하는 사용자 만 허용 할 수 있음) 일반적인 경우에는 해결책이 아닙니다. ActiveX 및 주변 항목은 IE에서만 작동합니다. 따라서 다른 브라우저의 사용자는 영향을받지 않습니다 (또한 IE에서도 웹 사이트가 불쾌한 작업을 수행하지 못하도록하는 보안 정책이 있습니다)
Alma Do

내 IP 주소는 HTTP_X_FORWARDED_FOR해당 페이지를 통해 캡처 됩니다.
tomdemuyt 2013

50
그럼 왜 물어? 왜냐하면 아마도, 나는 모든 것을 알지 못하기 때문입니다.
l008com 2013

1
:이 녀석은 할 whatismyproxy.com
likebike

1
@likebike 좋은 사람입니다. 그들이 어떻게 이것을하고 있는지 살펴 봅니다.
Dominic Cerisano 2011

답변:


117

결과적으로 HTML5의 최신 WebRTC 확장은 자바 스크립트가 로컬 클라이언트 IP 주소를 쿼리 할 수 ​​있도록합니다. 개념 증명은 http://net.ipcalf.com에서 확인할 수 있습니다.

이 기능은 분명히 의도적으로 설계된 것으로 버그가 아닙니다. 그러나 논란의 여지가있는 성격을 감안할 때 나는이 행동에 의존하는 것에 대해 신중할 것입니다. 그럼에도 불구하고 귀하의 의도 된 목적을 완벽하고 적절하게 해결한다고 생각합니다 (사용자에게 브라우저에서 유출되는 내용을 공개).


1
이것은 도움이되었습니다. 다시 한 번 감사드립니다!
Ansuraj Khadanga

7
IE, Edge 또는 safari가 아닌 크롬과 파이어 폭스에서만 작동합니다
ali

나는 내 WAN IP를 찾고 있었고이 웹 사이트 whatismyip.com 도 내 로컬 IP를 제공했으며 JS와 관련이 있다고 생각합니다.
Shayan

@ali 맞습니다. 위에서 언급 한 웹 사이트는 Edge에서 내 로컬 IP를 알 수 없습니다.
Shayan

6
Google 크롬은 기본적으로 로컬 IP를 숨기고 있습니다. e87e041d-15e1-4662-adad-7a6601fca9fb.local 과 유사한 것을 보여줍니다 . 이 동작은 Chrome : // flags에서 # enable-webrtc-hide-local-ips-with-mdns 변수 를 비활성화 로 설정하여 변경할 수 있습니다 .
injaon

81

최신 정보

이 솔루션은 브라우저가 webrtc 누출을 수정하고 있기 때문에 더 이상 작동하지 않습니다. 이에 대한 자세한 정보는이 다른 질문을 읽으십시오. RTCIceCandidate는 더 이상 IP를 반환하지 않습니다.


afourney의 답변 외에도이 코드는 WebRTC (Chrome 및 Firefox)를 지원하는 브라우저에서 작동합니다. 사이트가 IP (사용자의 지리적 위치 또는 사용자 미디어의 경우)를 요청하도록하는 기능을 구현하려는 움직임이 있다고 들었습니다. 아직 두 브라우저 중 하나에서 구현되지 않았습니다.

다음은 소스 코드 의 수정 된 버전으로 , 공개 IP가 아닌 로컬 IP 만 원하므로 줄을 줄이면서 스턴 요청을하지 않습니다.

window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;//compatibility for Firefox and chrome
var pc = new RTCPeerConnection({iceServers:[]}), noop = function(){};      
pc.createDataChannel('');//create a bogus data channel
pc.createOffer(pc.setLocalDescription.bind(pc), noop);// create offer and set local description
pc.onicecandidate = function(ice)
{
 if (ice && ice.candidate && ice.candidate.candidate)
 {
  var myIP = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
  console.log('my IP: ', myIP);   
  pc.onicecandidate = noop;
 }
};

원격 피어가 당사에 연락 할 수 있도록 더미 피어 연결을 생성하고 있습니다. 우리는 일반적으로 얼음 후보를 서로 교환하고 얼음 후보를 읽고 사용자의 IP를 알 수 있습니다.

> - 당신은에서 데모를 찾을 수 있습니다 데모


미도 감사합니다! 매우 감사.
Sujay Phadke

1
@dampee-Edge는 현재 데이터 채널을 지원하지 않는다고 생각합니다.
MichaelB76

가짜 데이터 채널이란 무엇입니까? Google에서 참조를 찾을 수 없습니다
AmazingTurtle 19

2
createOffer api가 successCallback 및 failCallback 대신 Promise를 매개 변수로 사용하도록 전환되었으므로 최신 버전에서는 작동하지 않을 수 있습니다. 다음을 참조하십시오. developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/…
Dickeylth

10

한 WebRTC API는 클라이언트의 로컬 IP를 검색 할 수 있습니다.

그러나 브라우저가이를 지원하지 않거나 클라이언트가 보안상의 이유로 비활성화했을 수 있습니다. 어쨌든 미래에 패치 될 가능성이 있기 때문에 장기적 으로이 "해킹"에 의존해서는 안됩니다 (Cullen Fluffy Jennings의 답변 참조).

아래 ECMAScript 6 코드는이를 수행하는 방법을 보여줍니다.

/* ES6 */
const findLocalIp = (logInfo = true) => new Promise( (resolve, reject) => {
    window.RTCPeerConnection = window.RTCPeerConnection 
                            || window.mozRTCPeerConnection 
                            || window.webkitRTCPeerConnection;

    if ( typeof window.RTCPeerConnection == 'undefined' )
        return reject('WebRTC not supported by browser');

    let pc = new RTCPeerConnection();
    let ips = [];

    pc.createDataChannel("");
    pc.createOffer()
     .then(offer => pc.setLocalDescription(offer))
     .catch(err => reject(err));
    pc.onicecandidate = event => {
        if ( !event || !event.candidate ) {
            // All ICE candidates have been sent.
            if ( ips.length == 0 )
                return reject('WebRTC disabled or restricted by browser');

            return resolve(ips);
        }

        let parts = event.candidate.candidate.split(' ');
        let [base,componentId,protocol,priority,ip,port,,type,...attr] = parts;
        let component = ['rtp', 'rtpc'];

        if ( ! ips.some(e => e == ip) )
            ips.push(ip);

        if ( ! logInfo )
            return;

        console.log(" candidate: " + base.split(':')[1]);
        console.log(" component: " + component[componentId - 1]);
        console.log("  protocol: " + protocol);
        console.log("  priority: " + priority);
        console.log("        ip: " + ip);
        console.log("      port: " + port);
        console.log("      type: " + type);

        if ( attr.length ) {
            console.log("attributes: ");
            for(let i = 0; i < attr.length; i += 2)
                console.log("> " + attr[i] + ": " + attr[i+1]);
        }

        console.log();
    };
} );

내가 글을 return resolve(..)쓰거나 return reject(..)단축키로 사용하는 것에 주목하십시오 . 두 함수 모두 아무것도 반환하지 않습니다.

그러면 다음과 같은 것이있을 수 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Local IP</title>
</head>
<body>
    <h1>My local IP is</h1>
    <p id="ip">Loading..</p>
    <script src="ip.js"></script>
    <script>
    let p = document.getElementById('ip');
    findLocalIp().then(
        ips => {
            let s = '';
            ips.forEach( ip => s += ip + '<br>' );
            p.innerHTML = s;
        },
        err => p.innerHTML = err
    );
    </script>
</body>
</html>

9

나는 미도의 포스트를 정리하고 그들이 찾은 기능을 정리했다. 이것은 false또는 array. 테스트 할 때 웹 개발자 콘솔에서 배열을 축소해야한다는 점을 기억하십시오. 그렇지 않으면 직관적이지 않은 기본 동작으로 인해 빈 array.

function ip_local()
{
 var ip = false;
 window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || false;

 if (window.RTCPeerConnection)
 {
  ip = [];
  var pc = new RTCPeerConnection({iceServers:[]}), noop = function(){};
  pc.createDataChannel('');
  pc.createOffer(pc.setLocalDescription.bind(pc), noop);

  pc.onicecandidate = function(event)
  {
   if (event && event.candidate && event.candidate.candidate)
   {
    var s = event.candidate.candidate.split('\n');
    ip.push(s[0].split(' ')[4]);
   }
  }
 }

 return ip;
}

또한 IE11 및 이전 버전에서 border-radius완전히 지원 되지 않는 비트 중 하나이지만 CSS와 같이 구식이 아니라는 점을 명심하십시오 . 항상 객체 감지를 사용하고, 상당히 오래된 브라우저 (예 : Firefox 4, IE9, Opera 12.1)에서 테스트하고 최신 스크립트가 최신 코드를 깨뜨리지 않는지 확인하십시오. 또한 항상 표준 준수 코드를 먼저 감지 하므로 CSS 접두사가 표준 비 접두어 코드를 먼저 감지 한 다음 장기 지원이 결국 나머지 존재에 대해 표준화 될 것이므로 대체합니다.


재 선언합니다 ip-3 행과 8 행
user2757813

@Anu WebRTC는 Internet Explorer 15 (또는 "Edge 15")까지 도입되지 않았으므로 아닙니다. 그렇기 때문에 위의 네 번째 줄에서 개체가 없으면 함수가 false를 반환합니다. IE에서 이것을 달성하는 다른 방법이 있다면 지금은 알지 못합니다.
John

@John-반환 값을 PHP 변수에 어떻게 전달합니까? 숨겨진 게시물을 통해?
MarcoZen

@MarcoZen <input name="example1" type="hidden" value="whatever" />이러한 상황에서 AJAX POST를 사용 하거나 사용할 수 있습니다 . ajax()여기 에서 내 기능을 공부하는 것이 좋습니다 . jabcreations.com/docs/javascript
John

이제 일부 브라우저 (예 : Chrome)가 IP 제공을 차단한다는 사실을 알게되었습니다. 비디오 / 오디오 권한이 요청되지 않으면 동일한 코드가 이제 mDNS 호스트 이름으로 확인됩니다. 참조 groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU
크리스토프 Bimminger

6

function getUserIP(onNewIP) { //  onNewIp - your listener function for new IPs
  //compatibility for firefox and chrome
  var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
  var pc = new myPeerConnection({
      iceServers: []
    }),
    noop = function() {},
    localIPs = {},
    ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g,
    key;

  function iterateIP(ip) {
    if (!localIPs[ip]) onNewIP(ip);
    localIPs[ip] = true;
  }
  onNewIP
  //create a bogus data channel
  pc.createDataChannel("");

  // create offer and set local description
  pc.createOffer().then(function(sdp) {
    sdp.sdp.split('\n').forEach(function(line) {
      if (line.indexOf('candidate') < 0) return;
      line.match(ipRegex).forEach(iterateIP);
    });

    pc.setLocalDescription(sdp, noop, noop);
  }).catch(function(reason) {
    // An error occurred, so handle the failure to connect
  });

  //listen for candidate events
  pc.onicecandidate = function(ice) {
    if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;
    ice.candidate.candidate.match(ipRegex).forEach(iterateIP);
  };
}
getUserIP(console.log)


편집기 옵션을 사용하여 코드 형식을 적절하게 지정하십시오.
31piy

3
코드를 몇 개 떨어 뜨릴뿐만 아니라 그의 코드와 코드에서 무슨 일이 벌어지고 있는지에 대한 설명도 제공한다면 좋을 것입니다. 질문 작성자 및 다른 사용자에게 도움이됩니다. 효과가 있으면 좋지만 내 생각에는 그 이유를 아는 것이 훨씬 더 중요합니다.
davejal

IE 호환 솔루션이 있습니까?
Anu

1
이 의견은이 문서의 복사 붙여 넣기입니다 : ourcodeworld.com/articles/read/257/...
Darkshifty

이제 일부 브라우저 (예 : Chrome)가 IP 제공을 차단한다는 사실을 알게되었습니다. 비디오 / 오디오 권한이 요청되지 않으면 동일한 코드가 이제 mDNS 호스트 이름으로 확인됩니다. 참조 groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU
크리스토프 Bimminger

5

Chrome 76 이상

작년에 Linblow의 답변 (2018-Oct-19)을 사용하여 javascript를 통해 내 로컬 IP를 성공적으로 발견했습니다. 그러나 최근 Chrome 업데이트 (76?)는이 메서드를 중단하여 이제 다음과 같이 난독 화 된 IP를 반환합니다.1f4712db-ea17-4bcf-a596-105139dfd8bf.local

브라우저를 완전히 제어 할 수있는 경우 주소 표시 줄에 다음을 입력하여 Chrome 플래그에서 사용을 중지하여이 동작을 취소 할 수 있습니다.

chrome://flags

및 플래그 비활성화 Anonymize local IPs exposed by WebRTC

제 경우에는 현재 위치를 확인하고 내 위치에 따라 다른 작업을 수행하기 위해 TamperMonkey 스크립트에 대한 IP가 필요합니다. 또한 내 브라우저 설정을 완전히 제어 할 수 있습니다 (기업 정책 등 없음). 그래서 저에게는 chrome://flags설정을 변경하는 것이 트릭입니다.

출처 :

https://groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU

https://codelabs.developers.google.com/codelabs/webrtc-web/index.html


그 깃발이 사라질 수 있습니다. 현재 확장이 여전히 IP를 얻는 것처럼 보이므로 백그라운드 스크립트에서 가져 오려고 할 수 있습니다. 장기적인 모든 베팅은 꺼져 있습니다.
Philipp Hancke 19

1
groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU 에 따르면 오디오 / 비디오 권한을 요청하는 솔루션을 구현하는 경우 IP가 계속 반환되어야합니다.
크리스토프 Bimminger


0

RTCPeerConnection사용할 수 있습니다. getUserMedia권한이 필요한 Chrome과 같은 브라우저에서는 사용 가능한 입력 장치를 감지하고 요청할 수 있습니다.

const internalIp = async () => {
    if (!RTCPeerConnection) {
        throw new Error("Not supported.")
    }

    const peerConnection = new RTCPeerConnection({ iceServers: [] })

    peerConnection.createDataChannel('')
    peerConnection.createOffer(peerConnection.setLocalDescription.bind(peerConnection), () => { })

    peerConnection.addEventListener("icecandidateerror", (event) => {
        throw new Error(event.errorText)
    })

    return new Promise(async resolve => {
        peerConnection.addEventListener("icecandidate", async ({candidate}) => {
            peerConnection.close()

            if (candidate && candidate.candidate) {
                const result = candidate.candidate.split(" ")[4]
                if (result.endsWith(".local")) {
                    const inputDevices = await navigator.mediaDevices.enumerateDevices()
                    const inputDeviceTypes = inputDevices.map(({ kind }) => kind)

                    const constraints = {}

                    if (inputDeviceTypes.includes("audioinput")) {
                        constraints.audio = true
                    } else if (inputDeviceTypes.includes("videoinput")) {
                        constraints.video = true
                    } else {
                        throw new Error("An audio or video input device is required!")
                    }

                    const mediaStream = await navigator.mediaDevices.getUserMedia(constraints)
                    mediaStream.getTracks().forEach(track => track.stop())
                    resolve(internalIp())
                }
                resolve(result)
            }
        })
    })
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.