在Chrome扩展中获取设备的本地IP

22
我正在开发一个Chrome扩展程序,它需要在本地网络中发现并与其他设备进行通信。为了发现这些设备,它需要找到自己的IP地址以确定网络的IP范围并检查其他设备。我无法找到本地机器的IP地址(我不是说localhost,也不是指暴露给互联网的地址,而是指本地网络上的地址)。基本上,我希望能够在background.js内部获得终端中ifconfig的输出。 Chrome Apps API提供了chrome.socket,似乎可以做到这一点,但扩展程序无法使用该API。通过阅读扩展程序的API,我没有找到任何可以让我找到本地IP的方法。

我是否遗漏了什么或者由于某些原因这是不可能的?还有其他发现网络上其他设备的方法,只要它们在同一IP范围内也可以(因为它们将在同一IP范围内),但是尽管从2012年12月开始就有一些关于扩展程序的发现API的传言,但似乎还不存在。

有人有任何想法吗?


如果有多个地址,因为机器有几个本地网络接口怎么办? - Barmar
如果可能的话,我想要所有地址。 - Lukas Ruge
你解决这个问题了吗? - user417669
“扩展API”的链接已经失效,不再有效。请考虑更新为:https://developer.chrome.com/docs/extensions/reference/。 “chrome.socket”和“background.js”的链接也已失效(不确定是否有更新的等效物)。 “ifconfig”链接是德语的,但存在英语等效物。https://en.wikipedia.org/wiki/Ifconfig - Wyck
4个回答

44

您可以通过WebRTC API获取本地IP地址列表(更准确地说,是本地网络接口的IP地址)。此API可被任何Web应用程序使用(不仅限于Chrome扩展程序)。

示例:

// Example (using the function below).
getLocalIPs(function(ips) { // <!-- ips is an array of local IP addresses.
    document.body.textContent = 'Local IP addresses:\n ' + ips.join('\n ');
});

function getLocalIPs(callback) {
    var ips = [];

    var RTCPeerConnection = window.RTCPeerConnection ||
        window.webkitRTCPeerConnection || window.mozRTCPeerConnection;

    var pc = new RTCPeerConnection({
        // Don't specify any stun/turn servers, otherwise you will
        // also find your public IP addresses.
        iceServers: []
    });
    // Add a media line, this is needed to activate candidate gathering.
    pc.createDataChannel('');
    
    // onicecandidate is triggered whenever a candidate has been found.
    pc.onicecandidate = function(e) {
        if (!e.candidate) { // Candidate gathering completed.
            pc.close();
            callback(ips);
            return;
        }
        var ip = /^candidate:.+ (\S+) \d+ typ/.exec(e.candidate.candidate)[1];
        if (ips.indexOf(ip) == -1) // avoid duplicate entries (tcp/udp)
            ips.push(ip);
    };
    pc.createOffer(function(sdp) {
        pc.setLocalDescription(sdp);
    }, function onerror() {});
}
<body style="white-space:pre"> IP addresses will be printed here... </body>


这应该是被接受的答案!!非常好用!我花了一整天的时间搜索,但每个人都说要发送请求到www服务器,但多亏了@Rob W他解决了它 :-) - Rafique Mohammed
1
@Zorgatone 可能不止一个,例如如果您通过电缆、无线、VPN等连接,则会显示活动网络接口的列表。所有IP地址都有潜在用途。请注意,我的方法仅显示本地地址(例如192.168.1.1),如果您正在寻找公共IP地址,则必须在“iceServers”列表中指定STUN服务器。 - Rob W
不,谢谢,我不需要公共的那个。好吧,我正在开发一款移动应用程序。在移动设备上通常只有一个网络。如果没有IPV6地址而只有IPV4,我会选择第一个。谢谢! :) - Zorgatone
由于某种原因,当我将此代码插入到我的代码中时,回调函数永远不会被触发。我可以在 getLocalIPs 之前打断点,但是当我恢复时,它会直接跳过回调函数。 - moodyak
1
这会给我一个类似于“763fa077-240d-4996-941d-714b9f2b0f6f.local”的东西,而不是IP地址。如果我切换到无痕标签页,它就可以工作了。原来你需要在chrome://flags中禁用“WebRTC公开的本地IP地址匿名化”标志。 - bhdrozgn
显示剩余2条评论

2

经过一番搜索,我发现类似的问题已经有人回答过了

如果是在扩展程序中调用,无法访问该API,但对于Chrome应用程序可用:

可以使用chrome.system.network.getNetworkInterfaces

该方法将返回一个包含所有接口及其IP地址的数组。

以下是示例代码:

chrome.system.network.getNetworkInterfaces(function(interfaces){ console.log(interfaces); });

权限声明(manifest-permissions):

"permissions": [ "system.network" ], ...


实际上,可以查询本地网络接口的地址。我已在https://dev59.com/OmMl5IYBdhLWcg3wOU5g#29514292发布了一个示例。 - Rob W
我已经使用正确的API更新了答案。你的解决方案看起来不错,但WebRTC实现中是否存在漏洞呢?在Firefox中,由于NoScript将其检测为XSS尝试,因此阻止了您片段的执行。 - 3demax
不,能够获取IP地址是WebRTC的一个功能。为了与其他对等方通信,两个对等方都必须知道彼此的地址。如果两者都在同一局域网中,则只需知道本地地址即可。否则,需要使用STUN来获取公共IP地址。 - Rob W
3
这不适用于扩展,它会产生以下错误:'system.network' 仅允许打包的应用程序使用,但这是一个扩展。 - jishi

0
> chrome.system.network.getNetworkInterfaces(function(interfaces){
>       console.log(interfaces);    }); 

清单权限:

"permissions": [ "system.network" ],...

对我也有效,并回复:

(4) [{…}, {…}, {…}, {…}]

0 : {address: "xxxx", name: "en0", prefixLength: 64}

1 : {address: "192.168.86.100", name: "en0", prefixLength: 24}

2 : {address: "xxxx", name: "awdl0", prefixLength: 64}

3 : {address: "xxxx", name: "utun0", prefixLength: 64}

length : 4


这个错误提示告诉我:'system.network' 只允许在打包的应用程序中使用,但这是一个扩展程序。 - Can Rau

-2

请查看http://developer.chrome.com/extensions/webRequest.html获取详细信息, 以下是我的代码示例:

// get IP using webRequest
var currentIPList = {};
chrome.webRequest.onCompleted.addListener(
  function(info) {
    currentIPList[info.url] = info.ip;
    currentIPList[info.tabId] = currentIPList[info.tabId] || [];
    currentIPList[info.tabId].push(info);
    return;
  },
  {
    urls: [],
    types: []
  },
  []
);

2
据我所知,这会获取远程服务器的IP地址,而不是客户端自己的IP地址。看起来@LukasRuge正在尝试获取客户端的IP地址。 - Doktor J

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接