使用 smcroute 连接不同物理接口上的两个客户端

A R*_*A R 4 routing multicast interface

我对网络很陌生。我有两个客户端连接在两个不同的物理接口上,它们上运行了 upnp。我想将它们都添加到同一个多播组中,以便它们都能相互发现,并且我将能够相互 ping 通。那可能吗?如何使用 smcroute 实现这一目标?

这是我尝试过的:

我创建了两个桥接接口(这是要求)并将它们连接到相应的物理接口。

向 smcroute.conf 添加了以下规则

mgroup from br1 group 239.255.255.250
mgroup from br2 group 239.255.255.250
mroute from br1 group 239.255.255.250 to br2
mroute from br2 group 239.255.255.250 to br1
Run Code Online (Sandbox Code Playgroud)

ip -s mroute 显示这个

# ip -s mroute
(x.x.x.x, 239.255.255.250) Iif: br2    Oifs: br1
  242 packets, 46509 bytes
(x.x.x.x, 239.255.255.250) Iif: br1     Oifs: br2
  243 packets, 46740 bytes
(x.x.x.x, 239.255.255.250) Iif: unresolved
#
Run Code Online (Sandbox Code Playgroud)

但是我的客户无法发现彼此。我是否以错误的方式做这件事?

/proc/net/ip_mr_vif 显示有数据包进出 br1 和 br2 接口。

这是要求。由于某些组织限制,我有两个物理接口,我不希望它们标记到同一个网桥。将有一些客户端连接到这些接口,在这些接口上运行 upnp 堆栈。我想让他们发现彼此。

我在这里尝试的解决方案是使用 arp 代理和 smcroute。我正在使用 arp 代理,因此两个客户端都能够检测到另一个。我正在使用 smcroute 将连接到这两个接口的所有客户端标记到多播组 239.255.255.250 并来回转发数据包。这是正确的方法吗?

添加我的设置图。

        Device 1                      Router                   Device 2
+-----------------+     +----------------------------+    +-----------------+
|                 |     |                            |    |                 |
|           eth1  |     | br2                    br1 |    |  wlan0          |
|   169.254.10.10 |-----| 169.254.50.1      10.0.0.1 |----| 169.254.168.11  |
| (self assigned) |     |                            |    | (self assigned) |
+-----------------+     +----------------------------+    +-----------------+
Run Code Online (Sandbox Code Playgroud)

用于启用代理 arp 的命令:

arp -i br2 -Ds 169.254.168.11 br1 pub
arp -i br1 -Ds 169.254.10.10 br2 pub
ip route add 169.254.168.0/24 dev br1
ip route add 169.254.10.0/24 dev br2
Run Code Online (Sandbox Code Playgroud)

我能够在 ip -s mroute 中看到数据包,但是没有发现彼此的设备:

# ip -s mroute
(169.254.10.10, 239.255.255.250) Iif: br2    Oifs: br1
  3 packets, 549 bytes
(169.254.168.11, 239.255.255.250) Iif: br1    Oifs: br2
  12 packets, 2196 bytes
(169.254.168.11, 239.255.255.250) Iif: unresolved
(169.254.10.10, 239.255.255.250) Iif: unresolved
#
Run Code Online (Sandbox Code Playgroud)

来自路由器的 Tcpdump:

# tcpdump -i br2 -vvv port 1900
tcpdump: listening on br2, link-type EN10MB (Ethernet), capture size 262144 bytes
21:29:20.867399 IP (tos 0x0, ttl 4, id 0, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.10.10.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:21.368865 IP (tos 0x0, ttl 4, id 0, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.10.10.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:21.869556 IP (tos 0x0, ttl 4, id 0, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.10.10.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:24.614276 IP (tos 0x50, ttl 3, id 6384, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.168.11.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:25.114268 IP (tos 0x50, ttl 3, id 6393, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.168.11.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:25.614997 IP (tos 0x50, ttl 3, id 6680, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.168.11.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
^C
6 packets captured
6 packets received by filter
0 packets dropped by kernel

# tcpdump -i br1 -vvv port 1900
tcpdump: listening on br1, link-type EN10MB (Ethernet), capture size 262144 bytes
21:29:40.869434 IP (tos 0x50, ttl 3, id 0, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.10.10.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:41.371016 IP (tos 0x50, ttl 3, id 0, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.10.10.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:41.871953 IP (tos 0x50, ttl 3, id 0, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.10.10.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:44.616742 IP (tos 0x0, ttl 4, id 17080, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.168.11.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:45.138486 IP (tos 0x0, ttl 4, id 17334, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.168.11.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
21:29:45.622226 IP (tos 0x0, ttl 4, id 17487, offset 0, flags [DF], proto UDP (17), length 183)
    169.254.168.11.50759 > 239.255.255.250.1900: [udp sum ok] UDP, length 155
^C
6 packets captured
6 packets received by filter
0 packets dropped by kernel
#
Run Code Online (Sandbox Code Playgroud)

命令输出:

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         x.x.x.x         0.0.0.0         UG    0      0        0 erouter0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 br1
169.254.0.0     0.0.0.0         255.255.0.0     U     0      0        0 br2
169.254.168.0   0.0.0.0         255.255.255.0   U     0      0        0 br1
239.255.255.250 0.0.0.0         255.255.255.255 UH    0      0        0 br1
#

# ifconfig br2
br2       Link encap:Ethernet  HWaddr xxxxxxxx
          inet addr:169.254.50.1  Bcast:169.254.255.255  Mask:255.255.0.0
          inet6 addr: fe80::d02d:5dff:fe68:8e60/64 Scope:Link
          UP BROADCAST RUNNING ALLMULTI MULTICAST  MTU:1500  Metric:1
          RX packets:24012 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23477 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:4779091 (4.5 MiB)  TX bytes:5154708 (4.9 MiB)
#

# ifconfig br1
br1       Link encap:Ethernet  HWaddr xxxxxxxx
          inet addr:10.0.0.1  Bcast:10.0.0.255  Mask:255.255.255.0
          inet6 addr: xxxxxxxxxxxxxxxxxxxxxxxxxx/64 Scope:Global
          inet6 addr: fe80::16b7:f8ff:fefe:faf6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:44444 errors:0 dropped:0 overruns:0 frame:0
          TX packets:55860 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:6780562 (6.4 MiB)  TX bytes:11041592 (10.5 MiB)
#
Run Code Online (Sandbox Code Playgroud)

dir*_*rkt 5

网络基础知识:

LAN 网络的基本单位是网。最初的10Base5 以太网使用长(通常是黄色)同轴电缆和吸血鬼抽头,所以一个网段看起来像这样:

... ----------------------------- ...
        |         |         |
     Client 1  Client 2  Client 3
Run Code Online (Sandbox Code Playgroud)

通过构造,一个网段上的每个设备都可以看到该网段上所有设备的所有以太网包,并且只过滤掉它感兴趣的那些。这允许广播(到一个网段上的所有设备)和多播(到某些设备段)。由于这些原因,LAN 段也称为广播域。一个段将被分配一个由网络掩码确定的 IP 地址范围。所以在上面的例子中,段可能有 192.168.1.0/24(即“段名称”有 24 位,每个客户端最后有 8 位),客户端 1 可能是 192.168.1.1,客户端 192.168。 1.2 等

当以太网改为点对点连接而不是吸血鬼抽头时,使用一个交换机来形成一个段:

      +-----------------------+
      |         Switch        |
      +-----------------------+
        |         |         |
     Client 1  Client 2  Client 3
Run Code Online (Sandbox Code Playgroud)

所以从概念上讲,交换机只是将它在一个端口上接收到的数据包发送到所有其他端口。(实际上,有优化)。

因此,连接两个客户端以便它们可以相互发送多播的最简单方法是使用交换机将它们放在同一段中,如上图所示。

如果一台 Linux 计算机有多个以太网端口,则它可以充当交换机,并将它们放在一个网桥中

    +-------------- Linux PC---------------+
    |                                      |
    |              192.168.1.4             |
    |  <------------  br0 ------------>    |
    |    eth0         eth1         eth2    |
    |     |            |            |      |
    +--------------------------------------+
          |            |            |
      Client 1     Client 2     Client 3
     192.168.1.1  192.168.1.2  192.168.1.3
Run Code Online (Sandbox Code Playgroud)

网桥之所以称为网桥,是因为这种结构最初是用来将两个 LAN 网段桥接在一起的,但在这里它就像交换机一样使用。桥接器可以有一个可选的“内部”接口,所以在概念上这与

      +------------------------------------------------+
      |                     Switch                     |
      +------------------------------------------------+
          |            |            |           |
      Client 1     Client 2     Client 3     Linux PC
     192.168.1.1  192.168.1.2  192.168.1.3  192.168.1.4
Run Code Online (Sandbox Code Playgroud)

因此,为了让您的两个客户端在 Linux PC 上相互看到,您使用一个网桥(我不知道您为什么使用两个,或者为什么这应该是一个要求)。

如果您的客户必须位于两个不同的部分(出于组织目的,您没有告诉我们),那么您必须路由(OSI 级别 3)而不是桥接(OSI 级别 2 )。

编写1/proc/sys/net/ipv4/ip_forward(或者在启动你的发行版的配置文件设置为等效)启用路由,ip route可以让你检查和添加路由,如果自动添加的路由是不够的。

这适用于单播流量,对于多播流量,您确实需要类似smcroute.

一个ARP代理是非常特殊的情况下由于某种原因,你无法弥合(例如WLAN 3地址模式和以太网)一cludge,但想桥梁排序的。这通过欺骗 arp 消息向每个网段假装另一个网段上的设备确实在同一网段中,并且路由单播流量。它不适用于广播 (DHCP),也不适用于多播。

如果您在没有告诉我们的特殊情况下使用 arp 代理,那么您可能做错了。如果您在网桥上使用 arp 代理,您几乎肯定做错了(您可以只桥接所有内容),除非您遇到了一些您没有告诉我们的非常疯狂的情况。

所以:

1) 决定是否可以桥接两个客户端(或仅使用交换机)。如果您无法桥接,请更新问题并解释原因。

2)如果无法桥接,请启用IP转发,检查路由并测试是否ping有效。然后就可以设置了smcroute。用ssmping或测试它asmping而不是ping。一旦ssmping/asmping工作,尝试 SSDP 是否被路由,尽管根据定义具有本地范围(我没有尝试)。如果没有,可能会有更多的摆弄。

3)如果您确实必须使用arp代理,请编辑问题并完整而彻底地解释情况,并提供所有详细信息。

编辑

因此,假设在服务器上进行以下设置:

  • eth1 与 10.0.0.1/24
  • 带有 10.0.1.1/24 的 eth2
  • eth1 后面的客户端 1,地址为 10.0.0.2
  • eth2 后面的客户端 2,地址为 10.0.1.2

杀死 arp 代理。

启用转发:

echo "1" | sudo tee /proc/sys/net/ipv4/ip_forward
Run Code Online (Sandbox Code Playgroud)

检查路由ip route,您应该看到到eth1和的路由eth2

在客户端 1 上,执行ping 10.0.0.1,然后ping 10.0.1.1,然后ping 10.0.1.2。检查所有 3 个工作。客户端 2 相同,具有适当的地址。

如果它不起作用,请tcpdump -ni eth1在一个窗口中使用,tcpdump -ni eth2在另一个窗口中使用 ping,然后看看哪里出了问题。

如果有效,请ssmping在两个客户端上安装。sudo smcrouted -n在新窗口中启动服务器,以便您可以看到消息。让我们使用组播组226.1.1.234进行测试。做sudo smcroutectl add eth1 226.1.1.2 eth2ssmpingd在客户端 1asmping -4 10.0.0.2 226.1.1.234上运行,然后在客户端 2 上运行。类似地,ssmpingd在客户端 2 上运行,然后asmping -4 10.0.1.2 226.1.1.234在客户端 1 上。如果它不起作用,则按上述方式进行调试。

最后尝试sudo smcroutectl add eth1 239.255.255.250 eth2测试 UPNP 发现是否有效。我刚刚使用minidlnagupnp-universal-cp使用两个额外的网络命名空间对此进行了测试,它在这里工作正常。

一旦它工作,根据需要设置配置文件。

编辑

RFC3927,并清楚地说

如果目标地址在 169.254/16 前缀 [...] 中,则发送方必须为目标地址进行 ARP,然后将其数据包直接发送到同一物理链路上的目标。

主机不得将带有 IPv4 链路本地目标地址的数据包发送到任何路由器进行转发。

和AFAIK这是在Linux内核中强制执行的,完全使用额外的ARP规则(必须是相同的接口)所以不可能路由169.254.*.*地址。如果我们试图路由它们,我们就必须在整个过程中与 Linux 内核作斗争。也许这是可能的,但我什至不想尝试。这仅适用于单播,甚至不适用于多播。

带有 169.254.*.*、UPNP、Apple Bonjour 等的设备旨在用于同一 LAN 网段。这也适用于所有想要使用它们的设备。这就是来龙去脉。

您有以下选择:

  • 触摸设备并配置静态 IP,或说服它们接受 DHCP。我所有的媒体设备都可以做到这一点。你没有说你有哪些设备,所以我不能帮你。

  • 将一个或两个媒体设备置于某种隧道、VLAN、额外 SSID 或其他任何东西之后,这样您就不必桥接所有内容,但可以将所有需要查看媒体设备的设备保留在一个 LAN 网段中。尽管我多次询问,但您没有解释您的网络设置,因此我无法帮助您找到解决方案。

  • 实现您自己的网络堆栈(在用户空间中,例如 arp-proxy,或者),忽略 RFC 和网络实践并执行您想要的操作。您不仅要传递 ARP,还必须传递广播和多播,因此它已经是自实现的 NIH 桥的大部分内容。

  • 实际上桥接一切,但是ebtables根据您的管理问题使用etc. 来强制分离。尽管我多次询问,但您没有解释您的行政问题,所以我无法帮助您。

如果这些选项都不适合您,那么您想要的东西是不可能的。时期。