OS X 网络堆栈忽略 IGMP 成员资格查询

War*_*ung 2 networking multicast streaming igmp

我们有一个远程站点,其中 Mac 不响应IGMP 成员资格查询,但 Windows 机器确实响应。因此,大约 10 分钟后,支持 IGMP 的网络交换机会切断发送至 Mac 的多播流。

这是显示问题的 Wireshark 屏幕截图:

Wireshark IGMP 数据包捕获

第一个数据包是应用程序请求网络开始允许从 239.255.20.1 到 Mac 的 IGMP 数据包。然后您会看到,此后大约每隔 125 秒,配置为 IGMP 查询器 (10.1.254.254) 的网络交换机就会询问我们是否仍然对该流感兴趣。请注意明显缺乏响应。

以下是本地网络上发生的情况,以供比较:

良好的 IGMP 数据包捕获

在这里,大约每 95 秒,IGMP 查询器 (172.20.0.2) 就会询问我们是否仍然需要该流,而相关的 Mac (172.20.0.144) 会说:“是的,继续发送它。”

有问题的 Mac 上的防火墙在 GUI 中已关闭,我已在命令行中对其进行了验证:

$ /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
防火墙已禁用。(状态 = 0)
$ /usr/libexec/ApplicationFirewall/socketfilterfw --getblockall
阻止所有禁用!
$ /usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode
隐身模式已禁用
$ /usr/libexec/ApplicationFirewall/socketfilterfw --getappblocked /Applications/mumblemutter.app/...
该应用程序不是防火墙的一部分

应用程序并不重要,因为堆栈在加入组后处理 IGMP 查询。

问题 Mac 运行的是 10.11.5,但我无法相信通过升级到绝对最新版本可以解决该问题,因为这意味着基于 BSD 的操作系统正在 2016 年修复其网络堆栈中的严重错误。有可能,但极其严重低概率。

War*_*ung 5

问题出现在第一个数据包捕获中,您会注意到 IGMP 组加入数据包是 IGMPv2 数据包,但来自 IGMP 查询器的响应都是 v3。

这看起来似乎没问题,因为 macOS 已经支持 IGMPv3 很长时间了,但是如果您深入研究Darwin 开源内核中的 IGMP 实现,在 中igmp_input_v3_query(),您会发现这段启发性的代码:

/*
 * Discard the v3 query if we're in Compatibility Mode.
 * The RFC is not obviously worded that hosts need to stay in
 * compatibility mode until the Old Version Querier Present
 * timer expires.
 */
if (igi->igi_version != IGMP_VERSION_3) {
    ...etc...
Run Code Online (Sandbox Code Playgroud)

这意味着 macOS 遵守IGMPv3 规范,并将看到 IGMPv2 数据包的任何网络接口置于“兼容模式”,这意味着它既不会在该网络接口上确认 IGMPv3 数据包,也不会使用 IGMPv3。就上面的代码而言,它将接口标记为igi_version = 2,因此我们将进行此测试并忽略 v3 组成员资格查询,因为理论上在此网络上使用 v3 是不安全的,以免 v2 设备无法理解是什么正在进行中。

我看到了三种可行的补救措施:

  1. 让网络负责人重新配置其交换机,以将 IGMPv2 查询发送回请求加入 IGMPv2 组的客户端。

  2. 完全关闭 IGMP 感知网络交换机中的 IGMPv3 支持,以便它们仅发送 IGMPv2 成员资格查询。

  3. 监视网络中的 IGMPv2 数据包,查找其来源,并修复、升级或删除它们。如果网络无法直通 v3,请选择 #1 或 #2。

这不是您可以通过更改应用程序代码来解决的问题。该IP_ADD_MEMBERSHIP选项setsockopt()包含版本号,因此应用程序无法请求 IGMPv3。该决定由堆栈决定。

虽然操作系统设置可能会影响这一点,但只有当 macOS IGMP 实现与我们在igmp.c上面链接中看到的不同时才会出现这种情况。

如果您在 Windows 机器上嗅探网络中的 IGMP,您将看到它使用 v3 响应来响应 IGMPv3 成员资格查询,尽管网络上存在 v2。因此它违反了 RFC;虽然一些网络管理员会说,“好吧,它有效,不是吗?”,正确的反应一定是,因为你不能强迫 macOS 也忽略 RFC,所以解决方案仍然是修复网络。