无法从 RTCPeerConnection 获取 IP V4 地址 - chrome
Unable to fetch IP V4 address from RTCPeerConnection - chrome
我需要从 Web 应用程序中获取客户端本地 IP 地址。
为此,我使用标准的 RTCPeerConnection 实现来获取。但是返回的ice candidate并没有携带IP V4地址,而是一个类似guid的地址:asdf-xxxx-saass-xxxx.local
但令人惊讶的是 chrome extension 能够在同一台机器和浏览器上获取相同的内容。
注意:我在 Web 应用程序中使用的代码与扩展程序中使用的代码相同
这是 html 相同的代码:
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript">
function logit(msg) {
var dt = new Date(); var time = dt.getHours() + ":" + dt.getMinutes() + ":"
+ dt.getSeconds();
console.log(time + " " + msg);
};
function getChromeVersion() {
try {
var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
return raw ? parseInt(raw[2], 10) : false;
} catch (e) {
return null;
}
}
function getChromeManifest() {
return chrome.runtime && typeof chrome.runtime === "function" ? chrome.runtime.getManifest() : {}
}
function getUserIP(callback) {
logit(" getting user local ip ")
getLocalIPs(function (ips) {
logit(" got user local ip : " + ips)
if (ips && ips.length) return callback(ips[0]);
logit(" getting user local ip with stun ")
getLocalIPs(function (ips) {
logit(" got user local ip with stun : " + ips)
if (ips && ips.length) return callback(ips[0])
logit(" cannot get user local ip, returning null ")
callback(null)
}, true, 2000)
})
}
function getLocalIPs(callback, withStun, timeout) {
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: [],
iceServers: withStun ? [{ urls: "stun:stun.services.mozilla.com" }] : []
});
var closeAndCallback = function () {
clearTimeout(waitTimeout)
try {
if (pc && pc.close) {
pc.close();
}
} catch (e) { console.log("exception while closing pc, err: %s", err) }
callback(ips);
}
var waitTimeout = timeout ? setTimeout(closeAndCallback, timeout) : null;
// 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) {
console.log(e)
if (!e.candidate) { // Candidate gathering completed.
pc.close();
closeAndCallback();
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() { });
};
function callThirdParty(server, name) {
var api = server;
logit("Connecting " + server + " ...");
$.ajax({
type: "GET",
url: api,
success: function (data) {
if (data && data['ip']) {
logit("Public IP: " + data['ip']);
}
}, error:
function (request, status, error) {
logit('Response: ' + request.responseText);
logit(' Error: ' + error);
logit(' Status: ' + status);
},
complete: function (data) {
logit(' API Finished: ' + name + " Server!");
}
});
}
document.addEventListener('DOMContentLoaded', function () {
getUserIP(function (ip) { //
ipaddress = ip;
$('#ip2').html(ipaddress);
var manifest = getChromeManifest();
logit(manifest.name);
logit("Version: " + manifest.version);
logit("Chrome Version: " + getChromeVersion());
callThirdParty("https://api.ipify.org?format=json", "ipify.org");
}, 100);
}, false);
</script>
</head>
<p>Public IPs</p>
<div id="ip"></div>
<p>Local IP</p>
<div id="ip2"></div>
<p>Logs</p>
<div id="log"></div>
<div id="log1"></div>
<div id="log2"></div>
</html>
TL;DR
看起来本地地址 are/will 将使用 mDNS 进行匿名化,对于所有 Chrome 用户,标志的默认设置将逐渐设置为 Enabled
。
本地开发看这里(设置为Disable
):chrome://flags/#enable-webrtc-hide-local-ips-with-mdns
除非有人找到一些巧妙的技巧,否则您可能无法为您的网络应用程序的用户恢复更改。
那个guid其实就是mDNS地址。快速搜索 Chromium 中最新的 WebRTC 错误 https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3ABlink%3EWebRTC+
揭示了一些有趣的条目,关于匿名化的 Whosebug 问题也很少 not working (like this one: mDNS Support for WebRTC at Google Chrome M74).
现在我在几台 Windows 10 的计算机上看到 Chrome 75 中的效果 - 一些以前能够完美检测本地 IP 的站点 (http://net.ipcalf.com, https://ipleak.net, https://browserleaks.com/webrtc) 现在不t 显示它或改为显示 mDNS url。
旁注:启用 mDNS 标志后,您链接的扩展无法检测到我的确切本地 IP。相反,它显示很少有来自 /24 地址组的候选地址。即使那样,该扩展程序也可以以某种方式享有特权,因此它不会受到 mDNS 匿名化的太大影响。
编辑(2020 年 3 月): Firefox 似乎也可以匿名化本地 IP。
截至 2020 年 3 月,about:config
页面中有两个设置:
media.peerconnection.ice.obfuscate_host_addresses
- 当设置为 true 时,它会将本地 IP 更改为 {uuid}.local
media.peerconnection.ice.obfuscate_host_addresses.whitelist
- 带有 URL 的字符串,即使启用混淆也能够检索真实 IP
我检查了 Firefox 73 和 Developer Edition 74(没有任何可能更改设置的扩展),首先将 obfuscate_host_addresses
设置为 false,而开发版启用了它。
编辑(2020 年 10 月): 自 Chrome 86 起,mDNS 设置已启用,无法再通过 chrome://flags 禁用(有没有这样的选项可用)。
我需要从 Web 应用程序中获取客户端本地 IP 地址。
为此,我使用标准的 RTCPeerConnection 实现来获取。但是返回的ice candidate并没有携带IP V4地址,而是一个类似guid的地址:asdf-xxxx-saass-xxxx.local
但令人惊讶的是 chrome extension 能够在同一台机器和浏览器上获取相同的内容。
注意:我在 Web 应用程序中使用的代码与扩展程序中使用的代码相同
这是 html 相同的代码:
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript">
function logit(msg) {
var dt = new Date(); var time = dt.getHours() + ":" + dt.getMinutes() + ":"
+ dt.getSeconds();
console.log(time + " " + msg);
};
function getChromeVersion() {
try {
var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
return raw ? parseInt(raw[2], 10) : false;
} catch (e) {
return null;
}
}
function getChromeManifest() {
return chrome.runtime && typeof chrome.runtime === "function" ? chrome.runtime.getManifest() : {}
}
function getUserIP(callback) {
logit(" getting user local ip ")
getLocalIPs(function (ips) {
logit(" got user local ip : " + ips)
if (ips && ips.length) return callback(ips[0]);
logit(" getting user local ip with stun ")
getLocalIPs(function (ips) {
logit(" got user local ip with stun : " + ips)
if (ips && ips.length) return callback(ips[0])
logit(" cannot get user local ip, returning null ")
callback(null)
}, true, 2000)
})
}
function getLocalIPs(callback, withStun, timeout) {
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: [],
iceServers: withStun ? [{ urls: "stun:stun.services.mozilla.com" }] : []
});
var closeAndCallback = function () {
clearTimeout(waitTimeout)
try {
if (pc && pc.close) {
pc.close();
}
} catch (e) { console.log("exception while closing pc, err: %s", err) }
callback(ips);
}
var waitTimeout = timeout ? setTimeout(closeAndCallback, timeout) : null;
// 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) {
console.log(e)
if (!e.candidate) { // Candidate gathering completed.
pc.close();
closeAndCallback();
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() { });
};
function callThirdParty(server, name) {
var api = server;
logit("Connecting " + server + " ...");
$.ajax({
type: "GET",
url: api,
success: function (data) {
if (data && data['ip']) {
logit("Public IP: " + data['ip']);
}
}, error:
function (request, status, error) {
logit('Response: ' + request.responseText);
logit(' Error: ' + error);
logit(' Status: ' + status);
},
complete: function (data) {
logit(' API Finished: ' + name + " Server!");
}
});
}
document.addEventListener('DOMContentLoaded', function () {
getUserIP(function (ip) { //
ipaddress = ip;
$('#ip2').html(ipaddress);
var manifest = getChromeManifest();
logit(manifest.name);
logit("Version: " + manifest.version);
logit("Chrome Version: " + getChromeVersion());
callThirdParty("https://api.ipify.org?format=json", "ipify.org");
}, 100);
}, false);
</script>
</head>
<p>Public IPs</p>
<div id="ip"></div>
<p>Local IP</p>
<div id="ip2"></div>
<p>Logs</p>
<div id="log"></div>
<div id="log1"></div>
<div id="log2"></div>
</html>
TL;DR
看起来本地地址 are/will 将使用 mDNS 进行匿名化,对于所有 Chrome 用户,标志的默认设置将逐渐设置为 Enabled
。
本地开发看这里(设置为Disable
):chrome://flags/#enable-webrtc-hide-local-ips-with-mdns
除非有人找到一些巧妙的技巧,否则您可能无法为您的网络应用程序的用户恢复更改。
那个guid其实就是mDNS地址。快速搜索 Chromium 中最新的 WebRTC 错误 https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3ABlink%3EWebRTC+ 揭示了一些有趣的条目,关于匿名化的 Whosebug 问题也很少 not working (like this one: mDNS Support for WebRTC at Google Chrome M74).
现在我在几台 Windows 10 的计算机上看到 Chrome 75 中的效果 - 一些以前能够完美检测本地 IP 的站点 (http://net.ipcalf.com, https://ipleak.net, https://browserleaks.com/webrtc) 现在不t 显示它或改为显示 mDNS url。
旁注:启用 mDNS 标志后,您链接的扩展无法检测到我的确切本地 IP。相反,它显示很少有来自 /24 地址组的候选地址。即使那样,该扩展程序也可以以某种方式享有特权,因此它不会受到 mDNS 匿名化的太大影响。
编辑(2020 年 3 月): Firefox 似乎也可以匿名化本地 IP。
截至 2020 年 3 月,about:config
页面中有两个设置:
media.peerconnection.ice.obfuscate_host_addresses
- 当设置为 true 时,它会将本地 IP 更改为 {uuid}.localmedia.peerconnection.ice.obfuscate_host_addresses.whitelist
- 带有 URL 的字符串,即使启用混淆也能够检索真实 IP
我检查了 Firefox 73 和 Developer Edition 74(没有任何可能更改设置的扩展),首先将 obfuscate_host_addresses
设置为 false,而开发版启用了它。
编辑(2020 年 10 月): 自 Chrome 86 起,mDNS 设置已启用,无法再通过 chrome://flags 禁用(有没有这样的选项可用)。