Сетевой уровень: адресация и маршрутизация (IPv6)
Задачи
Интернет: объединение сред передачи данных в глобальную сеть
- Глобальная идентификация (адресация)
- Структура адреса
Механизм раздачи идентификаторов
- Алгоритм доставки (маршрутизация)
- Известный маршрут и маршрут по умолчанию внутри крупной сети
- Связность крупных сетей (карта достижимости / стоимость)
Динамическая (в общем случае) природа обеих задач.
IPv6
Презентация от Jen "Furry" Linkova
Структура адреса
- Адрес: 128 бит
Назначается на интерфейс (т. е. не уникален для узла)
Может быть несколько на одном интерфейсе (т. е. не уникален для интерфейса узла)
- Категории адресов
- Неопределённый адрес: 128 нулей
- Петлевой адрес: 127 нулей и единица
- Unicast
Multicast: первый октет 1111 1111, он же 0xff
- Область действия (Scope) юникастного адреса
- Loopback: внутри одной машины
Link-local (первые 10 бит — 1111 1110 10)
- Global Unicast
Запись: 2001:0db8:85a3:0000:0000:0370:008e:7334 == 2001:db8:85a3::370:8e:7334
Для LL-адресов: fe80::8a2e:370:7334%eth1, после % идёт scope identifier, "зона"
В Linux можно после % писать имя интерфейса, а можно его уникальный ifindex в netns.
- Префиксы: диапазоны адресов с одинаковыми N старших бит
- кол-во старших бит — "длина префикса"
"префикс X короче префикса Y" <=> "в X больше адресов, чем в Y"
Интерфейсный идентификатор, Interface ID, IID: младшие биты
- например, MAC или его хэш
- все IID доступны для использования
Адреса интерфейсов в Linux: ip a (add, del и т. п.)
LLA: внутриинтерфейсные адреса
- Адреса для служебных целей, которые "просто работают"
- уникальны и актуальны только в рамках одного сегмента связи
fe80::3a%15 и fe80::3a%17 — не обязательно обозначения одного абонента
fe80::3a без интерфейса не имеет смысла
- всегда доступны в локальной среде напрямую
- иначе говоря, узел по link-local-адресу — всегда сосед
что не всегда верно для адресов других обл. действия, даже если назначен адрес в том же префиксе!
- не подлежат маршрутизации (и не требуют IPv6-маршрутизаторов)
- узел назначает себе LLA на каждом поднятом интерфейсе
- уникальны и актуальны только в рамках одного сегмента связи
На каждом интерфейсе, на котором включен IP, автоматически генерируется link-local адрес:
узел генерирует себе интерфейсный идентификатор: например, ::1c80:9aa4:528e:bb85
назначает себе адрес(-а) в префиксе fe80::/64 с младшими битами, равными IID: например, fe80::1c80:9aa4:528e:bb85
Можно, конечно, назначить и вручную. Если назначать внутри fe80::/10, но за пределами fe80::/64, то точно не будет пересечения с автогенератами.
Нужны для обнаружения соседей в локальной среде, для общения OSPF-маршрутизаторов, как next hop маршрутов и пр.
Могут использоваться и для прикладного трафика между соседями, если это вдруг удобно: ssh 'root@fe80:7e::3%eth1'
Multicast: адреса групп узлов
| 1111 1111 xxxx xxxx rrrr rrrr .... .... ............. gggg gggg gggg gggg gggg gggg gggg gggg | | ^^^^ ^^^^ ^^^^ ^ ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | multicast scope reserved prefixlen 64-bit group ID | | ^^^^ network prefix | | flags <--- (if P-flag is 1) ----> | | | | [8 bits] [4+4bits] [8 bits] [8 bits] [64 bits] [32 bits] |
У multicast-групп тоже есть область действия (scope):
1: interface-local
2: link-local
5: site-local
e: global
В жизни бывают только 2 и 5.
Примеры:
ff02::1%eth1: все узлы в локальной среде за eth1 (фактически это широковещание)
ff02::2%eth1: все маршрутизаторы в локальной среде за eth1
ff05::2: все маршрутизаторы within a site (TODO: туплю)
ff02::101%eth1: все NTP-серверы в локальной среде за eth1
ff02::1:ff3a:d876%eth1: все узлы в локальной среде за eth1, что имеют адрес, заканчивающийся на 24 бита ::3a:d876
Последние два примера на схеме:
| <-------------- 32 bits --------------> < --- 64 bits --- > <-------------- 32 bits --------------> | | 1111 1111 xxxx xxxx rrrr rrrr prefixlen .... .... ...p gggg gggg gggg gggg gggg gggg gggg gggg | | ------------------------------------------------------------------------------------------------------ | | f f 0 2 .. .. 0 0 0 0 0 0 1 0 1 | | 1111 1111 0000 0010 0000 0000 0000 0000 .... .... 0000 0000 0000 0000 0000 0000 0001 0000 0001 | | f f 0 2 .. .. 1 f f 3 a d 8 7 6 | | 1111 1111 0000 0010 0000 0000 0000 0000 .... .... 0001 1111 1111 0011 1010 1101 1000 0111 0110 |
Доставка пакета
- Заголовок фиксированной длины
- заголовки-расширения и заголовки более верхних уровней идут далее
- Фрагментация на стороне отправителя, PMTUD
- или, вместо неё, рекомендовать максимальный размер пакета уровням выше
- Противодействие зацикливанию: hop limit
- Типы доставки: Unicast / Anycast / Multicast
- Unicast: пакет направлен одному получателю по его адресу назначения
- Anycast: пакет направлен любому получателю из нескольких по их общему адресу
- например, ближайшему
- Multicast: пакет направлен всем получателям в группе, адрес назначения — адрес группы
- адрес группы не может быть адресом отправителя
- Принадлежность адреса к префиксу: маска побитового AND
пример: /48 == ffff:ffff:ffff:0:0:0:0:0, второй вариант никто не пишет.
- Принятие решения о маршрутизации
- Таблица маршрутизации в соответствии с адресом получателя
- Результат поиска в таблице
интерфейс, интерфейсный_адрес — для многоабонентной среды
интерфейс — для P2P среды
Routing Headers: мета-маршрутизация по расширенному заголовку; самый актуальный сегодня подход — SRv6
- В ядре Linux:
Таблица: ip -6 route (по умолчанию подразумевает IPv4 :[)
ip -6 route add <dest-prefix> via <target-address> dev <link>
ip -6 route add <dest-prefix> from <src-prefix> <target-address> dev <link>
Судьба пакета за рамками IP: encap {mpls,bpf,seg6,seg6local,xfrm}
Нетабличная маршрутизация по отправителю/next-header/ULP: ip rule
- Заполнение маршрутных таблиц:
по объявлению от маршрутизатора (Router Advertisement, RAdv)
автоматическое при добавлении сети на интерфейсе (если не указан флаг noprefixroute)
- ручное
Протоколы динамической маршрутизации (самый известный — OSPF)
Linux/*NIX — демон BIRD и др.
Специальные адреса и сети
rfc5156, актуальная таблица от IANA
Address Block
Name
RFC
Allocation Date
Termination Date
Source
Destination
Forwardable
Globally Reachable
Reserved-by-Protocol
::1/128
Loopback Address
2006-02
N/A
False
False
False
False
True
::/128
Unspecified Address
2006-02
N/A
True
False
False
False
True
::ffff:0:0/96
IPv4-mapped Address
2006-02
N/A
False
False
False
False
True
64:ff9b::/96
IPv4-IPv6 Translat.
2010-10
N/A
True
True
True
True
False
64:ff9b:1::/48
IPv4-IPv6 Translat.
2017-06
N/A
True
True
True
False
False
100::/64
Discard-Only Address Block
2012-06
N/A
True
True
True
False
False
2001::/23
IETF Protocol Assignments
2000-09
N/A
False [1]
False [1]
False [1]
False [1]
False
2001:1::1/128
Port Control Protocol Anycast
2015-10
N/A
True
True
True
True
False
2001:1::2/128
Traversal Using Relays around NAT Anycast
2017-02
N/A
True
True
True
True
False
2001:2::/48
Benchmarking
2008-04
N/A
True
True
True
False
False
2001:3::/32
AMT
2014-12
N/A
True
True
True
True
False
2001:4:112::/48
AS112-v6
2014-12
N/A
True
True
True
True
False
2001:10::/28
Deprecated (previously ORCHID)
2007-03
2014-03
2001:20::/28
ORCHIDv2
2014-07
N/A
True
True
True
True
False
2001:30::/28
Drone Remote ID Protocol Entity Tags (DETs) Prefix
2022-12
N/A
True
True
True
True
False
2001:db8::/32
Documentation
2004-07
N/A
False
False
False
False
False
2002::/16 [3]
6to4
2001-02
N/A
True
True
True
N/A [3]
False
2620:4f:8000::/48
Direct Delegation AS112 Service
2011-05
N/A
True
True
True
True
False
3fff::/20
Documentation
2024-07
N/A
False
False
False
False
False
5f00::/16
Segment Routing (SRv6) SIDs
2024-04
N/A
True
True
True
False
False
fc00::/7
Unique-Local
2005-10
N/A
True
True
True
False [4]
False
fe80::/10
Link-Local Unicast
2006-02
N/A
True
True
False
False
True
Примечательны те, у которых в последнем столбце True.
IPv4-mapped: этот диапазон из 2**32 адресов кодирует IPv4-адреса при работе с сокетами
connect() к такому адресу подключится по IPv4, по интерфейсам пойдут пакеты IPv4;
bind() на таком адресе и listen() позволит слушать на IPv4-сокете;
- админ может выключить через sysctl, программа — для сокета через setsockopt
- в базе данных не нужно кодировать для IP-адреса версию протокола IP; хватит 128 бит;
IPv4-mapped адреса не должны появляться в пакетах как отправитель/получатель, иначе это рычаг для подделки трафика.
Кстати, bind() на нуль-адресе :: позволит получать соединения (датаграммы) от клиентов и по IPv6, и по IPv4 на одном сокете, а не двух;
ICMP
(rfc4443)
- ICMP-пакет — одиночная датаграмма ⇒ есть контрольная сумма
множество types и codes
работа traceroute: отсылка пакетов с увеличивающимся TTL и регистрация ICMP-ответов в стиле «пакет не дожил»
Path MTU Discovery (rfc4821 / Maximum_transmission_unit)
NDP (rfc4861): Мы знаем IP адресата, и определили, что он находится в локальной сети за интерфейсом, скажем, eth1. Надо инкапсулировать IP-пакет в фрейм и отослать по MAC-адресу… какому?
- Тоже ICMP, а не сетево-интерфейсного уровня
Duplicate Address Detection (DAD) : перед самоназначением адреса шлём NS
В частности, src ip = :: (потому что не известно, уникальный ли мы придумали адрес)
- Neighbour Solicitation / Neighbour Advertisement: "слышно ли меня адресату"
Если адресату понадобится наш MAC-адрес, он должен проделать ту же процедуру
- Router Discovery тоже считается частью NDP (подробнее в следующей лекции)
- конечные узлы шлют Router Solicitation, RS
- маршрутизаторы шлют Router Advertisement, RA
- Алсо, ND Proxy: притворяемся, что это наш MAC, а сами втихую пересылаем
ip neigh: посмотреть таблицу соответствия MAC → IP
Neighbour Discovery на примере
Два соседа в одной локальной сети: athena и router.
Запустим tcpdump -xx -n -v icmp6 на роутере.
Поднимем на клиенте athena интерфейс в сторону роутера:
[root@athena ~]# ip link set eth1 up
Клиент сгенерировал и назначил себе внутрисегментный адрес fe80::a00:27ff:fe9a:a65e на этом интерфейсе. Как он поймёт, что в сегменте нет других абонентов с таким адресом? Вышлет DAD-пакет, который видно в дампе на router:
18:19:02.431267 08:00:27:9a:a6:5e > 33:33:ff:9a:a6:5e, ethertype IPv6 (0x86dd), length 86: (hlim 255, next-header ICMPv6 (58) payload length: 32) :: > ff02::1:ff9a:a65e: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::a00:27ff:fe9a:a65e
nonce option (14), length 8 (1): 4c 03 0c 40 93 ab
0x0000: 3333 ff9a a65e 0800 279a a65e 86dd 6000 33...^..'..^..`.
0x0010: 0000 0020 3aff 0000 0000 0000 0000 0000 ....:...........
0x0020: 0000 0000 0000 ff02 0000 0000 0000 0000 ................
0x0030: 0001 ff9a a65e 8700 043e 0000 0000 fe80 .....^...>......
0x0040: 0000 0000 0000 0a00 27ff fe9a a65e 0e01 ........'....^..
0x0050: 4c03 0c40 93ab L..@..Это who-has запрос "у кого адрес fe80::a00:27ff:fe9a:a65e — отзовитесь". IP-адрес источника не определён, IP-адрес назначения — solicited-node мультивещательная группа.
От разрешаемого адреса fe80::a00:27ff:fe9a:a65e берутся младшие 24 бита -> 0x9a 0xa6 0x5e
Старшие 104 бита — ff02::1:ff00:0000, в сумме: ff02::1:ff9a:a65e
Ethernet multicast — младшие 32 бита + префикс: ff02::1:ff9a:a65e -> 33:33:ff:9a:a6:5e
Если в течение таймаута (1.5 секунды) никто не ответил — адрес наш.
Роутер тоже автоназначил себе адрес:
[root@router ~]# ip -br a lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 DOWN eth1 UP fe80::a00:27ff:fec8:ae33/64 eth2 DOWN eth3 DOWN
Попробуем пингануть соседа (ping -c2 fe80::a00:27ff:fec8:ae33%eth1).
TODO Придумать более читаемую разметку (например, цветом + комментарии в tooltip-ах)
tcpdump поймает следующее:
18:24:35.388779 08:00:27:9a:a6:5e > 33:33:ff:c8:ae:33, ethertype IPv6 (0x86dd), length 86: (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::a00:27ff:fe9a:a65e > ff02::1:ffc8:ae33: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::a00:27ff:fec8:ae33
source link-address option (1), length 8 (1): 08:00:27:9a:a6:5e
0x0000: 3333 ffc8 ae33 0800 279a a65e 86dd 6000 33...3..'..^..`.
: ^^^^ ^^^^ ^^^^ ^
: ethernet multicast Ver
0x0010: 0000 0020 3a ....:
: ^^^^ ^^
: len Next Header (ICMPv6)
0x0010: ff fe80 0000 0000 0000 0a00 ...........
: ^^
: Hop Limit
0x0020: 27ff fe9a a65e ff02 0000 0000 0000 0000 '....^..........
0x0030: 0001 ffc8 ae33 87 .....3.
: ^^
: type (NS)
0x0030: 00 41b4 0000 0000 fe80 .A.......
: ^^ ^^^^
: code csum
0x0040: 0000 0000 0000 0a00 27ff fec8 ae33 0101 ........'....3..
0x0050: 0800 279a a65e ..'..^
18:24:35.388827 08:00:27:c8:ae:33 > 08:00:27:9a:a6:5e, ethertype IPv6 (0x86dd), length 86: (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::a00:27ff:fec8:ae33 > fe80::a00:27ff:fe9a:a65e: [icmp6 sum ok] ICMP6, neighbor advertisement, length 32, tgt is fe80::a00:27ff:fec8:ae33, Flags [router, solicited, override]
destination link-address option (2), length 8 (1): 08:00:27:c8:ae:33
0x0000: 0800 279a a65e 0800 27c8 ae33 86dd 6000 ..'..^..'..3..`.
: ^^^^ ^^^^ ^^^^
: ethernet unicast reply
0x0010: 0000 0020 3aff fe80 0000 0000 0000 0a00 ....:...........
0x0020: 27ff fec8 ae33 fe80 0000 0000 0000 0a00 '....3..........
0x0030: 27ff fe9a a65e 8800 2734 e000 0000 fe80 '....^..'4......
: ^^ ^
: type (NA) flags
0x0040: 0000 0000 0000 0a00 27ff fec8 ae33 0201 ........'....3..
: ^^^^
: option type and length
0x0050: 0800 27c8 ae33 ..'..3
: ^^^^ ^^^^ ^^^^
: option 2: dest link address Запрос соседа (who-has fe80::a00:27ff:fec8:ae33) — NS
отправлен мультикастом на ff02::1:ffc8:ae33 аналогично DAD
- со своего имеющегося адреса, в отличие от DAD
Объявление о соседе (target-is 08:00:27:c8:ae:33) — NA
- отправлено юникастом на адрес автора запроса.
- Ответ содержит опцию "интерфейсный адрес назначения" (а то вдруг там прокси?)
- Получатель ND-сообщений проверяет, что hop limit ни разу не был уменьшен маршрутизатором.
В результате у первого узла возникнет запись о втором в состоянии REACHABLE. «receipt of a solicited advertisement indicates that a path is working in both directions».
У второго узла возникнет запись о первом в состоянии STALE, rfc4861; не REACHABLE, потому что второй не убедился, что визави может ответить на его, второго, запрос.
Далее соседи начинают общаться: пинг, ответ, пинг, ответ.
18:24:35.389214 08:00:27:9a:a6:5e > 08:00:27:c8:ae:33, ethertype IPv6 (0x86dd), length 118: (flowlabel 0x03500, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::a00:27ff:fe9a:a65e > fe80::a00:27ff:fec8:ae33: [icmp6 sum ok] ICMP6, echo request, id 1, seq 1
0x0000: 0800 27c8 ae33 0800 279a a65e 86dd 6000 ..'..3..'..^..`.
0x0010: 3500 0040 3a40 fe80 0000 0000 0000 0a00 5..@:@..........
0x0020: 27ff fe9a a65e fe80 0000 0000 0000 0a00 '....^..........
0x0030: 27ff fec8 ae33 8000 d793 0001 0001 7326 '....3........s&
: ^^ ^^^^
: type (echo) seqn
0x0040: b669 0000 0000 0796 0500 0000 0000 1011 .i..............
0x0050: 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 ...............!
0x0060: 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 "#$%&'()*+,-./01
0x0070: 3233 3435 3637 234567
18:24:35.389245 08:00:27:c8:ae:33 > 08:00:27:9a:a6:5e, ethertype IPv6 (0x86dd), length 118: (flowlabel 0x4cb7a, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::a00:27ff:fec8:ae33 > fe80::a00:27ff:fe9a:a65e: [icmp6 sum ok] ICMP6, echo reply, id 1, seq 1
0x0000: 0800 279a a65e 0800 27c8 ae33 86dd 6004 ..'..^..'..3..`.
0x0010: cb7a 0040 3a40 fe80 0000 0000 0000 0a00 .z.@:@..........
0x0020: 27ff fec8 ae33 fe80 0000 0000 0000 0a00 '....3..........
0x0030: 27ff fe9a a65e 8100 d693 0001 0001 7326 '....^........s&
: ^^ ^^^^
: type (echo-reply) seqn
0x0040: b669 0000 0000 0796 0500 0000 0000 1011 .i..............
0x0050: 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 ...............!
0x0060: 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 "#$%&'()*+,-./01
0x0070: 3233 3435 3637 234567
18:24:36.389426 08:00:27:9a:a6:5e > 08:00:27:c8:ae:33, ethertype IPv6 (0x86dd), length 118: (flowlabel 0x03500, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::a00:27ff:fe9a:a65e > fe80::a00:27ff:fec8:ae33: [icmp6 sum ok] ICMP6, echo request, id 1, seq 2
0x0000: 0800 27c8 ae33 0800 279a a65e 86dd 6000 ..'..3..'..^..`.
0x0010: 3500 0040 3a40 fe80 0000 0000 0000 0a00 5..@:@..........
0x0020: 27ff fe9a a65e fe80 0000 0000 0000 0a00 '....^..........
0x0030: 27ff fec8 ae33 8000 3891 0001 0002 7426 '....3..8.....t&
: ^^ ^^^^
: type (echo) seqn
0x0040: b669 0000 0000 a597 0500 0000 0000 1011 .i..............
0x0050: 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 ...............!
0x0060: 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 "#$%&'()*+,-./01
0x0070: 3233 3435 3637 234567
18:24:36.389474 08:00:27:c8:ae:33 > 08:00:27:9a:a6:5e, ethertype IPv6 (0x86dd), length 118: (flowlabel 0x4cb7a, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::a00:27ff:fec8:ae33 > fe80::a00:27ff:fe9a:a65e: [icmp6 sum ok] ICMP6, echo reply, id 1, seq 2
0x0000: 0800 279a a65e 0800 27c8 ae33 86dd 6004 ..'..^..'..3..`.
0x0010: cb7a 0040 3a40 fe80 0000 0000 0000 0a00 .z.@:@..........
0x0020: 27ff fec8 ae33 fe80 0000 0000 0000 0a00 '....3..........
0x0030: 27ff fe9a a65e 8100 3791 0001 0002 7426 '....^..7.....t&
: ^^ ^^^^
: type (echo-reply) seqn
0x0040: b669 0000 0000 a597 0500 0000 0000 1011 .i..............
0x0050: 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 ...............!
0x0060: 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 "#$%&'()*+,-./01
0x0070: 3233 3435 3637 234567Повторим эксперимент, но с запущенным в фоне ip monitor neighbor dev eth1:
[root@athena ~]# ip monitor neighbor dev eth1 & [root@athena ~]# ping -c2 fe80::a00:27ff:fe9e:95d1%eth1 PING fe80::a00:27ff:fe9e:95d1%eth1 (fe80::a00:27ff:fe9e:95d1%eth1) 56 data bytes fe80::a00:27ff:fe9e:95d1 lladdr 08:00:27:9e:95:d1 router REACHABLE 64 bytes from fe80::a00:27ff:fe9e:95d1%eth1: icmp_seq=1 ttl=64 time=1.60 ms 64 bytes from fe80::a00:27ff:fe9e:95d1%eth1: icmp_seq=2 ttl=64 time=0.898 ms --- fe80::a00:27ff:fe9e:95d1%eth1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.898/1.250/1.602/0.352 ms
[root@router ~]# ip n flush dev eth1
fe80::a00:27ff:fe57:54af FAILED
Deleted fe80::a00:27ff:fe57:54af FAILED
[root@router ~]# tcpdump -i eth1 -xx -n -v
tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
fe80::a00:27ff:fe57:54af lladdr 08:00:27:57:54:af STALE
23:21:06.518450 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::a00:27ff:fe57:54af > ff02::1:ff9e:95d1: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::a00:27ff:fe9e:95d1
source link-address option (1), length 8 (1): 08:00:27:57:54:af
0x0000: 3333 ff9e 95d1 0800 2757 54af 86dd 6000
0x0010: 0000 0020 3aff fe80 0000 0000 0000 0a00
0x0020: 27ff fe57 54af ff02 0000 0000 0000 0000
0x0030: 0001 ff9e 95d1 8700 16b1 0000 0000 fe80
0x0040: 0000 0000 0000 0a00 27ff fe9e 95d1 0101
0x0050: 0800 2757 54af
23:21:06.518530 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::a00:27ff:fe9e:95d1 > fe80::a00:27ff:fe57:54af: [icmp6 sum ok] ICMP6, neighbor advertisement, length 32, tgt is fe80::a00:27ff:fe9e:95d1, Flags [router, solicited, override]
destination link-address option (2), length 8 (1): 08:00:27:9e:95:d1
0x0000: 0800 2757 54af 0800 279e 95d1 86dd 6000
0x0010: 0000 0020 3aff fe80 0000 0000 0000 0a00
0x0020: 27ff fe9e 95d1 fe80 0000 0000 0000 0a00
0x0030: 27ff fe57 54af 8800 c2ca e000 0000 fe80
0x0040: 0000 0000 0000 0a00 27ff fe9e 95d1 0201
0x0050: 0800 279e 95d1
23:21:06.519447 IP6 (flowlabel 0x867fd, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::a00:27ff:fe57:54af > fe80::a00:27ff:fe9e:95d1: [icmp6 sum ok] ICMP6, echo request, id 6, seq 1
0x0000: 0800 279e 95d1 0800 2757 54af 86dd 6008
0x0010: 67fd 0040 3a40 fe80 0000 0000 0000 0a00
0x0020: 27ff fe57 54af fe80 0000 0000 0000 0a00
0x0030: 27ff fe9e 95d1 8000 cc1f 0006 0001 e23e
0x0040: b769 0000 0000 096b 0900 0000 0000 1011
0x0050: 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021
0x0060: 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031
0x0070: 3233 3435 3637
23:21:06.519466 IP6 (flowlabel 0x36eaa, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::a00:27ff:fe9e:95d1 > fe80::a00:27ff:fe57:54af: [icmp6 sum ok] ICMP6, echo reply, id 6, seq 1
0x0000: 0800 2757 54af 0800 279e 95d1 86dd 6003
0x0010: 6eaa 0040 3a40 fe80 0000 0000 0000 0a00
0x0020: 27ff fe9e 95d1 fe80 0000 0000 0000 0a00
0x0030: 27ff fe57 54af 8100 cb1f 0006 0001 e23e
0x0040: b769 0000 0000 096b 0900 0000 0000 1011
0x0050: 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021
0x0060: 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031
0x0070: 3233 3435 3637
23:21:07.519740 IP6 (flowlabel 0x867fd, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::a00:27ff:fe57:54af > fe80::a00:27ff:fe9e:95d1: [icmp6 sum ok] ICMP6, echo request, id 6, seq 2
0x0000: 0800 279e 95d1 0800 2757 54af 86dd 6008
0x0010: 67fd 0040 3a40 fe80 0000 0000 0000 0a00
0x0020: 27ff fe57 54af fe80 0000 0000 0000 0a00
0x0030: 27ff fe9e 95d1 8000 fc19 0006 0002 e33e
0x0040: b769 0000 0000 d86f 0900 0000 0000 1011
0x0050: 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021
0x0060: 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031
0x0070: 3233 3435 3637
23:21:07.519819 IP6 (flowlabel 0x36eaa, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::a00:27ff:fe9e:95d1 > fe80::a00:27ff:fe57:54af: [icmp6 sum ok] ICMP6, echo reply, id 6, seq 2
0x0000: 0800 2757 54af 0800 279e 95d1 86dd 6003
0x0010: 6eaa 0040 3a40 fe80 0000 0000 0000 0a00
0x0020: 27ff fe9e 95d1 fe80 0000 0000 0000 0a00
0x0030: 27ff fe57 54af 8100 fb19 0006 0002 e33e
0x0040: b769 0000 0000 d86f 0900 0000 0000 1011
0x0050: 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021
0x0060: 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031
0x0070: 3233 3435 3637Когда сосед был известен, но запись протухла, и надо что-то ему отправить — переводим в PROBE:
fe80::a00:27ff:fe57:54af lladdr 08:00:27:57:54:af PROBE
fe80::a00:27ff:fe57:54af lladdr 08:00:27:57:54:af REACHABLE
23:21:11.912793 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::a00:27ff:fe9e:95d1 > fe80::a00:27ff:fe57:54af: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::a00:27ff:fe57:54af
source link-address option (1), length 8 (1): 08:00:27:9e:95:d1
0x0000: 0800 2757 54af 0800 279e 95d1 86dd 6000
0x0010: 0000 0020 3aff fe80 0000 0000 0000 0a00
0x0020: 27ff fe9e 95d1 fe80 0000 0000 0000 0a00
0x0030: 27ff fe57 54af 8700 e634 0000 0000 fe80
0x0040: 0000 0000 0000 0a00 27ff fe57 54af 0101
0x0050: 0800 279e 95d1
23:21:11.913444 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 24) fe80::a00:27ff:fe57:54af > fe80::a00:27ff:fe9e:95d1: [icmp6 sum ok] ICMP6, neighbor advertisement, length 24, tgt is fe80::a00:27ff:fe57:54af, Flags [solicited]
0x0000: 0800 279e 95d1 0800 2757 54af 86dd 6000
0x0010: 0000 0018 3aff fe80 0000 0000 0000 0a00
0x0020: 27ff fe57 54af fe80 0000 0000 0000 0a00
0x0030: 27ff fe9e 95d1 8800 6bad 4000 0000 fe80
0x0040: 0000 0000 0000 0a00 27ff fe57 54afШлём unicast NS лично соседу. Получили solicited NA — состояние REACHABLE.
NDP поддерживается ядром Linux.
Настройка IP в Linux и табличная маршрутизация
Destination-based принцип табличной маршрутизации: «адрес получателя ⇒ префикс получателя ⇒ маршрут».
Три скринкаста к проводимым ниже настройкам: router, client, clone.
Настройка префикса
Длина префикса часто записывается в виде числа после символа слеша (/48), реже — как последовательность 1 в двоичном виде
# sipcalc 2001:db8:ab::3:4:56a/64 -[ipv6 : 2001:db8:ab::3:4:56a/64] - 0 [IPV6 INFO] Expanded Address - 2001:0db8:00ab:0000:0000:0003:0004:056a Compressed address - 2001:db8:ab::3:4:56a Subnet prefix (masked) - 2001:db8:ab:0:0:0:0:0/64 Address ID (masked) - 0:0:0:0:0:3:4:56a/64 Prefix address - ffff:ffff:ffff:ffff:0:0:0:0 Prefix length - 64 Address type - Aggregatable Global Unicast Addresses Network range - 2001:0db8:00ab:0000:0000:0000:0000:0000 - 2001:0db8:00ab:0000:ffff:ffff:ffff:ffff
В спецификации протокола IPv6 описана модель работы узла, в которой на интерфейс назначается префикс с длиной, в котором узел берёт себе ноль или более адресов. Linux на эту модель не опирается; даёт возможность назначить на сетевом интерфейсе адрес с длиной префикса.
При ручной настройке IP+префикса на сетевом интерфейсе Linux по умолчанию вносит в таблицу маршрутизации запись вида: «такая-то IP-подсеть находится непосредственно за этим сетевым интерфейсом», предполагая, что адреса в этом префиксе доступны напрямую по локальной среде.
1 srv:~# ip link set dev eth1 up 2 srv:~# ip addr add dev eth1 2001:db8:0:a::56a/64 3 srv:~# ip -6 r 4 2001:db8:0:a::/64 dev eth1 proto kernel metric 256 pref medium 5 srv:~# ping 2001:db8:0:a::56b 6 PING 2001:db8:0:a::56b (2001:db8:0:a::56b) 56 data bytes 7 ^C 8 1 packets transmitted, 0 received, 100% packet loss, time 0ms 9 srv:~# ip -6 n 10 2001:db8:0:a::56b dev eth1 INCOMPLETE 11 srv:~# ping 2001:db8:0:b::400 12 ping: connect: Network is unreachable 13
Неявное правило из таблицы маршрутизации гласит, что с абонентом мы связаны единой средой передачи данных, и сетевая подсистема вправе ожидать появления MAC-адреса этого 2001:db8:0:a::56b в ARP-таблице таблице соседей (ip neighbour)
При обращении к 2001:db8:0:b::400 мы видим, что он ни с чем не совпадает, а других записей в таблице маршрутизации у нас нет — как следствие, сообщение о недостижимости.
На второй машине (она будет называться router, потому что в дальнейшем послужит маршрутизатором) — практически то же самое, но назначим внутрисегментный адрес:
1 router:~# ip link set dev eth1 up 2 router:~# ip addr add dev eth1 fe80::2/64 3 router:~# ping -c 1 2001:db8:0:a::56a 4 ping: connect: Network is unreachable 5 router:~# ip r add 2001:db8:0:a::/64 dev eth1 # добавим prefix route сами 6 router:~# ping -c 1 2001:db8:0:a::56a 7 PING 2001:db8:0:a::56a(2001:db8:0:a::56a) 56 data bytes 8 64 bytes from 2001:db8:0:a::56a: icmp_seq=1 ttl=64 time=1.84 ms 9 router:~# ip -6 n # записи протухают за считанные секунды! 10 2001:db8:0:a::56a dev eth1 lladdr 08:00:27:f5:75:0c DELAY 11
Глобальных адресов у нас нет, но до соседа 2001:db8:0:a::56a мы можем достучаться с того адреса, который есть (в нашем случае это link local адрес fe80::2/64!), и он сможет нам ответить.
Маршрутизация между двумя сетями
Подключим ко второму интерфейсу маршрутизатора ещё одну машину.
- маршрутизатор:
Поскольку link local адреса уникальны только в пределах среды за интерфейсом, мы можем взять такой же — fe80::2/64
удалённая машина сlient:
1 client:~# ip link set dev eth1 up 2 client:~# ip addr add dev eth1 2001:db8:0:b::400/64 3 client:~# ping -c1 fe80::2%eth1 4 PING fe80::2%eth1(fe80::2%eth1) 56 data bytes. 5 64 bytes from fe80::2%eth1: icmp_seq=1 ttl=64 time=0.864 ms 6 client:~# ping 2001:db8:0:a::56a 7 ping: connect: Network is unreachable 8 client:~# ip -6 route add default via fe80::2%eth1 9 client:~# ip -6 r 10 default via fe80::2 dev eth1 11 fe80::/64 dev eth1 proto kernel metric 256 pref medium 12
default — это такая сеть с нулевой сетевой маской ::/0 — т. е. весь Интернет. Такой записи соответствует вообще любой пакет.
Если адрес получателя в пакете отвечает сразу нескольким записям в таблице маршрутизации, выбирается запись с наибольшей сетевой маской, самым длинным префиксом (т. е. «самая определённая» запись)
Надо сделать ещё два действия:
Настроить маршрут на машине srv. Не будем добавлять default, а укажем более точный диапазон:
1 srv:~# ip -6 route add 2001:db8:0:b::/64 via fe80::2%eth1 2 srv:~# ip -6 r 3 2001:db8:0:a::/64 dev eth1 proto kernel metric 256 pref medium 4 2001:db8:0:b::/64 via fe80::2 dev eth1 metric 1024 pref medium 5 fe80::/64 dev eth1 proto kernel metric 256 pref medium 6 srv:~# ping -c1 2001:db8:0:a::56a 7 PING 2001:db8:0:a::56a (2001:db8:0:a::56a) 56(84) bytes of data. 8 64 bytes from 2001:db8:0:a::56a: icmp_seq=1 ttl=64 time=0.041 ms 9
Вторая запись в таблице означает: нам известно, что для посылки пакетов в сеть 2001:db8:0:b::/64 их надо направлять на интерфейс eth1 к fe80::2 (это маршрутизатор, он разберётся)
Что до самого fe80::2 на eth1 — мы точно знаем, что это сосед.
Чтобы linux-машина router начала работать маршрутизатором, надо включить в ядре поддержку пересылки IP-пакетов, пришедших на каждый интерфейс:
1 router:~# sysctl net.ipv6.conf.all.forwarding=1- или, что то же самое:
1 router:~# echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
Будем работать с параметром forwarding для всех интерфейсов сразу. Есть ещё sysctl-параметр conf/$X/forwarding, он отвечает совсем за другое, лучше его не трогать!
Начиная с сентября 2025 г., включить маршрутизацию пакетов, пришедщих на конкретный интерфейс X, можно: conf/$X/force_forwarding.
- Все эти параметры тонко взаимодействуют друг с другом и неявно переключают друг друга неочевидным образом; останавливаться на этом сегодня некогда.
Простая табличная маршрутизация:
- Получаем пакет
- Просматриваем все записи в таблице, из них выбираем те, в префиксе которых лежит адрес получателя пакета (применяем к нему соответствующую маску и сравниваем префикс маршрута с результатом)
- Если настроен маршрут по умолчанию (с сетевой маской длины 0), он всегда подходит
- Среди подходящих записей выбирается та, что имеет самый длинный префикс (т. е. в которой меньше абонентов)
- Если это запись вида «сеть dev интерфейс», обращаемся за адресом к ND-таблице соседей, если «сеть via адрес» — используем этот адрес
- Пересылаем пакет на найденный адрес
TODO Предположительно не влезает, в т. ч. в Д/З!
Целевая маршрутизация
Ранее мы работали с destination-based принцип табличной маршрутизации: «сеть получателя ⇒ маршрут».
Задача source-based маршрутизации: «свойства пакета отправителя ⇒ маршрут».
Linux: просто заведём несколько таблиц маршрутизации (разных), и будем обрабатывать пакет по правилам одной из них сообразно его свойствам:
- Адрес отправителя
- Порт получателя (или отправителя)
- Интерфейс, протокол и т. п. …
Команда ip -6 rule (немного документации)
Заготовка: TODO: убрать выходы в интернет, заменить на ещё одну виртуалку.
Два компьютера с выходом в интернет у каждого
- Маршрутизатор, подключённый к этим двум машинам по отдельным интерфейсам и третьей сетью для внутренних клиентов
Пример 1: подключаем два клиента ко внутренней сети, настраиваем source routing: с одного адреса пакеты в одну сторону, с другого — в другую
[router] # ip -6 route add default второй_сервер table какой-то-номер [router] # ip -6 rule add from «IP_B» table какой-то-номер
Пример 2: подключаем один клиент, перекидываем трафик по 80/443 портам в другую сторону
# ip -6 route add default второй_сервер table какой-то-номер # ip -6 rule add dport 80 table какой-то-номер
Получаем такую настройку:
1 [root@router ~]# ip -6 rule list
2 0: from all lookup local
3 32765: from all dport 80 lookup какой-то-номер
4 32766: from all lookup main
5 [root@router ~]# ip -6 route list
6 default via Сервер1 dev eth1
7 …
8 [root@router ~]# ip -6 route list table какой-то-номер
9 default via Сервер2 dev eth2
10
Правила в ip rule
- Просматриваются в порядке увеличения номера (приоритет 0 — наивысший)
Правило lookup приводит к поиску в соответствующей таблице
- Если этот поиск удачен, происходит маршрутизация
Например, правило с наивысшим приоритетом «0: from all lookup local» приводит к поиску в таблице local (посмотрите на неё), отражающей подключённые локальные сети. Если адрес не из локальной сети, lookup local ничего не находит,
Если правило lookup не нашло маршрута, поиск продолжается дальше
Приоритет правила можно задавать вручную, добавив в конце priority номер
Основная таблица — main, именно её показывает ip route (т. е. ip route list table main)
Разумеется, в обоих примерах на серверах надо дополнительно настраивать маршрут в клиентскую сеть через центральный маршрутизатор.
Д/З
В образе есть traceroute и sipcalc.
Задание 4
- Суть: объединить четыре компьютера тремя сетями по простой линейной схеме:
clone ←сеть3→ subrouter ←сеть2→ router ←сеть1→ base
На машинах clone и base — по одному интерфейсу
На машинах subrouter и router — два, там настроить маршрутизацию
Обеспечить доступность между clone и base
- Отчёт (выполнятся с нуля на ненастроенных машинах):
report 4 clone
- Настройка/поднятие интерфейса
- Дополнительные настройки маршрутизации (если нужны)
tcpdump -c4 -i интерфейс udp (должен показать пинги)
report 4 subrouter
- Настройка/поднятие двух интерфейсов
- Дополнительные настройки маршрутизации (если нужны)
report 4 router
- Настройка/поднятие двух интерфейсов
- Дополнительные настройки маршрутизации (если нужны)
report 4 base (выполняется последним)
- Настройка/поднятие интерфейса
- Дополнительные настройки маршрутизации (если нужны)
traceroute -q4 -m3 адрес_clone (должен проходить)
Повторить пинги, но в обратную сторону: собирать дамп пакетов на base, отправлять пакеты с clone.
Четыре отчёта (названия сохранить; должно быть: report.04.base, report.04.clone, report.04.router, report.04.subrouter) переслать одним письмом в качестве приложений на uneexlectures@cs.msu.ru
