NetLab Academy

Сетевые лаборатории в браузере

Войти Начать бесплатно

Теория: IPv6: адресация и соседи

Как устроен 128-битный адрес и почему его не жалко, откуда на интерфейсе берётся link-local, зачем /64 неприкосновенен, чем NDP отличается от ARP и как хост получает адрес без DHCP. Прочитайте материал, а затем пройдите тест — следующий пункт курса откроется после верных ответов.

Почему пришлось менять адрес

Адресов IPv4 четыре с небольшим миллиарда, и свободных пулов у регистраторов не осталось: RIPE раздал последний блок в 2019 году. Дальше адреса только перепродают.

Жить с этим научились через NAT: за одним публичным адресом прячется вся организация. Работает — но ценой того, что соединение можно установить только изнутри наружу. Всё, что требует входящего соединения, приходится подпирать костылями: проброс портов, STUN и TURN для звонков, промежуточные серверы для всего остального. Каждый такой костыль стоит денег и ломается по-своему.

IPv6 отвечает на это прямо: адрес длиной 128 бит вместо 32. Разница не в четыре раза, а в 296 раз — числа такого порядка не с чем сравнивать. Практический смысл один: адресов больше не жалко. Их хватает, чтобы каждому устройству дать настоящий адрес, а каждой сети — заведомо избыточный кусок, и не считать их до конца существования интернета.

Как выглядит адрес и как его сокращают

128 бит записывают как восемь групп по четыре шестнадцатеричные цифры, через двоеточие:

2001:0db8:0000:0000:0000:0000:0000:0001
Полная запись нечитаема, поэтому её сокращают по двум правилам:

Ведущие нули в группе убираются: 0db8db8, 00000.
Одна подряд идущая цепочка нулевых групп схлопывается в ::. Именно одна: если цепочек две, схлопнуть можно только какую-то одну, иначе адрес нельзя будет восстановить однозначно.

2001:0db8:0000:0000:0000:0000:0000:0001
2001:db8:0:0:0:0:0:1        # убрали ведущие нули
2001:db8::1                 # схлопнули цепочку нулей
Регистр не важен, но принято писать строчными.

Маска пишется только префиксом: 2001:db8::1/64. Записи вида 255.255.255.0 в IPv6 нет вовсе — и это заметно упрощает жизнь.

В адресной строке браузера адрес берут в квадратные скобки, иначе двоеточие спутается с номером порта: http://[2001:db8::1]:8080/.
128 бит в восьми группах — и два правила, которые делают их читаемыми
Маска у такого адреса пишется только префиксом: /64. Записи вида 255.255.255.0 в IPv6 нет вовсе. А в адресной строке браузера адрес берут в квадратные скобки, иначе двоеточие спутается с номером порта.

Три вида адресов, и ни одного широковещательного

У интерфейса в IPv6 адресов всегда несколько — это нормальное состояние, а не ошибка настройки.

Global unicast — глобально маршрутизируемый, аналог белого адреса IPv4. Выделены из 2000::/3, то есть всё, что начинается на 2 или 3. Для примеров и документации зарезервирован 2001:db8::/32 — он не маршрутизируется в интернете, и именно его вы увидите во всех учебниках, включая этот.
Link-localfe80::/10, живёт только в пределах одного линка и появляется на интерфейсе сам, без всякой настройки. Через него работают NDP, RA и соседства протоколов маршрутизации.
Unique localfc00::/7, на практике fd00::/8: аналог «серых» адресов для внутренних сетей. Внутри префикса полагается взять случайный 40-битный идентификатор, чтобы при слиянии двух сетей адреса не совпали.

И отдельно — multicast, ff00::/8. Широковещания в IPv6 нет вообще. Всё, что в IPv4 рассылалось всем подряд, здесь адресовано конкретной группе: ff02::1 — все узлы линка, ff02::2 — все роутеры линка, ff02::5 и ff02::6 — роутеры OSPFv3. Сетевая карта, которой группа неинтересна, отбрасывает кадр на аппаратном уровне и процессор не будит.

Link-local: адрес, без которого ничего не работает

Самое непривычное для человека из IPv4: link-local-адрес есть на каждом включённом интерфейсе всегда, даже если никто ничего не настраивал. Роутер поднял порт — на нём уже есть fe80::….

На этом адресе держится почти вся служебная жизнь IPv6:
• соседи ищут друг друга через NDP — с link-local;
• роутер рассылает объявления RA — с link-local;
маршрут по умолчанию у хоста указывает на link-local роутера, а не на его глобальный адрес;
• соседства OSPFv3 и next-hop внутри линка — тоже link-local.

Отсюда практическое следствие, на котором спотыкаются все: адрес fe80::1 может одновременно быть у десятка соседей на разных интерфейсах, и сам по себе он не уникален. Поэтому при обращении к нему обязательно указывают интерфейс через знак процента:

ping6 fe80::1%eth1
ssh [fe80::1%eth0]
Забыли %eth1 — получите «invalid argument» и полчаса недоумения.

Как устроен глобальный адрес: почему /64 неприкосновенен

Глобальный адрес делится на три части:

2001:0db8:1234 : 5678 : 0000:0000:0000:0001
└─── префикс сети ───┘ └─ подсеть ─┘ └── идентификатор узла ──┘
Провайдер выдаёт организации /48 (реже /56), из него нарезаются подсети по /64, а последние 64 бита — под адреса узлов.

Первая реакция человека, привыкшего к IPv4: «/64 на подсеть из трёх серверов — это расточительство, возьму /112». Так делать не надо. Длина /64 зашита в механизмы протокола: на ней держатся автонастройка адреса, формирование идентификатора из MAC и адрес solicited-node. Подсеть длиннее /64 ломает SLAAC, и хосты в ней просто не получат адрес сами.

Считать при этом стало проще, а не сложнее: из /48 нарезается 65 536 подсетей /64, и границы всегда проходят по целым группам адреса — никакой арифметики с масками посередине байта. Экономить здесь нечего и незачем.

Откуда берётся вторая половина адреса

Идентификатор узла (последние 64 бита) может появиться тремя способами.

EUI-64 — вычисляется из MAC-адреса: MAC делится пополам, в середину вставляется ff:fe, а седьмой бит первого байта инвертируется.
MAC     00:1a:2b:3c:4d:5e
         ↓ вставили ff:fe в середину
        00:1a:2b:ff:fe:3c:4d:5e
         ↓ инвертировали 7-й бит первого байта (00 → 02)
EUI-64  021a:2bff:fe3c:4d5e
Способ прозрачный, но у него есть неприятное свойство: MAC устройства оказывается вписан в адрес и ездит с ним по всему интернету. Сменили сеть — префикс другой, а вторая половина та же, и по ней устройство узнаётся.

Приватные адреса (RFC 4941) решают это: вторая половина выбирается случайно и регулярно меняется. Современные ОС по умолчанию делают именно так, а EUI-64 остаётся для оборудования.

Заданный руками — обычная практика для серверов и роутеров: 2001:db8:1::1 куда приятнее в конфигурации и в голове, чем случайные шестнадцать цифр.

NDP вместо ARP

ARP в IPv6 нет. Его работу выполняет NDP (Neighbor Discovery Protocol), и он живёт не поверх Ethernet, а внутри ICMPv6 — то есть на третьем уровне. Отсюда следствие, которое стоит запомнить сразу: заблокировали ICMPv6 «на всякий случай» — сеть не работает вообще. Это не диагностика, которую можно выключить, это несущая конструкция.

Четыре сообщения, которые надо знать:
NS (Neighbor Solicitation) — «кто держит этот адрес?». Аналог ARP-запроса.
NA (Neighbor Advertisement) — ответ «я, вот мой MAC».
RS (Router Solicitation) — «роутеры, отзовитесь».
RA (Router Advertisement) — «я роутер, вот префикс сети и вот я как шлюз».

Главное отличие от ARP — адресация запроса. ARP кричал на всю сеть, и его слышали все. NS отправляется на solicited-node multicast: адрес ff02::1:ff плюс последние 24 бита искомого адреса. В такую группу входит обычно один узел — тот самый. Остальные карту даже не поднимут.

Заодно NDP делает то, чего в IPv4 не было: DAD (Duplicate Address Detection). Прежде чем начать пользоваться адресом, узел спрашивает, не занят ли он. Ответили — адрес помечается как дубликат и не используется. Конфликт адресов в IPv6 обнаруживается сам, а не по жалобам пользователей.

SLAAC: адрес без DHCP

Роутер раз в несколько секунд рассылает RA на ff02::1, а появившийся в сети хост может не ждать и спросить сам, послав RS. В объявлении лежит префикс сети, срок его жизни и признак «я шлюз».

Дальше хост собирает адрес сам: берёт префикс из RA, приписывает к нему свою половину и проверяет через DAD, что адрес свободен. Ни сервера, ни аренды, ни базы выданных адресов — это и есть SLAAC, автонастройка без сохранения состояния.

Два флага в RA говорят хосту, нужен ли ему вдобавок DHCPv6:
M (managed) — «адрес бери у DHCPv6-сервера»;
O (other) — «адрес собери сам, но за DNS сходи в DHCPv6».

И отдельно то, что ломает больше всего настроек: шлюз по умолчанию приходит только из RA. В DHCPv6 опции «default gateway» не существует — её там нет вовсе, ни в одной реализации. Выключили RA и понадеялись на DHCPv6 — хосты получат адрес и никуда не смогут выйти.

Dual-stack: два стека в одной сети

Переход на IPv6 нигде не делался разом. Рабочая схема — dual-stack: на интерфейсе живут оба адреса, у узла работают оба стека, и каждое соединение идёт по тому протоколу, который доступен обоим сторонам.

Выбор делает клиент по ответу DNS: пришла запись AAAA — пробует IPv6, пришла только A — идёт по IPv4. Современные браузеры и библиотеки используют Happy Eyeballs: начинают оба соединения почти одновременно и берут то, которое установилось первым. Пользователь не замечает ничего, даже если IPv6 в сети настроен наполовину.

Это удобно и это же главная ловушка эксплуатации: сломанный IPv6 долго остаётся незамеченным. Трафик тихо уходит на IPv4, всё «работает», а половина настройки не проверена никем. Поэтому dual-stack проверяют явно и по отдельности — принудительно прося каждый протокол: ping -4 и ping6, curl -4 и curl -6.

Что здесь ломается

Заблокировали ICMPv6. Классика, перенесённая из привычек IPv4. Без ICMPv6 не работают NDP (соседи не находятся), RA (нет адреса и шлюза) и определение MTU пути — соединения устанавливаются и виснут на первом крупном пакете.

Подсеть длиннее /64. Адреса вроде бы назначаются, а SLAAC не работает: хосты не получают адрес и молчат.

Понадеялись на DHCPv6 без RA. Адрес есть, шлюза нет. Шлюз приходит только из объявления роутера.

Забыли %eth1 у link-local. Пинг до fe80::1 без указания интерфейса не проходит и не может пройти: система не знает, в какой линк отправлять.

Не включён форвардинг. Роутер отвечает на свои адреса, но чужие пакеты не пересылает. По умолчанию стоит no ipv6 forwarding — это ровно оно.

Файрвол настроен только для IPv4. Правила есть, а трафик ходит вторым стеком мимо них. Самая тихая и самая опасная из ошибок: сеть выглядит защищённой ровно до первой проверки.

Мониторинг смотрит только на IPv4. Половина сети не наблюдается, и об аварии узнают от пользователей.

Как проверять

ip -6 addr show — адреса интерфейса. Смотреть надо на все сразу: link-local должен быть всегда, глобальный — если настроен. Пометка tentative означает, что идёт DAD; dadfailed — что адрес занят кем-то ещё.

ip -6 route — таблица маршрутизации. Маршрут по умолчанию должен указывать на link-local роутера и на конкретный интерфейс.

ip -6 neigh — таблица соседей, аналог arp -a. Состояние REACHABLE — сосед отвечает, STALE — запись есть, но давно не подтверждалась, FAILED — не отвечает.

ping6 ff02::1%eth1 — отзовутся все узлы линка. Быстрый способ увидеть, кто вообще есть в сегменте, не зная ни одного адреса.

ping6 ff02::2%eth1 — то же для роутеров: не отвечает никто, значит шлюза в сегменте нет.

show ipv6 interface eth1 — адреса, состояние RA, интервалы. Здесь видно, рассылает ли роутер объявления вообще.

Команды — шпаргалка

# адресация на роутере
ipv6 forwarding                        # разрешить пересылку: без неё роутер
                                       #   работает как обычный хост
interface eth1
 ipv6 address 2001:db8:12::1/64        # адрес и длина префикса. Для IPv6 /64
                                       #   на сегмент — практически всегда норма

# объявления роутера: по умолчанию они НЕ рассылаются
interface eth3
 ipv6 address 2001:db8:11::1/64
 no ipv6 nd suppress-ra                # приставка no снимает подавление, то есть
                                       #   ВКЛЮЧАЕТ рассылку Router Advertisement
 ipv6 nd prefix 2001:db8:11::/64       # какой префикс объявлять хостам
 ipv6 nd ra-interval 10                # как часто слать объявления, в секундах
 ipv6 nd other-config-flag             # поднять флаг O: «адрес возьми сам, а за
                                       #   DNS сходи в DHCPv6»

# проверка на роутере
show ipv6 interface eth1               # адреса порта, включая link-local
show ipv6 route                        # таблица маршрутов IPv6

# на хосте (Linux)
ip -6 addr show dev eth1               # -6 — работать с IPv6, а не с IPv4;
                                       #   dev сужает вывод до одного интерфейса
ip -6 route
ip -6 neigh                            # соседи: аналог ARP-таблицы
ping6 -c3 2001:db8:11::1               # -c — сколько пакетов послать
ping6 -c3 fe80::1%eth1                 # %eth1 — зона: link-local адрес одинаково
                                       #   валиден в каждом сегменте, поэтому надо
                                       #   сказать, через какой порт слать
ping6 -c3 ff02::1%eth1                 # ff02::1 — групповой адрес «все узлы
                                       #   сегмента»: кто отзовётся, тот и есть
traceroute6 2001:db8:20::10
sysctl net.ipv6.conf.all.forwarding    # тот же форвардинг, но на Linux-роутере.
                                       #   Ключ -w перед именем — записать значение
Контрольные вопросы

Дальше — лабораторная работа «IPv6: подними dual-stack»

Для неё нужен аккаунт: стенд поднимается персонально под вас — свои роутеры, свои конфиги, никто в них не мешает. Регистрация — почта и пароль.

Теория прочитана. Дальше — руками.

Личный стенд из настоящих роутеров разворачивается за секунды. Платформа проверяет не ответы на тесты, а состояние вашей сети: поднялись ли соседства, сошлись ли маршруты, ходит ли ping. Рядом — AI-наставник, который видит ваши конфиги и ведёт к решению, не выдавая готовое.

Начать бесплатно → бета открыта, доступ бесплатный