Многоадресная рассылка IPv6 с Node.js

node.js ipv6 multicast

671 просмотра

2 ответа

123918 Репутация автора

Я экспериментирую с многоадресной рассылкой IPv6 UDP через VPN. Я пробовал следующий код:

const dgram = require('dgram');

let sock = dgram.createSocket('udp6', {
  reuseAddr: true
});

sock.on('message', (data, source) => {
  console.log('on message', arguments);
});

sock.bind('36912', '2620:9b::1944:e598', () => {
  sock.addMembership('ff02::1:3', '2620:9b::1944:e598');
});


setInterval(() => {
  let buf = Buffer.from((new Date()).toString());
  sock.send(buf, 0, buf.length, 36912, 'ff02::1:3');
}, 500);

Сценарий запускается, и я вижу пакеты, отправляемые / получаемые с помощью Wireshark, но ни один конец не показывает их в консоли.

Wireshark UDP Capture

Что я делаю неправильно? Как можно отправить и получить базовую многоадресную рассылку с IPv6?

Автор: Brad Источник Размещён: 19.07.2016 01:50

Ответы (2)


7 плюса

10669 Репутация автора

Scope id -> номер интерфейса

В IPv6 существует концепция scope_id адреса, который должен указывать контекст для IP-адреса, и, как правило, просто означает, на каком интерфейсе он доступен. В то время как у областей есть специфичные для ОС имена, каждое из них просто переводит номер интерфейса, где 0 обычно означает системное значение по умолчанию.

В многоадресной рассылке IPv6 этот scope_id предоставляется непосредственно IP_ADD_MEMBERSHIP и IP_MULTICAST_IF вместо предоставления IP-адреса, связанного с интерфейсом, как это делает IPv4.

сглаживание различий в v6

узел (через libuv) скрывает эту разницу для вас addMembership, ища scope_id по «адресу интерфейса», который вы предоставляете.

К сожалению, начинать с простого IP-адреса и получать область видимости не имеет большого смысла (весь смысл области в том, что IP-адрес может использоваться по-разному в разных областях.) Таким образом, libuv может заполнить область видимости только в том случае, если Вы явно предоставляете это в конце адреса, используя %[scope]формат.

Использование адресов с явными областями

Способ обойти это, кажется:

 sock.bind('36912', '::', () => {
   sock.addMembership('ff02::1:3', '::%eth2');
 ...
 sock.send(buf, 0, buf.length, 36912, 'ff02::1:3%eth2');

Где:

  • использование ::(или отсутствие адреса) в связывании необходимо, так как вы комбинируете получение, которое фильтрует многоадресный адрес по этому адресу, с отправкой, которой нужен нормальный адрес.

  • используя %[iface#]силы область действия этого интерфейса #.

  • Второй аргумент addMembership может действительно начинаться с любого адреса, так как мы форсируем область действия, а остальные отбрасываются.

  • Обычно отправляющий сокет отделяется и получает другой порт или анонимный порт, поскольку вы либо ограничены в том, что вы можете настроить, либо рискуете получить ошибки EADDRINUSE из-за слишком похожих сокетов.

Автор: lossleader Размещён: 22.07.2016 11:48

1 плюс

1960 Репутация автора

Я следовал инструкциям в этом ответе, но все еще не мог заставить работать многоадресную рассылку IPv6. Оказалось, что я настраивал socket.setMulticastLoopback(false)фильтрацию сообщений, поступающих от самого узла, что хорошо работало для IPv4, но блокировало все сообщения для IPv6. Устранение этой проблемы устранило проблему, и сообщения начали появляться правильно, без необходимости фильтровать.

Автор: Adam Reis Размещён: 08.08.2017 04:44
Вопросы из категории :
32x32