JavaScript를 통해 사용자 로컬 LAN IP 주소를 얻을 수 있습니까? “할 수 없습니다”, “필요하지 않아야합니다. 뭔가

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

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

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

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



답변

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

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


답변

최신 정보

이 솔루션은 브라우저가 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를 알 수 있습니다.

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


답변

한 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>


답변

나는 미도의 포스트를 정리하고 그들이 찾은 기능을 정리했다. 이것은 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 접두사가 표준 비 접두어 코드를 먼저 감지 한 다음 장기 지원이 결국 나머지 존재에 대해 표준화 될 것이므로 대체합니다.


답변

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)


답변

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


답변

이 문제를 완화하기 위해 브라우저가 추가 할 수있는 제한 사항과 IETF가 수행하는 작업 및 IP 처리에 대한 IETF SPEC 에서 이것이 필요한 이유에 대한 자세한 정보를 찾을 수 있습니다.