web-dev-qa-db-fra.com

Pouvez-vous obtenir une adresse IP de réseau local d'utilisateurs via JavaScript?

Je sais que la réaction initiale à cette question est "non" et "cela ne peut pas être fait" et "vous ne devriez pas en avoir besoin, vous faites quelque chose de mal". Ce que j'essaie de faire, c'est d'obtenir l'adresse IP du réseau local des utilisateurs et de l'afficher sur la page Web. Pourquoi? C’est la page sur laquelle je travaille qui affiche le plus d’informations possibles sur vous, le visiteur: http://www.whatsmyip.org/more-info-about-you/ =

Je ne fais donc rien en réalité avec l’IP, si ce n’est le montrer à l’utilisateur à des fins d’information. J'avais l'habitude de faire cela en utilisant un petit applet Java. Cela a plutôt bien fonctionné. Mais ces jours-ci, les navigateurs vous font frapper d’accord et de confiance tellement de fois, pour exécuter même le plus mineur des applets Java, que je préférerais ne pas en exécuter un du tout.

Donc, pendant un moment, je viens de me débarrasser de cette fonctionnalité, mais j'aimerais la récupérer si possible. En tant que consultant en informatique, c’était quelque chose que j’utilisais de temps en temps. Il est plus rapide d'aller sur ce site Web pour voir sur quelle plage IP un réseau fonctionne, plutôt que d'aller dans les Préférences Système, Réseau, puis quelle que soit l'interface active.

Alors je me demande, en espérant, s'il y a un moyen de le faire en javascript seulement? Peut-être qu'un nouvel objet auquel vous pouvez accéder, similaire à la façon dont javascript peut demander au navigateur où se trouve l'emplacement géographique sur la Terre. Il y a peut-être quelque chose de similaire pour les informations de réseau client? Sinon, peut-être une autre façon de le faire? Les seuls moyens auxquels je peux penser sont un applet Java ou un objet flash. Je préférerais ne faire ni l'un ni l'autre.

85
l008com

Il s’avère que la récente extension WebRTC de HTML5 permet à javascript d’interroger l’adresse IP du client local. Une preuve de concept est disponible ici: http://net.ipcalf.com

Cette fonctionnalité est apparemment à dessein , et n’est pas un bug. Cependant, étant donné sa nature controversée, je serais prudent de me fier à ce comportement. Néanmoins, je pense que cela répond parfaitement et de manière appropriée à l'objectif recherché (révéler à l'utilisateur les fuites de son navigateur).

105
afourney

En plus de la réponse de afourney, ce code fonctionne dans les navigateurs prenant en charge WebRTC (Chrome et Firefox). J'ai entendu parler d'un mouvement visant à mettre en œuvre une fonctionnalité qui oblige les sites à demander l'adresse IP (comme dans le cas de la géolocalisation de l'utilisateur ou du média de l'utilisateur), bien qu'elle n'ait pas encore été implémentée dans l'un ou l'autre de ces navigateurs.

Voici une version modifiée du code source , réduit le nombre de lignes, ne faisant aucune demande d'étourdissement, car vous ne voulez que l'adresse IP locale et non l'adresse IP publique:

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

Nous créons une connexion homologue factice pour que l'homologue distant puisse nous contacter. Nous échangeons généralement les candidats à la glace les uns avec les autres et en lisant les candidats à la glace, nous pouvons connaître l'adresse IP de l'utilisateur.

Vous pouvez trouver une démo sur -> Demo

73
mido

J'ai nettoyé le poste de mido, puis la fonction trouvée. Cela retournera soit false ou un array. Lors du test rappelez-vous que vous devez réduire le tableau dans la console du développeur Web, sinon son comportement par défaut non intuitif peut vous induire en erreur en lui faisant croire qu'il renvoie un array vide.

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

De plus, n'oubliez pas que ce n'est pas quelque chose de nouveau, comme CSS border-radius bien que l'un de ces bits soit carrément pas pris en charge par IE11 et les versions antérieures. Toujours utilisez la détection d'objet, testez dans des navigateurs raisonnablement anciens (par exemple, Firefox 4, IE9, Opera 12.1) et assurez-vous que vos nouveaux scripts ne cassent pas vos nouveaux morceaux de code. De plus, toujours détecte le code conforme aux normes premier donc s'il y a quelque chose avec un préfixe CSS, par exemple, détecte le code standard non préfixé premier et se replie ensuite comme à long terme, le support finira par être normalisé pour le reste de son existence.

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

     //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);
    };
}
5
Joaquín Piñeyro

WebRTC API peut être utilisé pour récupérer l'adresse IP locale du client.

Cependant, le navigateur peut ne pas le prendre en charge ou le client peut l’avoir désactivé pour des raisons de sécurité. Dans tous les cas, il ne faut pas compter sur ce "bidouillage" sur le long terme car il est probable qu'il soit corrigé à l'avenir (voir la réponse de Cullen Fluffy Jennings).

Le code ECMAScript 6 ci-dessous montre comment procéder.

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

Remarquez que j’écris return resolve(..) ou return reject(..) comme raccourci. Ces deux fonctions ne renvoient rien.

Ensuite, vous pouvez avoir quelque chose comme ça:

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

Vous pouvez trouver plus d'informations sur les limitations que les navigateurs vont probablement ajouter pour atténuer ce problème et sur ce que fait l'IETF à ce sujet, ainsi que sur les raisons de cette nécessité sur SPEC IETF sur le traitement IP

3