Node.js - 无法将 udp6 套接字绑定到特定地址

Node.js - Can't bind a udp6 socket to a specific address

来自 Node,此可用地址列表:

var os = require('os');
os.networkInterfaces()

打印:

{ lo0:
   [ { address: '::1',
       netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
       family: 'IPv6',
       mac: '00:00:00:00:00:00',
       scopeid: 0,
       internal: true },
     { address: '127.0.0.1',
       netmask: '255.0.0.0',
       family: 'IPv4',
       mac: '00:00:00:00:00:00',
       internal: true },
     { address: 'fe80::1',
       netmask: 'ffff:ffff:ffff:ffff::',
       family: 'IPv6',
       mac: '00:00:00:00:00:00',
       scopeid: 1,
       internal: true } ],
  en0:
   [ { address: 'fe80::2acf:e9ff:fe1f:3939',
       netmask: 'ffff:ffff:ffff:ffff::',
       family: 'IPv6',
       mac: '28:cf:e9:1f:39:39',
       scopeid: 4,
       internal: false },
     { address: '10.0.0.8',
       netmask: '255.255.255.0',
       family: 'IPv4',
       mac: '28:cf:e9:1f:39:39',
       internal: false } ],
  awdl0:
   [ { address: 'fe80::e46a:6cff:fe68:a76a',
       netmask: 'ffff:ffff:ffff:ffff::',
       family: 'IPv6',
       mac: 'e6:6a:6c:68:a7:6a',
       scopeid: 8,
       internal: false } ] }

但是如果我尝试创建特定的 udp 套接字,我可以绑定 udp4 但不能绑定 udp6 套接字。

var dgram = require('dgram');
var udp4 = dgram.createSocket('udp4');
udp4.bind(null, '10.0.0.8');
udp4.address()

打印

{ address: '10.0.0.8', family: 'IPv4', port: 65061 }

但是

var udp6 = dgram.createSocket('udp6');
udp6.bind(null, 'fe80::e46a:6cff:fe68:a76a');

投掷:

Error: bind EADDRNOTAVAIL fe80::e46a:6cff:fe68:a76a
    at Object.exports._errnoException (util.js:874:11)
    at exports._exceptionWithHostPort (util.js:897:20)
    at dgram.js:213:18
    at doNTCallback3 (node.js:452:9)
    at process._tickDomainCallback (node.js:399:17)

同样的事情发生在地址 'fe80::2acf:e9ff:fe1f:3939' 上。注意,我在 Nodes 的 REPL 中 运行 这些语句,所以当我尝试检查地址时绑定已经完成。

我能做到

udp6.bind()
udp6.address()

打印

{ address: '::', family: 'IPv6', port: 51897 }

但这并没有告诉我它绑定到哪个地址(我需要它来通知其他同行)。

为什么我可以绑定到特定的 IPv4 地址而不是 IPv6 地址?这似乎不一致。这可能是运行时中的错误吗? Relevant bug in Node issue tracker.

我需要具有特定地址的 udp 套接字,这些地址反映了 os.networkInterfaces 的可用内容,因为我是 building an ICE agent

我正在使用 Node v4.2.2。

好的,看来我需要 Link-local addresses 的背景知识。

要点是,对于 IPv4,您通常使用 DHCP 等协议来分配本地 IP 地址。如果你不这样做,你可以选择一个并希望你不会与网络上的其他主机发生冲突。这样的地址称为“Link 本地地址”。这些在 IPv4 中是可选的,现在在 IPv6 中是必需的。 Link 本地地址始终具有前缀 fe80:: IPv6 地址前缀。

在 Node.js 中,您可以监听 link 本地地址,但您必须在地址字符串后加上接口名称,例如:

udp6.bind(null, 'fe80::e46a:6cff:fe68:a76a%en0');

可以从 运行 ifconfig.

中找到具体的字符串

那么,同网的其他peer可以联系你,但是也必须指定同网的网络设备的接口。例如

nc6 -u fe80::2acf:e9ff:fe1f:3939%wlp3s0 65022

其中wlp3s0是朋友无线网卡的接口。

如果他们插入以太网并连接到同一网络,则他们可以通过以太网接口发送,但除非它连接到同一本地网络。

此外,我发布的 IP 地址表明我的家庭路由器没有分配 IPv6 地址。在工作中,我得到了一个 IPv6 地址,所以我可以毫无问题地监听一个非 fe80 前缀的地址。在工作中,os.networkInterfaces() 看起来更像是:

  en0:
   [ { address: 'fe80::2acf:e9ff:fe1f:3939',
       netmask: 'ffff:ffff:ffff:ffff::',
       family: 'IPv6',
       mac: '28:cf:e9:1f:39:39',
       scopeid: 4,
       internal: false },
     { address: '10.252.28.131',
       netmask: '255.255.248.0',
       family: 'IPv4',
       mac: '28:cf:e9:1f:39:39',
       internal: false },
     { address: '2620:101:80fc:224:2acf:e9ff:fe1f:3939',
       netmask: 'ffff:ffff:ffff:ffff::',
       family: 'IPv6',
       mac: '28:cf:e9:1f:39:39',
       scopeid: 0,
       internal: false },
     { address: '2620:101:80fc:224:4d78:1087:39a2:65d7',
       netmask: 'ffff:ffff:ffff:ffff::',
       family: 'IPv6',
       mac: '28:cf:e9:1f:39:39',
       scopeid: 0,
       internal: false } ],

所以我可以成功绑定到任何 2620: 前缀地址。

最后,对于我的 ICE 代理,updated draft spec 表示“不得收集对应于 IPv6 link 本地地址的候选主机。”