Javascript webrtc (STUN) ipv6

问题描述

当尝试使用公共 STUN 服务器查找我的公共 IP 地址时,它适用于 IPv4,但不适用于 IPv6,无论我使用什么 STUN 服务器。

我只在候选地址下得到“59aeb370-1d93-44ee-a526-27d639256cf4.local”之类的东西。 有没有办法使用 STUN 通过 javascript 获取公共 IPv6?

我使用的代码是:

(不要介意 IPv4 正则表达式;无论如何,整个“候选人”都是控制台记录的)

@base <http://test.com/ns> .
@prefix foobar: <http://test.com/ns#> .

<#anotherthing> a "Blubb" ;
    foobar:contains "another property" .

<#something> a "Blah" ;
    foobar:contains "a property" .

编辑:

似乎在某些情况下,当在某些网页的控制台内运行代码时,我确实在响应中获得了我的 IPv6。

但是,例如,当从 chrome 隐身访问同一页面时,它不起作用,所以这不是因为域或类似的原因。

也不涉及任何权限。

那到底是怎么回事?它背后的逻辑是什么?有什么办法可以让我的网页始终使其访问者收到他们的 IPv6 地址?

解决方法

引用一篇关于您的问题的精彩文章:

忽略这一事实,谷歌已经在运行 mDNS 作为几个 Chrome 版本的实验。作为实验,决定了两件事:

  • 它几乎“随机”地在用户的 Chrome 浏览器上运行,对用户或正在发生的服务没有任何实际控制(至少不是自动化和明显的)
  • 仅在必须共享本地 IP 地址且不需要摄像头或麦克风权限时才添加它(仅接收场景)

基本上,Chrome 一直在推出 mDNS IP 混淆。这意味着如果您的脚本不调用 getUserMedia,候选行将被混淆。请阅读整篇文章here

旧答案:

由于 Chrome 团队的安全问题,IP 地址现在被混淆(隐藏,definition)。如果您查看 post you commented 上的日期(2018 年,三年前),您会发现这个问题和解决方案是多么过时。

但是,您可以使用 UDP 传输,它可以可靠地返回用户的IPv4 地址。考虑以下代码段:

iceServers: [{
    urls: "stun:stun.l.google.com:19302?transport=udp"
}]

话虽如此,您还可以使用诸如 Abstract 之类的第 3 部分 API 可靠地获取用户的 IP 地址(请参阅第 3 方 IP 查找的完整列表 here)。或者,您可以使用 Node.js 来做同样的事情。以下是一些相关的代码示例和文章:

How to Get User’s IP Details in ExpressJS - 文章

geoip-lite - Node.js 模块

Node.js 中的简单 ip 检测:

const express = require('express');
const app = express();
const router = express.Router();

router.get('/someroute',(req,res) => {
  const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
  console.log(ip); // ip address of the user
});

app.use('/',router);
app.listen(5000);

(找到 here

参考文献:

Wikipedia

基本协议的工作原理如下:客户端,通常在专用网络中运行,向公共 Internet 上的 STUN 服务器发送绑定请求。从服务器的角度观察,STUN 服务器以包含客户端 IP 地址和端口号的成功响应进行响应。 结果通过异或 (XOR) 映射进行模糊处理,以避免应用层网关转换数据包内容 (ALG),这些网关执行深度数据包检查以尝试执行备用 NAT 遍历方法。

RFC 5389

XOR-MAPPED-ADDRESS 属性与 MAPPED-ADDRESS 相同 属性,除了反射传输地址被混淆 通过异或函数。

这是最终代码:

var ip_dups = {};

function getRTCPeerConnection () {
    var iframe,content_window,rtc_peer_con = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;
    return rtc_peer_con || (iframe = document.createElement("iframe"),iframe.style.display = "none",document.body.appendChild(iframe),content_window = iframe.contentWindow,rtc_peer_con = content_window.RTCPeerConnection || content_window.mozRTCPeerConnection || content_window.webkitRTCPeerConnection || content_window.msRTCPeerConnection),rtc_peer_con
};

var n = getRTCPeerConnection();
servers = {
    iceServers: [{
        urls: "stun:stun.l.google.com:19302?transport=udp"
    }]
};  
mediaConstraints = {
    optional: [{
        RTCPChannel: true
    }]
};
        
pc = new n(servers,mediaConstraints);

function handleCandidate(candidate){
    console.log(candidate);
    //match just the IP address
    var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
    var ip_addr = ip_regex.exec(candidate)[1];
    if(ip_dups[ip_addr] === undefined) {
        console.log(ip_addr);
        ip_dups[ip_addr] = true;
    }
    pc.close()
}

pc.onicecandidate = function(ice){
    //skip non-candidate events
    console.log(ice)
    if(ice.candidate) {
        handleCandidate(ice.candidate.candidate);
    }
};
// now you have to create a data channel with a name
pc.createDataChannel("fake_data_channel");

void pc.createOffer(function(e) {
    console.log(e)
    console.log(e.sdp)
    pc.setLocalDescription(e,function() {},function() {})
},function() {})