Назад | Перейти на главную страницу

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

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

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

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

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

Здесь примерно каждые 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 году. Возможно, но крайне низкая вероятность.

Проблема показана в первом захвате пакета, где вы заметите, что пакет присоединения к группе 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, остается решение исправить сеть.