紹介する

紹介する

これまで、私はマルチキャストにipv4を使用しており、関連するすべてのコンピュータはLinuxを実行しています。私は2台のコンピュータで聞き、それらの1つ(別々の端末)に送ります。次の例では、送信コンピュータとリモートコンピュータ(ero)から「Hello 1」を受信します。

ero:~$ sudo ip addr add 224.4.19.42 dev enp4s0 autojoin
ero:~$ netcat -l -k -u -p 9988

strawberry:~ $ sudo ip addr add 224.4.19.42 dev wlan0 autojoin
strawberry:~ $ netcat -l -k -u -p 9988

strawberry:~ $ echo "Hello 1" | netcat -s 192.168.178.109 -w 0 -u 224.4.19.42 9988

ipv6を使用すると、リモートシステムのみを受信する限り機能します。以下の例では、「Hello 2」が ero によって受信されます。発信者(strawberry)もマルチキャストグループに参加すると、発信者(strawberry)とリモートシステム(ero)の両方が「Hello 3」を受信しません。

ero:~$ sudo ip addr add ff05:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:4141 dev enp4s0 autojoin
ero:~$ netcat -l -k -u -p 9988

strawberry:~ $ echo "Hello 2" | netcat -w 0 -s 2001:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:76d0 -u ff05:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:4141 9988

strawberry:~ $ sudo ip addr add ff05:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:4141 dev wlan0 autojoin
strawberry:~ $ netcat -l -k -u -p 9988

strawberry:~ $ echo "Hello 3" | netcat -w 0 -s 2001:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:76d0 -u ff05:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:4141 9988

たぶん面白いかもしれません。送信者アドレスを指定しない場合、つまり -s オプションがない場合、ipv4 の例は ipv6 と同じ動作を示します。イチゴがマルチキャストグループに参加していない場合にのみメッセージが受信されます。だから私はipv6を使って別の送信アドレスを試しました:例に示されているグローバルアドレス(2001:...)、一意のローカルアドレス(ULA; fd00:...)、およびリンクローカルアドレス(LLA; fe80:.. .) .) 。どちらも役に立ちません。

私が間違っていることについてのヒントはありますか?

答え1

紹介する

ホストシステムの場合、マルチキャストIPアドレスへの送信はユニキャストアドレスへの送信と非常に似ていますが、マルチキャストの受信は異なり、追加のAPIを使用します。ホストはマルチキャストアドレスをインターフェイスに割り当てず、代わりにアプリケーションが接続されたときにそれを結合します。要求時に(ソケットを使用)選択したマルチキャストトラフィックを受信することに興味があるプログラム。これはRFC 1112に記載されている。 RFCホストグループに参加そしてホストグループの退会この関数は、以下を使用してほとんどの *nix で使用される BSD ソケット API に変換されます。setsockopt(2)マルチキャストグループに参加して退会するオプション。 IPv6 は IPv4 と同じに従いますが、ルーティング動作を含む違いがあります。 POSIXは偶数です。珍しい 場所IPv6 APIを実装する方法(IPv4のマルチキャストをあまり説明しないようです。おそらく、オペレーティングシステム間でより断片化されているので価値がないからです)。

Linuxで使用されるデフォルトのソケットオプションは次のとおりです。IP_MULTICAST_IF追加するIP_ADD_MEMBERSHIPIPv4とIPV6_MULTICAST_IF追加するIPV6_ADD_MEMBERSHIP(POSIX互換エイリアスIPV6_JOIN_GROUP)(IPv6用)。 OPの質問も興味深いですが、基本的に有効になっています。IP_MULTICAST_LOOPそしてIPV6_MULTICAST_LOOP

回線で何が起こっているのかを理解し、ネットワーク上で動作するようにします(マルチキャストグループ管理プロトコルIPv4の場合、またはMLDIPv6の場合...)またはネットワーク全体(例:PIM-SM)はアプリケーションレベルでは必要ありません(ただし、特にスイッチやマルチキャストリスニングに関連する問題を解決するために必要な場合があります)。

残りの答えは、システムのネットワーク構成に特別な変更がないと予想しています。インターフェイスにマルチキャストアドレスは追加されず、オプションもありませんautojoin。また、224.4.19.42は次のとおりです。ロンドン証券取引所に割り当てられたAD-HOCブロックIIブロック。プライベートローカル範囲ブロックの構成選べる239.0.0.0/8以内

インターネット猫

インターネット猫(すべて変形)はマルチキャストを処理しません。したがって、ネットワーク設定を調整して(自動的に参加一般的にトンネルに関連する設定で使用することを意図しています)OPは、IPv4マルチキャストアドレスでnetcatを使用するように管理されていますが、IPv6ではそうではありませんでした。実際、マルチキャストを使用するすべてのアプリケーションは標準に準拠し、追加のAPIを使用して適切なマルチキャストブロードキャストサポートを取得します。 。次の診断ツールインターネット猫より複雑なソフトウェアを交換するために使用されますが、この交換は同じことができるはずです。インターネット猫に慣れています。

ソカット

IPv4

ソカットすでに(ほぼ)完了IPv4マルチキャストサポート

そのようなマルチキャストグループに送信する方法は、どのマルチキャストサポートインターフェイスを介して送信する必要があるかを指定することです(実際にはソカットこのAPIはアドレスバリアントのみをサポートしており、使用時にインターフェースを提供することはできません。ソカットAPI がサポートしているが使用しない限りダランもともとsocatオプション、以下を参照)、オプションでマルチキャストループバックが必要かどうsetsockoptかを宣言します(デフォルトでは有効になっているので、ここでは使用しないので、例に入れます)。

Strawberryには、デフォルトのパスがあるか、少なくともマルチキャスト224.4.19.42への期待されるインターフェイスを使用するパスがあれば十分ですnc。 :

echo "Hello 1" | socat -u - UDP4-DATAGRAM:224.4.19.42:9988
echo "Hello 1" | socat -u - UDP4-DATAGRAM:224.4.19.42:9988,ip-multicast-loop=1

それ以外の場合は、インターフェイスのアドレスとしてインターフェイスを指定する必要があります。

echo "Hello 1" | socat -u - UDP4-DATAGRAM:224.4.19.42:9988,ip-multicast-if=192.168.178.109

記録された使用ダランフォーマット1は、サポートされていない紹介段落で説明されているAPI部分のオプションをsocat使用して、任意のソケットオプションを使用できます。setsockoptこれはオペレーティングシステムであり、アーキテクチャによって異なります。 amd64(x86_64) アーキテクチャの Linux(>= 3.5) がここに紹介されます。

SOL_IP=0
IP_MULTICAST_IF= 32

in_mreqAPIバリアントに期待される代替構造:IPv4マルチキャストアドレス(プリアンブルによって導入されたビッグエンディアン形式IPv4アドレスの16進4バイトx)とローカルアドレス(別の4バイト)。バリエーションのin_mreqn場合:先行i。すべてのパラメータが必要なわけではありません。操作例(JSON形式の使用とjqインタフェースインデックス計算コマンドwlan0):

echo "Hello 1" | socat -u - UDP4-DATAGRAM:224.4.19.42:9988,setsockopt=0:32:x00000000xc0a8b26d
echo "Hello 1" | socat -u - UDP4-DATAGRAM:224.4.19.42:9988,setsockopt=0:32:x00000000x00000000i$(ip -j link show enp4s0 | jq '.[].ifindex')

使用している場合、ip-multicast-loop=0Strawberryは独自に発信されたマルチキャストトラフィックを受信しません。

受信部分は、IP_ADD_MEMBERSHIP参加するマルチキャストIPアドレスグループを指定するために使用する必要があり、ローカルアドレスまたはインターフェイスを選択することもできます(正しいアドレスを選択するためにルーティングスタックに依存しない場合は、これらのオプションの1つが再び必要です)。オプション)マルチキャストに移動せずにアドレスへの正しいパス(たとえば、デフォルトパスがない場合、またはデフォルトパスが間違っている場合)。ソケットが別のアドレスにバインドされていても、このローカルアドレスを宣言する必要はありません。それ以外の場合、INADDR_ANYオペレーティングシステムはこの選択に従います。受信部分は通常、UDP4-RECV(受信マージ)またはUDP4-RECVFROM(各データグラム分割)オプションを使用できますfork。たとえば、

224.4.19.42(デフォルトを含む)へのパスがある場合は、両方のホストで次の操作を行います。

socat -u UDP4-RECV:9988,ip-add-membership=224.4.19.42:0.0.0.0 -

そうでない場合(ここでインターフェース名の構文を選択)

  • ~のためイチゴ:

    socat -u UDP4-RECV:9988,ip-add-membership=224.4.19.42:wlan0 -
    
  • ~のためガアラ:

    socat -u UDP4-RECV:9988,ip-add-membership=224.4.19.42:enp4s0 -
    

IPv6

IPv6のサポートは部分的に実装されているようです。ip-add-membershipIPv4と同様に、同等のオプションがipv6-add-membershipソースコードに存在し動作しますが、どこにも文書化されていません。すべてのテストに使用されるソカート 7.4.1だからこのバージョンを見せてください。これオプションが存在します:

#ifdef IPV6_JOIN_GROUP
        IF_IP6    ("ipv6-add-membership",       &opt_ipv6_join_group)
#endif

またはエイリアス:

#ifdef IPV6_JOIN_GROUP
        IF_IP6    ("ipv6-join-group",   &opt_ipv6_join_group)
#endif

そして形式文後で使用するにはsetsockopt(2)

#ifdef IPV6_JOIN_GROUP
const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IPV6, IPV6_JOIN_GROUP };
#endif

したがって、実際にはデフォルトのマルチキャストIPv6リスニングがサポートされています(そうでない場合はdalanが必要です)。setsockopt-listen ソカット最新バージョンのオプションが必要です)。オプションがないためipv6-multicast-if(まだ?)、デフォルトのルーティングスタックを使用して転送を拒否することは不可能です。 dalan 形式は引き続き使用できます。使用される構造にはIPV6_MULTICAST_IFインターフェイスインデックスのみが必要です。IPV6_MULTICAST_IFIPv6マルチキャスト範囲がサイトローカルの範囲より低い場合(たとえば、ff01 :: 16またはff02 :: 16)、常に必要になる場合がありますが、他の場合はしばしば必要になることがあります(下記参照)。繰り返しますが、このパラメータはipv6-multicast-loopまだ実装されていないため、dalan形式のsetockoptオプションも必要です。

ここで、IPv6 ルーティングの動作は IPv4 と若干異なります。デフォルトパスに従わない可能性があり、インターフェイスが(再)設定される順序によっては、明示的に定義されたパスなしで複数のインターフェイスを使用するシステムで未定義の動作がある可能性があります。ルーティングテーブルは以下から切り替えることができます。

# ip -6 route show table all type multicast
multicast ff00::/8 dev wlan0 table local proto kernel metric 256 pref medium
multicast ff00::/8 dev dummy0 table local proto kernel metric 256 pref medium

到着

# ip -6 route show table all type multicast
multicast ff00::/8 dev dummy0 table local proto kernel metric 256 pref medium
multicast ff00::/8 dev wlan0 table local proto kernel metric 256 pref medium

インターフェイスがダウンして再び上がっても、使用するデフォルトインターフェイスを変更することです。すべての種類のコンテナー、仮想マシン、または動的インターフェイスを実行すると、この問題が発生する可能性があります。

最後に、システムのルーティングスタックの選択を信頼して盲目的に送信します(またはルーティングが正しく設定されていることがわかっている場合)。イチゴ(IPv6が要求するシェル解釈角かっこを避けるために引用符を参照してください):

echo "Hello 1" | socat -u - UDP6-DATAGRAM:'[ff05::4141]':9988

マルチキャストループバックを使用するには、dalanフォーマットオプションが必要であることを明示的に指定し、送信するインターフェイスを指定しますsetsockopt

SOL_IPV6= 41
IPV6_MULTICAST_LOOP= 19
IPV6_MULTICAST_IF= 17ブール値:実際には
IPV6_MULTICAST_LOOP整数のインデックス(したがってdalanデータ型に使用される文字):整数i
IPV6_MULTICAST_IF

echo "Hello 1" | socat -u - UDP6-DATAGRAM:'[ff05::4141]':9988,setsockopt=41:19:i1,setsockopt=41:17:i$(ip -j link show wlan0 | jq '.[].ifindex')
  • に受信しましたイチゴ:

    socat -u UDP6-RECV:9988,ipv6-add-membership='[ff05::4141]':wlan0 -
    
  • また受け取ったガアラ:

    socat -u UDP6-RECV:9988,ipv6-add-membership='[ff05::4141]':enp4s0 -
    

ピア数に関係なく、IPv6マルチキャスト通信が可能です。以下は、セルフループバックマルチキャストトラフィックの受信を無効にしてインターフェイスを指定する例です。

  • イチゴ:

    socat UDP6-DATAGRAM:'[ff05::4141]':9988,bind=:9988,ipv6-add-membership='[ff05::4141]':wlan0,setsockopt=41:19:i0,setsockopt=41:17:i$(ip -j link show wlan0 | jq '.[].ifindex') -
    
  • ガアラ(同じです。インターフェイス名にのみ機会があります):

    socat UDP6-DATAGRAM:'[ff05::4141]':9988,bind=:9988,ipv6-add-membership='[ff05::4141]':enp4s0,setsockopt=41:19:i0,setsockopt=41:17:i$(ip -j link show enp4s0 | jq '.[].ifindex') -
    
  • 他のシステムでも同じコマンドを実行できますが、インターフェイス名は異なる場合があります。

それぞれは、socat他のすべてのマルチキャストピアにデータを送信し(ターミナルにこれを入力し)、それらから送信されたトラフィックを再度読み取ります(ただし、それ自体から送信されたトラフィックは読み取りません)。

関連情報