JavaScript Aracılığıyla Kullanıcının Yerel LAN IP Adresi Alabilir misiniz?


102

Bu soruya verilen ilk tepkinin "hayır" ve "yapılamaz" ve "buna ihtiyacın olmamalı, yanlış bir şey yapıyorsun" olduğunu biliyorum. Yapmaya çalıştığım şey, kullanıcıların LAN IP adresini almak ve bunu web sayfasında görüntülemek. Neden? Çünkü üzerinde çalıştığım sayfa bununla ilgili, sizin hakkınızda mümkün olduğunca fazla bilgi gösteren ziyaretçi: http://www.whatsmyip.org/more-info-about-you/

Bu yüzden, IP'yi kullanıcıya bilgi amaçlı göstermek dışında aslında hiçbir şey YAPMAMAK. Bunu küçük bir Java uygulaması kullanarak yapardım. Oldukça iyi çalıştı. Ancak bu günlerde, tarayıcı, en küçük java uygulamasını bile çalıştırmak için birçok kez hemfikir olmanızı ve güvenmenizi sağlar ki, hiç birini çalıştırmamayı tercih ederim.

Bir süreliğine bu özellikten kurtuldum, ancak mümkünse geri gelmesini istiyorum. Bir bilgisayar danışmanı olarak zaman zaman kullandığım bir şeydi. Bir ağın hangi IP aralığında çalıştığını görmek için bu web sitesine gitmek, Sistem Tercihleri, Ağ Oluşturma ve daha sonra hangi arayüzün aktif olduğuna gitmekten daha hızlıdır.

Merak ediyorum, umuyorum, bunu tek başına javascript ile yapmanın bir yolu var mı? Belki javascript’in tarayıcıya dünyanın coğrafi konumunun nerede olduğunu sorabilmesine benzer şekilde erişebileceğiniz bazı yeni nesneler. Belki istemci ağ bilgileri için benzer bir şey vardır? Değilse, belki de tamamen yapmanın başka bir yolu vardır? Aklıma gelen tek yol bir java uygulaması veya bir flash nesnesidir. İkisini de yapmamayı tercih ederim.


1
Cevabı biliyorsun. O zaman neden soruyorsun? Java uygulamalarına veya flash nesnelerine kullanıcılar tarafından izin verilme olasılığı düşüktür (yalnızca İnternet'te yeni olanlar olabilir) - bu nedenle bu yaygın bir çözüm değildir. ActiveX ve yakındaki öğeler yalnızca IE'de çalışıyor ve bu nedenle, diğer tarayıcıların kullanıcıları etkilenmeyecek (ve dahası, IE'de bile web sitesinin kötü şeyler yapmasını önleyen bir güvenlik politikası var)
Alma Do

IP adresim HTTP_X_FORWARDED_FORo sayfada, sadece söyleniyor.
tomdemuyt

51
O halde neden soruyorsunuz? Çünkü belki, sadece belki, her şeyi bilmiyorum.
l008com

1
: Bu adamlar bunu yapmak whatismyproxy.com
likebike

1
@likebike Güzel biri. Bunu nasıl yaptıklarını araştırıyorum.
Dominic Cerisano

Yanıtlar:


117

HTML5'in son WebRTC uzantısı, javascript'in yerel istemci IP adresini sorgulamasına olanak tanıyor. Bir kavram kanıtı burada mevcuttur: http://net.ipcalf.com

Bu özellik görünüşe göre tasarım gereğidir ve bir hata değildir. Bununla birlikte, tartışmalı doğası göz önüne alındığında, bu davranışa güvenmek konusunda temkinli olurum. Yine de, amacınıza mükemmel ve uygun bir şekilde hitap ettiğini düşünüyorum (kullanıcıya tarayıcısının neyi sızdırdığını açıklamak).


1
Bu yardımcı oldu. Tekrar teşekkürler!
Ansuraj Khadanga

7
Sadece chrome ve firefox üzerinde çalışıyor, IE, Edge veya safaride DEĞİL
ali

WAN IP'mi arıyordum ve whatismyip.com bu web sitesi de bana yerel IP adresimi verdi ve sanırım JS ile bir ilgisi vardı.
Shayan

@ali Haklısınız, yukarıda bahsettiğim web sitesi yerel IP'mi Edge'de söyleyemez.
Shayan

7
Google Chrome, varsayılan olarak yerel IP'yi gizlemektedir. E87e041d-15e1-4662-adad-7a6601fca9fb.local'a benzer bir şey gösterir . Bu davranış, # enable-webrtc-hide-local-ips-with-mdns değişkeninin Chrome: // flags
injaon

81

Güncelleme

Tarayıcılar webrtc sızıntısını düzelttiği için bu çözüm artık işe yaramayacak: bununla ilgili daha fazla bilgi için şu diğer soruyu okuyun: RTCIceCandidate artık IP döndürmüyor


Afourney'in cevabına ek olarak, bu kod WebRTC'yi destekleyen tarayıcılarda (Chrome ve Firefox) çalışır. Sitelerin IP'yi istemesini sağlayan bir özelliği uygulamaya yönelik bir hareket olduğunu duydum (kullanıcının coğrafi konumu veya kullanıcı medyası durumunda olduğu gibi), ancak bu tarayıcılardan herhangi birinde henüz uygulanmamış.

İşte kaynak kodun değiştirilmiş bir versiyonu , satırları azalttı, sadece Yerel IP'yi Genel IP'yi istemediğiniz için herhangi bir bayıltma isteği yapmayın:

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;
 }
};

Uzak eşin bizimle iletişime geçmesi için sahte bir eş bağlantısı oluşturuyoruz. Genelde birbirimizle buz adayları değiş tokuşu yapıyoruz ve buz adaylarını okuyarak kullanıcının ipini söyleyebiliriz.

-> Demo adresinde bir demo bulabilirsiniz


Bu Mido için teşekkürler! Çok minnettarım.
Sujay Phadke

1
@dampee - Edge'in şu anda veri kanallarını desteklemediğine inanıyorum.
MichaelB76

Sahte veri kanalı nedir? Google'da herhangi bir referans bulunamıyor
AmazingTurtle

2
createOffer api'nin, param olarak successCallback ve failCallback yerine Promise'a dayandığına dikkat edin, bu nedenle bu, daha yeni sürümlerde çalışmayabilir, bkz: developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/…
Dickeylth

10

WebRTC API müşterinin yerel IP almak için kullanılabilir.

Ancak tarayıcı bunu desteklemeyebilir veya istemci güvenlik nedenleriyle onu devre dışı bırakmış olabilir. Her halükarda, gelecekte yamalanması muhtemel olduğundan, bu "hack" e uzun vadede güvenilmemelidir (Cullen Fluffy Jennings'in cevabına bakınız).

Aşağıdaki ECMAScript 6 kodu bunun nasıl yapılacağını göstermektedir.

/* 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();
    };
} );

Dikkat edin yazıyorum return resolve(..)veya return reject(..)kısayol olarak. Bu işlevlerin her ikisi de hiçbir şey döndürmez.

O zaman şuna sahip olabilirsiniz:

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

Mido'nun gönderisini temizledim ve sonra buldukları işlevi temizledim. Bu ya dönecek falseya da bir array. Test ederken, web geliştirici konsolundaki diziyi daraltmanız gerektiğini unutmayın , aksi takdirde bu sezgisel olmayan varsayılan davranış, boş bir geri döndüğünü düşünerek sizi yanıltabilir 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;
}

Bu CSS gibi eski yeni bir şey olmadığını Ayrıca zihnin millet bulundurun border-radiusdüpedüz olan bu bit biri olsa değil IE11 ve daha eski desteklediği. Her zaman nesne algılamayı kullanın, oldukça eski tarayıcılarda test edin (örn. Firefox 4, IE9, Opera 12.1) ve yeni komut dosyalarınızın yeni kod parçalarını bozmadığından emin olun. Ayrıca her zaman standartlarla uyumlu kod tespit öncelikle bir CSS öneki standart dışı önceden sabitlenmiş kod tespit söylemek ile bir şey varsa o kadar ilk ve ardından sonunda 's varlığının kalanı için standardize edilecek uzun vadeli destek olarak geri düşer.


yeniden ip
bildiriyorsunuz

@Anu WebRTC, Internet Explorer 15'e (veya "Edge 15") kadar tanıtılmadı, bu yüzden hayır. Bu nedenle, yukarıdaki dördüncü satırda nesnelerden hiçbiri yoksa işlev yanlış döndürür. IE'de bunu başarmanın başka bir yolu varsa, o zaman şu anda bunun farkında değilim.
John

@John - dönüş değerini bir php değişkenine nasıl iletiriz? Gizli bir gönderi aracılığıyla mı?
MarcoZen

@MarcoZen <input name="example1" type="hidden" value="whatever" />Böyle bir durumda AJAX POST kullanabilir veya kullanabilirsiniz. ajax()Fonksiyonumu burada incelemenizi şiddetle tavsiye ederim : jabcreations.com/docs/javascript
John

Bazı tarayıcıların (ör. Chrome) artık IP sağlamayı engellediğini öğrendim - aynı kod, Video / Ses izni istenmezse, artık bir mDNS ana bilgisayar adına çözümleniyor. Bkz groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU
Christoph 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)


Kodunuzu uygun şekilde biçimlendirmek için lütfen düzenleyici seçeneklerini kullanın.
31piy

3
Sadece biraz kod düşürmekle kalmaz, aynı zamanda onun ve kodunuzda neler olup bittiğine dair bir açıklama yaparsanız harika olur. Soru yazarına ve diğer kullanıcılara yardımcı olur. İşe yararsa iyidir, ancak bence neden daha önemli olduğunu bilmek.
davejal

IE uyumlu herhangi bir çözüm var mı?
Anu

1
Yorum, bu makalenin bir kopyasıdır: ourcodeworld.com/articles/read/257/…
Darkshifty

Bazı tarayıcıların (ör. Chrome) artık IP sağlamayı engellediğini öğrendim - aynı kod, Video / Ses izni istenmezse, artık bir mDNS ana bilgisayar adına çözümleniyor. Groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU adresine
Christoph Bimminger

5

Chrome 76+

Geçen yıl Linblow'un cevabını (2018-Ekim-19) yerel IP'mi javascript aracılığıyla başarılı bir şekilde keşfetmek için kullandım. Ancak, son Chrome güncellemeleri (76?), Bu yöntemi artık şaşkına çeviren bir IP döndürmek üzere uyandırdı:1f4712db-ea17-4bcf-a596-105139dfd8bf.local

Tarayıcınız üzerinde tam kontrole sahipseniz, bunu adres çubuğunuza yazarak Chrome Bayrakları'nda kapatarak bu davranışı geri alabilirsiniz:

chrome://flags

ve bayrağın DEVRE DIŞI BIRAKILMASI Anonymize local IPs exposed by WebRTC

Benim durumumda, mevcut konumumu belirlemek ve konumuma bağlı olarak farklı şeyler yapmak için bir TamperMonkey komut dosyası için IP'ye ihtiyacım var. Ayrıca kendi tarayıcı ayarlarım üzerinde tam kontrole sahibim (Kurumsal Politikalar yok, vb.). Bu yüzden benim için chrome://flagsayarı değiştirmek hile yapıyor.

Kaynaklar:

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

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


o bayrak kaybolabilir. Şu anda uzantılar hala IP alıyor gibi görünüyor, bu nedenle arka plan komut dosyasından almayı deneyebilirsiniz. Uzun vadeli tüm bahisler kapalıdır.
Philipp Hancke

1
Göre Groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU'ya , Ses / Video izni talep eden çözümünüzü uygularsanız IP yine de döndürülmelidir.
Christoph Bimminger


0

Bir RTCPeerConnectionkullanılabilir. İznin getUserMediagerekli olduğu Chrome gibi tarayıcılarda , sadece mevcut giriş cihazlarını tespit edip bunları isteyebiliriz.

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)
            }
        })
    })
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.