您可以通过 JavaScript 获取用户本地 LAN IP 地址吗?

IT技术 javascript ip-address
2021-01-20 21:04:37

我知道对这个问题的最初react是“不”和“它无法完成”和“你不应该需要它,你做错了什么”。我想要做的是获取用户的 LAN IP 地址,并将其显示在网页上。为什么?因为这就是我正在处理的页面的全部内容,尽可能多地显示有关您(访问者)的信息:https : //www.whatsmyip.org/more-info-about-you/

所以我实际上并没有对 IP 做任何事情,除了将其显示给用户以供参考。我曾经通过使用一个小的 Java 小程序来做到这一点。它工作得很好。但是这些天,浏览器让你多次点击同意和信任,即使是最小的 Java 小程序,我也不想运行一个。

所以有一段时间我只是摆脱了这个功能,但如果可能的话我希望它回来。作为一名计算机顾问,我有时会实际使用它。访问此网站以查看网络运行的 IP 范围比进入系统偏好设置、网络以及任何活动接口要快。

所以我想知道,希望,是否有某种方法可以单独在 javascript 中做到这一点?也许您可以访问一些新对象,类似于 javascript 可以询问浏览器地球上的地理位置在哪里。也许客户端网络信息有类似的东西?如果没有,也许有其他方法可以完全做到这一点?我能想到的唯一方法是 Java 小程序或 Flash 对象。我宁愿不做其中任何一个。

6个回答

事实证明,最近 HTML5 的 WebRTC 扩展允许 javascript 查询本地客户端 IP 地址。概念证明可在此处获得:http : //net.ipcalf.com

此功能显然是设计使然,并不是错误。但是,鉴于其有争议的性质,我对依赖这种行为持谨慎态度。尽管如此,我认为它完美且恰当地解决了您的预期目的(向用户透露他们的浏览器正在泄漏什么)。

这很有帮助。再次感谢!
2021-03-13 21:04:37
它仅适用于 chrome 和 firefox,不适用于 IE、Edge 或 safari
2021-03-25 21:04:37
默认情况下,谷歌浏览器隐藏本地 IP。它显示了类似于e87e041d-15e1-4662-adad-7a6601fca9fb.local 的内容可以通过在 Chrome://flags中将变量#enable-webrtc-hide-local-ips-with-mdns 设置禁用来更改此行为
2021-03-28 21:04:37
我正在查找我的 WAN IP,这个网站whatismyip.com也给了我我的本地 IP,我猜它与 JS 有关系。
2021-04-01 21:04:37
这不再起作用,对象作为本地 ipV4 地址RTCSessionDescription返回0.0.0.0它返回本地 ip 直到大约 Firefox 80
2021-04-07 21:04:37

更新

此解决方案将不再有效,因为浏览器正在修复 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;
 }
};

我们正在为远程对等方创建一个虚拟对等连接以与我们联系。我们一般会互相交换ice的候选,读取ice的候选就可以知道用户的ip。

您可以在 --> Demo找到演示

请注意 createOffer api 已切换为基于 Promise 而不是 successCallback 和 failCallback 作为参数,因此这可能不适用于较新版本,请参阅:developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/...
2021-03-13 21:04:37
感谢这个美度!非常感激。
2021-03-19 21:04:37
@dampee - 我相信 Edge 目前不支持数据通道。
2021-03-25 21:04:37
什么是虚假数据通道?在谷歌上找不到任何参考
2021-04-02 21:04:37

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

我清理了mido的帖子,然后清理了他们发现的功能。这将返回falsearray. 测试时请记住,您需要在 Web 开发人员控制台中折叠数组,否则它的非直观默认行为可能会欺骗您认为它正在返回一个空的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;
}

另外请记住,border-radius虽然IE11 及更早版本完全支持这些位之一,但这并不是像 CSS 那样的新旧东西始终使用对象检测,在相当旧的浏览器(例如 Firefox 4、IE9、Opera 12.1)中进行测试,并确保您的新脚本不会破坏您的新代码。另外总是检测标准的代码第一,所以如果有什么用说CSS前缀检测标准的非前缀码第一,然后回落作为长期的支持最终将被标准化为它的存在的其余部分。

您正在重新声明ip- 第 3 行和第 8 行。
2021-03-27 21:04:37
@Anu WebRTC 直到 Internet Explorer 15(或“Edge 15”)才被引入,所以没有。这就是为什么在上面的第四行,如果不存在任何对象,函数将返回 false。如果在 IE 中有另一种方法可以实现这一点,那么我目前不知道。
2021-03-27 21:04:37
@John - 我们如何将返回值传递给 php 变量?通过隐藏的帖子?
2021-03-27 21:04:37
刚刚发现某些浏览器(例如 Chrome)现在会阻止提供 IP - 如果没有请求视频/音频许可,相同的代码现在会解析为 mDNS 主机名。请参阅groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU
2021-03-29 21:04:37
@MarcoZen<input name="example1" type="hidden" value="whatever" />在这种情况下,您可以使用或使用 AJAX POST。我强烈建议在ajax()这里学习我的函数:jabcreations.com/docs/javascript
2021-04-01 21:04:37

铬 76+

去年,我使用 Linblow 的答案(2018 年 10 月 19 日)通过 javascript 成功发现了我的本地 IP。但是,最近的 Chrome 更新(76?)已经使用了这种方法,因此它现在返回一个混淆的 IP,例如:1f4712db-ea17-4bcf-a596-105139dfd8bf.local

如果您可以完全控制浏览器,则可以通过在地址栏中键入以下内容在 Chrome Flags 中将其关闭来撤消此行为:

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,因此您可以尝试从后台脚本中获取它。不过,从长远来看,所有赌注都没有了。
2021-03-17 21:04:37
我正在寻找这个完全相同的原因,当我阅读你帖子的最后一段时,lmao。不敢相信这在 2020 年末仍然是可能的,但很高兴它是!+1 分享。
2021-03-27 21:04:37
根据groups.google.com/forum/#!topic/discuss-webrtc/6stQXi72BEU,如果您实施请求音频/视频权限的解决方案,IP 仍应返回。
2021-04-05 21:04:37