Опубликован: 30.07.2013 | Уровень: для всех | Доступ: свободно
Лекция 7:

Приложения протокола розыска соседей

Автоматическая настройка IPv6

Выбор идентификатора интерфейса и обнаружение адресных конфликтов

Давным-давно существовал протокол IPX, в чем-то похожий на IPv6. 4 Точнее, это IPv6 немного похож на IPX, потому что позаимствовал его хорошие стороны. Адрес IPX тоже состоял из двух частей фиксированной длины, отвечающих каналу и интерфейсу. Интересной особенностью адреса IPX было то, что идентификатор интерфейса всегда совпадал с адресом MAC 48 того же интерфейса. Благодаря этому, упрощались два аспекта работы сети. Во-первых, розыск соседей становился тривиальной операцией: достаточно было выделить в адресе IPX идентификатор интерфейса, чтобы получить канальный адрес искомого соседа. Во-вторых, при настройке сети IPX не приходилось назначать каждому интерфейсу уникальный адрес, а достаточно было назначить идентификатор (префикс) всему каналу, потому что об уникальности адресов MAC — глобальной! — уже позаботился IEEE. Платой за эту простоту была жесткая связь между канальными и сетевыми адресами. Так, например, при смене сетевого адаптера у узла менялся адрес IPX.

Если адаптер позволяет программировать свой адрес MAC, то можно было бы сохранить старый адрес, однако это означало бы переход к самостоятельному управлению адресами MAC и — прощай, простота IPX! В действительности, реализации даже позволяли выбирать адрес IPX на свой вкус, но это вызывало программную смену связанного с ним адреса MAC.

Конечно, еще одно очевидное ограничение IPX состояло в том, что он мог работать только поверх каналов с адресацией MAC 48 или совместимой.

К счастью, ограничения на идентификатор интерфейса IPv6 гораздо мягче, чем это было в IPX. Единственное условие, на котором мы настаиваем, — это чтобы идентификатор интерфейса в индивидуальном адресе IPv65 Кроме особых адресов с двоичным префиксом 000 был длиной 64 бита и отвечал формату модифицированного EUI 64. В §2.7 мы даже пошли на отклонение от IEEE EUI 64, чтобы с адресами, назначенными вручную, было удобнее работать. Благодаря этой модификации, идентификатор интерфейса вполне может быть небольшим числом: 1, 2, 3 и т.д. Такая политика назначения адресов необходима, когда речь идет, например, о серверах, которым требуется постоянный и мало-мальски удобный сетевой адрес.

Чаще всего серверу достаточно постоянного имени, которое зарегистрировано в DNS. Тем не менее, в некоторых случаях нужен именно постоянный адрес IP, который будет зафиксирован в настройках клиентов. Например, это касается серверов DNS. Ведь узнать из DNS адрес сервера DNS — это все равно, что вытащить себя из болота за собственные волосы.

Между тем, технология TCP/IP находит применение не только в традиционных вычислительных сетях. Не исключено, что скоро все интеллектуальные бытовые приборы и личные электронные устройства будут общаться друг с другом по IPv6, и движение в эту сторону заметно уже сегодня. Управление такими сетями требует нетрадиционного подхода, потому что у рядового пользователя не будет ни желания, ни навыков, чтобы вручную назначить адрес IPv6 каждому из окружающих его "маленьких цифровых друзей". Но даже в традиционных сетях далеко не все узлы требуют адресов, назначенных вручную. Например, такие адреса не нужны большинству рабочих станций и терминалов. Для них, равно как и для персональных электронных устройств, будет достаточно предсказуемой автоматической настройки адресов.

Предсказуемость здесь нужна, чтобы облегчить отладку сети, если уж до этого дойдет дело.

Итак, мы видим, что нам пора заняться процедурой автоматической настройки индивидуальных адресов в IPv6. На какие части можно разбить ее? Прежде всего, узел должен найти для каждого из активных сетевых интерфейсов один или несколько адресов IPv6. Чтобы составить хотя бы один адрес IPv6, узел должен откуда-то узнать значения его фундаментальных частей — префикса подсети и идентификатора интерфейса. Посмотрим на эти части по отдельности, начав с последней.

Если у интерфейса, подлежащего настройке, есть уникальный канальный адрес, такой как MAC 48 или EUI 64, то это отличный кандидат на роль идентификатора интерфейса. Все, что требуется в этом случае — преобразовать канальный адрес к формату "модифицированный EUI 64" по общепринятой методике, которую мы "разработали" в §2.7. Эта часть задачи не представляет трудности.

Строго говоря, методику преобразования канального адреса в идентификатор интерфейса должен приводить документ, посвященный передаче IPv6 в данной канальной среде. Например, для Ethernet это [RFC 2464]. Тем не менее, случаи EUI 64 и MAC 48 также рассмотрены в центральном документе "Адресная архитектура IPv6" потому что эти виды идентификаторов популярны и применяются в самых разных технологиях канального уровня [Приложение A, RFC 4291]. Там же приводятся рекомендации, что делать, если у интерфейса нет уникального канального адреса.

Мы уже встретили пример, когда, не имея готовых адресов, канальный протокол согласует уникальные идентификаторы интерфейса для IPv6. Это, конечно же, IPV6CP в рамках PPP — см. §4.1.2.

Как выбрать префикс подсети, зависит от области адреса. Если надо составить внутриканальный адрес, то искомый префикс заранее известен: FE80::/64. Благодаря этому, узел может самостоятельно выбрать внутриканальные адреса для своих активных интерфейсов, не пользуясь никакими дополнительными сведениями.

Хотя для внутриканальных адресов был зарезервирован префикс FE80::/10, на интерфейсах мы встречаем только FE80::/64 в согласии с тем правилом, что длина префикса подсети IPv6 составляет 64 бита. Но, строго говоря, внутриканальный префикс подсети может зависеть от типа канала и уточняется соответствующим документом о канальной инкапсуляции IPv6.

Если же область адреса больше, чем канал, то префикс подсети выбирает и сообщает узлу администратор сети. Здесь наш путь снова раздваивается: или администратор вручную заносит префикс подсети в настройки узла, или же префикс настраивается централизованно, а узел узнает его автоматически, следуя некому протоколу. Такой протокол вполне сможет работать поверх IPv6, так как узел уже выбрал себе внутриканальные адреса.

Искушенный читатель спросит, почему бы не выбрать этим протоколом DHCP (точнее, его вариант для IPv6 — DHCPv6). Сейчас мы убедимся, что в NDP уже заложено достаточно возможностей, чтобы обойтись без еще одного протокола, по крайней мере, для распространения самых необходимых настроек.

Мы посвятим §5.4.2 вопросу о точном механизме автоматической настройки префикса подсети, а сейчас давайте переключимся на следующую проблему. Предположим, что узел уже автоматически составил адрес IPv6. Например, это может быть внутриканальный адрес, префикс которого известен заранее: FE80::/64. В отличие от IPX, где идентификатор интерфейса обязан совпадать с его адресом MAC, в IPv6 такого требования нет. Поэтому нельзя исключить ситуацию, когда автоматически выбранный идентификатор интерфейса уже занят другим узлом-соседом.

Скажем, узел собирается назначить внутриканальный адрес интерфейсу Ethernet, адрес MAC которого 00-01-02-03-04-05. Согласно правилам "модифицированного EUI 64", ему отвечает идентификатор интерфейса 02-01-02-FF-FE-03-04-05. Сцепляя его с внутриканальным префиксом, узел получает адрес FE80::0201:02FF:FE03:0405. Несмотря на уникальность исходного адреса MAC, тот же самый адрес IPv6 уже может быть назначен другому соседу, например, вручную. Таким образом, было бы опрометчиво назначить автоматически составленный адрес IPv6, не проверив его на уникальность в пределах канала.

Строго говоря, рассмотренный в примере конфликт адресов возникает из-за нарушения формата "модифицированный EUI 64": администратор не должен назначать "с потолка" идентификаторы интерфейсов, у которых установлен бит U/L. Тем не менее, на практике случается всякое. Даже производители сетевых адаптеров не застрахованы от ошибок, и у разных адаптеров могут совпасть адреса MAC. Подобные проблемы желательно выявлять до того, как они навредят работе сети.

Непроверенный адрес мы обозначим как пробный ( tentative). Требуется ли новый протокол, чтобы проверить такой адрес на уникальность? На самом деле, нет — мы можем обойтись протоколом ND из §5.1, слегка доработав его. В общих чертах схема ясна: узел посылает запрос NS касательно пробного адреса и ожидает, не ответит ли кто-то из соседей объявлением NA; если такой ответ поступит, то пробный адрес, очевидно, уже занят. Однако этот случай применения ND обладает рядом отличительных особенностей, которые выделяют его в под-протокол с названием DAD ( duplicate address detection, выявление дубликатных адресов) [§5.4 RFC 4862].

Как мы знаем, в IPv4 для той же цели служил добровольный запрос ARP. Хотя практика IPv4 уже давно держит этот механизм в своем арсенале, формальная процедура была опубликована относительно недавно под названием " обнаружение конфликтов адресов IPv4" (IPv4 Address Conflict Detection, ACD) [RFC 5227].

Первое затруднение состоит в том, что участие в ND, каким мы его знаем, требует уже назначенного индивидуального адреса. Ведь у пакета ND должен быть определенный адрес источника, не так ли? В то же время, узел не может назначить себе адрес, не проверив его по DAD. Это рождает "проблему курицы и яйца", для решения которой DAD должен работать, даже когда узел-инициатор вообще не обладает индивидуальными адресами. Пусть узел, выполняющий DAD, всегда посылает запрос NS с неопределенным адресом источника IPv6 :: [§5.4.2 RFC 4862] и без опции "канальный адрес источника" [§4.3 RFC 4861]. Тогда неопределенный адрес источника выделит NS для DAD среди обычных вызовов NS, передаваемых с целью разрешения адреса или NUD.

Но как узел-инициатор получит возможный ответ NA? Ведь пакет IPv6 нельзя направить по неопределенному адресу! Чтобы обойти и эту преграду, пусть отвечающий узел направляет ответ NA по групповому адресу "все узлы канала", FF02::1, если вызов NS пришел с неопределенного адреса. Следовательно, узел-инициатор должен вступить в эту группу перед началом DAD [§5.4.2 RFC 4862].

Как следствие, протокол управления группами IPv6 MLD должен работать, когда на интерфейсе еще нет индивидуальных адресов. Возьмем себе это на заметку, чтобы вспомнить позже, когда дело дойдет до MLD (§6.4).

Благодаря тому, что запрос NS в рамках DAD не использует опцию "канальный адрес источника" и ответ на него подлинно групповой, механизм DAD устойчив к конфликтам канальных адресов. Если бы мы "оптимизировали" DAD так, чтобы ответ NA шел по индивидуальному адресу MAC, коммутируемая локальная сеть направила бы его одному случайному владельцу этого адреса MAC, и DAD с большой вероятностью дал бы сбой. А ведь конфликт канальных адресов приведет и к конфликту адресов IPv6, составленных на их основе посредством "модифицированного EUI 64".

Отвечающий узел шлет объявление NA в ответ на запрос NS, однако в случае DAD это объявление направляется всем узлам канала, а не только узлу-инициатору DAD. Такое объявление NA получат и те узлы, которые о нем не просили. Поэтому, отвечая на вызов DAD, то есть вызов NS с неопределенного адреса, узел должен сбросить флаг S (S = 0). Вот еще одна особенность применения ND для DAD.

Дополнительное затруднение возникает, когда два узла одновременно пытаются проверить один и тот же незанятый адрес. Если следовать простейшей схеме, то ни один из узлов не получит объявления NA, и оба узла решат, что пробным адресом можно пользоваться. В результате возникнет конфликт адресов. Чтобы избежать такого исхода, узел-инициатор должен обращать внимание не только на объявления NA, но и на вызовы NS. Если узел получит чужой вызов NS касательно пробного адреса, исходящий с неопределенного адреса, то значит, еще один узел пытается проверить тот же адрес с помощью DAD, и назревает конфликт адресов [§5.4.3 RFC 4862]. Если же чужой вызов NS касательно пробного адреса поступит с определенного адреса, то это обычный розыск соседа, и его следует игнорировать, потому что право нашего узла на пробный адрес еще не доказано. В свою очередь, чтобы принимать интересующие его вызовы NS, узел-инициатор DAD должен заранее вступить в группу искомого узла, отвечающую пробному адресу [§5.4.2 RFC 4862].

Вообще говоря, узел может получать и свои собственные групповые сообщения. Так как в данном случае адрес источника IPv6 неопределенный, источник вызова DAD надо идентифицировать, если это возможно, по его канальному адресу [Приложение A RFC 4862]. Альтернативный подход, если локальный уровень IPv6 уверен, что получает собственные вызовы DAD, — это подсчитать разность между числом посланных и принятых сообщений [там же]; очевидно, в отсутствие конфликта она должна оставаться нулевой. В любом случае, верная обработка этой ситуации зависит от точных свойств канала и интерфейса в него.

Интересная идея, подсказанная нам редактором, состоит вот в чем: узел мог бы отличать собственные групповые вызовы NS от чужих, если бы он включал в свои вызовы особую опцию ND, содержащую достоверный "отпечаток пальцев" узла, например, подпись HMAC.

Узел-владелец пробного адреса, отвечая на вызов DAD, мог бы послать объявление NA более узкой группе искомого узла, а не группе "все узлы канала". Ведь узел-инициатор DAD все равно обязан состоять в обеих группах. Мы не видим препятствий для такого подхода, однако стандарты о нем не говорят. По-видимому, мысль разработчиков IPv6 шла по тому же пути, что и наша: сначала они решали проблему доставки объявления NA инициатору DAD, а только потом озаботились проблемой одновременных сеансов DAD. Затем надо было соотнести полученные решения между собой и оптимизировать первое из них в свете второго, но до этого, видимо, просто не дошли руки .6 См. обсуждение "why is NA to DAD NS sent to all-nodes address?" в списке рассылки IETF IPV6: http://www.ietf.org/mail-archive/web/ipv6/current/msg06287.html зеркало: http://www.mail-archive.com/ipv6@ietf.org/msg06101.html

Сергей Субботин
Сергей Субботин

"Теоретически канал с адресацией EUI 64 может соединить порядка 2^63 "

запись вида 2^63  не понятна и отнимает время на попытку ее осмыслить.

ее можно заменить например на записи вида  264  или 1,8 * 1019

 

Павел Афиногенов
Павел Афиногенов

Курс IPv6, в тексте имеются ссылки на параграфы. Разбиения курса на параграфы нет.

Сергей Смоляр
Сергей Смоляр
Россия, Ялта