Сетевой стек OS X игнорирует запросы членства IGMP

У нас есть удаленный сайт, где Mac не отвечает на запросы о членстве в IGMP , но компьютеры Windows отвечают . Следовательно, примерно через 10 минут сетевой коммутатор с поддержкой IGMP отключает многоадресный поток на компьютеры Mac.

Вот снимок экрана Wireshark, показывающий проблему:

Wireshark IGMP packet capture

Первый пакет - это приложение, запрашивающее, чтобы сеть начала разрешать пакеты IGMP от 239.255.20.1 до Mac. Затем вы видите, что примерно каждые 125 секунд после этого сетевой коммутатор, настроенный как запросчик IGMP (10.1.254.254), спрашивает, интересует ли нас этот поток. Обратите внимание на явное отсутствие ответа.

Вот что происходит здесь, в локальной сети, для сравнения:

good IGMP packet capture

Здесь примерно каждые 95 секунд запросчик IGMP (172.20.0.2) спрашивает, нужен ли нам этот поток, и Рассматриваемый Mac (172.20.0.144) говорит: «Да, продолжайте отправлять его».

Брандмауэр отключен на проблемных Mac в графическом интерфейсе пользователя, и я проверил это в командной строке:

$ /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
Firewall is disabled. (State = 0)
$ /usr/libexec/ApplicationFirewall/socketfilterfw --getblockall
Block all DISABLED! 
$ /usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode
Stealth mode disabled 
$ /usr/libexec/ApplicationFirewall/socketfilterfw --getappblocked /Applications/mumblemutter.app/...
The application is not part of the firewall 

Приложение не имеет значения, так как стек обрабатывает запросы IGMP после того, как группа была присоединена.

Проблема На компьютерах Mac работает 10.11.5, но я не могу поверить, что проблема будет решена путем обновления до последней версии, поскольку это будет означать, что ОС на основе BSD исправляет серьезные ошибки в своем сетевом стеке в 2016 году. Возможно, но крайне низкая вероятность.

2
задан 10 December 2016 в 02:00
2 ответа

Проблема показана в первом захвате пакета, где вы заметите, что пакет присоединения к группе IGMP является пакетом IGMPv2, но все ответы от запрашивающего IGMP - v3.

Это может показаться прекрасным, поскольку macOS уже очень давно поддерживает IGMPv3, но если вы углубитесь в реализацию IGMP в ядре Darwin с открытым исходным кодом , в 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...

Это означает, что macOS подчиняется спецификации IGMPv3 и переводит любой сетевой интерфейс, на котором он видел пакеты IGMPv2, в «режим совместимости», что означает, что он не будет подтверждать Пакеты IGMPv3 не говорят IGMPv3 на этом сетевом интерфейсе. В терминах приведенного выше кода интерфейс помечается как igi_version = 2 , поэтому мы пройдем этот тест и проигнорируем запрос членства в группе v3, исходя из теории, что говорить на v3 в этой сети небезопасно, чтобы устройства v2 не могли понять, что происходит.

Я вижу три работоспособных решения:

  1. Заставьте тех, кто отвечает за сеть, перенастроить свои коммутаторы для отправки обратно запросов IGMPv2 клиентам, которые запросили присоединение к группе IGMPv2.

  2. Полностью отключите поддержку IGMPv3 в сетевых коммутаторах с поддержкой IGMP, чтобы они отправляли только запросы о членстве IGMPv2.

  3. Отслеживайте сеть на предмет пакетов IGMPv2, находите их источник и исправляйте, обновляйте или удаляйте их. Если сеть не может быть настроена на передачу v3 сквозной передачи, выберите №1 или №2.

Это не то, что вы можете исправить с помощью изменения кода приложения. Параметр IP_ADD_MEMBERSHIP от до setsockopt () не включает номер версии, поэтому приложение не может требовать IGMPv3. Это решение остается за стеком.

Хотя вполне возможно, что существует параметр ОС, который повлияет на это, это может иметь место только в том случае, если реализация IGMP в macOS отличается от того, что мы видим в igmp.c , ссылка на которую приведена выше.

Если вы обнюхаете сеть на наличие IGMP в окне Windows, вы увидите, что она отвечает на запросы членства IGMPv3 с ответами v3, несмотря на наличие v2 в сети. Следовательно, это нарушает RFC; в то время как некоторые сетевые администраторы, которые скажут: «Ну, это работает, не так ли?», правильный ответ должен заключаться в том, что, поскольку вы не можете заставить macOS игнорировать RFC, остается решение исправить сеть.

3
ответ дан 3 December 2019 в 10:36

большинство сетей. Почему? Потому что некоторые очень распространенные реализации mDNS (например, iPhone) часто и необоснованно покидают и присоединяются к 224.0.0.251 (группа mDNS) быстрее, чем время ожидания версии IGMP. Если хотя бы одно устройство отправляет IGMPv2-запрос на 224.0.0.251, запросчик выдаст специфичный для группы запрос ICMPv2 для 224.0.0.251, чтобы узнать, остался ли кто-нибудь. Все остальные в этой группе (а это большинство хостов в наши дни) увидят это и переключат интерфейс на v2, не позволяя MacOS отвечать на запросы IGMPv3.

Все это несмотря на то, что спецификация IGMP говорит, что хосты не должны явно покидать и присоединяться к блоку 224.0.0.0/24, а отслеживающие коммутаторы должны всегда его пересылать. И удачи вам в том, чтобы Apple исправила эту проблему с необоснованным выходом/присоединением на миллионах устройств.

Вы можете обойти это, перезагрузив все свои устройства iOS после переключения querier на IGMPv3 и подождав. Но если какое-либо устройство когда-либо выдаст сообщение IGMPv2, многоадресная рассылка MacOS снова прервется.

Это очевидная ошибка, за которую нельзя винить ничего, кроме того, что MacOS игнорирует сообщения IGMPv3, когда считает, что интерфейс имеет версию 2.

1
ответ дан 6 May 2021 в 18:47

Теги

Похожие вопросы