Как реализовать локальное обнаружение соседа ICMPv6?

Я реализую свой собственный сетевой стек IPv6, и у меня возникают проблемы с работой обнаружения соседей ICMPv6. Стек работает путем захвата пакетов существующего интерфейса, выбора адресованных ему пакетов и отправки новых пакетов с "виртуального" адреса стека.

Чтобы проверить это, у меня есть машина Ubuntu с контейнером LXC, используемым в качестве клиента тестирования для отправки трафика. Хост Ubuntu имеет следующий мостовой интерфейс для контейнеров LXC:

ubuntu:~$ ifconfig
...
lxcbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.3.1  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::216:3eff:fe00:0  prefixlen 64  scopeid 0x20<link>
        ether 00:16:3e:00:00:00  txqueuelen 1000  (Ethernet)
        RX packets 522282  bytes 85867541 (85.8 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 554574  bytes 51636337 (51.6 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
...

Контейнер имеет следующий сетевой интерфейс:

my-continer:~$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.3.40  netmask 255.255.255.0  broadcast 10.0.3.255
        inet6 fe80::216:3eff:fe72:dc1c  prefixlen 64  scopeid 0x20<link>
        ether 00:16:3e:72:dc:1c  txqueuelen 1000  (Ethernet)
        RX packets 554722  bytes 51647709 (51.6 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 522297  bytes 93181219 (93.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
...

Если я пропингую хост Ubuntu из контейнера LXC, он, конечно, работает:

my-continer:~$ sudo tcpdump -i eth0 -nn icmp6 -vv
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

11:56:44.435633 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::216:3eff:fe72:dc1c > ff02::1:ff00:0: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::216:3eff:fe00:0
          source link-address option (1), length 8 (1): 00:16:3e:72:dc:1c
            0x0000:  0016 3e72 dc1c
11:56:44.435649 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::216:3eff:fe00:0 > fe80::216:3eff:fe72:dc1c: [icmp6 sum ok] ICMP6, neighbor advertisement, length 32, tgt is fe80::216:3eff:fe00:0, Flags [solicited, override]
          destination link-address option (2), length 8 (1): 00:16:3e:00:00:00
            0x0000:  0016 3e00 0000
11:56:44.435652 IP6 (flowlabel 0x4fb04, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::216:3eff:fe72:dc1c > fe80::216:3eff:fe00:0: [icmp6 sum ok] ICMP6, echo request, seq 1
11:56:44.435660 IP6 (flowlabel 0xbb56b, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::216:3eff:fe00:0 > fe80::216:3eff:fe72:dc1c: [icmp6 sum ok] ICMP6, echo reply, seq 1
11:56:45.465749 IP6 (flowlabel 0x4fb04, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::216:3eff:fe72:dc1c > fe80::216:3eff:fe00:0: [icmp6 sum ok] ICMP6, echo request, seq 2
11:56:45.465768 IP6 (flowlabel 0xbb56b, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::216:3eff:fe00:0 > fe80::216:3eff:fe72:dc1c: [icmp6 sum ok] ICMP6, echo reply, seq 2
11:56:46.490187 IP6 (flowlabel 0x4fb04, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::216:3eff:fe72:dc1c > fe80::216:3eff:fe00:0: [icmp6 sum ok] ICMP6, echo request, seq 3
11:56:46.490204 IP6 (flowlabel 0xbb56b, hlim 64, next-header ICMPv6 (58) payload length: 64) fe80::216:3eff:fe00:0 > fe80::216:3eff:fe72:dc1c: [icmp6 sum ok] ICMP6, echo reply, seq 3

Мой собственный стек настроен с MAC-адресом 0c:22:38:4e:9a:bc и адрес IPv6 fe80::216:3eff:fe00:1234,

Реализация в Erlang, и код для обработки пакета запроса соседнего узла выглядит следующим образом:

process(#ipv6{headers = [#icmpv6{type = neighbor_solicitation, payload = {IP6, _}}|_]} = Packet, {IP6, Mac}) ->
    #ipv6{src = Src} = Packet,
    send(#ipv6{
        src = IP6,
        dst = Src,
        next = ?IP_PROTO_ICMPv6,
        hlim = 16#FF,
        headers = [
            {icmpv6, #icmpv6{
                type = neighbor_advertisement,
                code = 0,
                payload = {IP6, #{source_link_layer_addr => Mac}}
            }}
        ]
    });

Packet является запросом входящего соседа и {IP6, Mac} IPv6-адрес и mac-адрес, с которыми был настроен стек.

При проверке пакетов пакеты достигают интерфейса на хосте и попадают в libpcap. Я генерирую ответ на разрешение адреса, но проверка никогда не выполняется:

my-continer:~$ ping6 -I eth0 fe80::216:3eff:fe00:1244
PING fe80::216:3eff:fe00:1244(fe80::216:3eff:fe00:1244) from fe80::216:3eff:fe72:dc1c%eth0 eth0: 56 data bytes
From fe80::216:3eff:fe72:dc1c%eth0 icmp_seq=1 Destination unreachable: Address unreachable
From fe80::216:3eff:fe72:dc1c%eth0 icmp_seq=2 Destination unreachable: Address unreachable
From fe80::216:3eff:fe72:dc1c%eth0 icmp_seq=3 Destination unreachable: Address unreachable
^C
--- fe80::216:3eff:fe00:1244 ping statistics ---
4 packets transmitted, 0 received, +3 errors, 100% packet loss, time 3065ms

Трассировка показывает, что соседние рекламные пакеты достигают контейнера:

my-continer:~$ sudo tcpdump -i eth0 -nn icmp6 -vv
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

12:04:23.751427 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::216:3eff:fe72:dc1c > ff02::1:ff00:1234: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::216:3eff:fe00:1234
          source link-address option (1), length 8 (1): 00:16:3e:72:dc:1c
            0x0000:  0016 3e72 dc1c
12:04:23.753662 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::216:3eff:fe00:1234 > fe80::216:3eff:fe72:dc1c: [icmp6 sum ok] ICMP6, neighbor advertisement, length 32, tgt is fe80::216:3eff:fe00:1234, Flags [solicited, override]
          source link-address option (1), length 8 (1): 0c:22:38:4e:9a:bc
            0x0000:  0c22 384e 9abc
12:04:24.761850 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::216:3eff:fe72:dc1c > ff02::1:ff00:1234: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::216:3eff:fe00:1234
          source link-address option (1), length 8 (1): 00:16:3e:72:dc:1c
            0x0000:  0016 3e72 dc1c
12:04:24.765901 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::216:3eff:fe00:1234 > fe80::216:3eff:fe72:dc1c: [icmp6 sum ok] ICMP6, neighbor advertisement, length 32, tgt is fe80::216:3eff:fe00:1234, Flags [solicited, override]
          source link-address option (1), length 8 (1): 0c:22:38:4e:9a:bc
            0x0000:  0c22 384e 9abc
12:04:25.786994 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::216:3eff:fe72:dc1c > ff02::1:ff00:1234: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has fe80::216:3eff:fe00:1234
          source link-address option (1), length 8 (1): 00:16:3e:72:dc:1c
            0x0000:  0016 3e72 dc1c
12:04:25.789413 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::216:3eff:fe00:1234 > fe80::216:3eff:fe72:dc1c: [icmp6 sum ok] ICMP6, neighbor advertisement, length 32, tgt is fe80::216:3eff:fe00:1234, Flags [solicited, override]
          source link-address option (1), length 8 (1): 0c:22:38:4e:9a:bc
            0x0000:  0c22 384e 9abc

Они выглядят идентичными тем, которые отправляются в реальный интерфейс и из него, за исключением самих адресов.

Проверка таблицы маршрутизации показывает, что разрешение адреса для виртуального адреса по какой-то причине не работает:

my-continer:~$ sudo ip -6 neigh
fe80::216:3eff:fe00:0 dev eth0 lladdr 00:16:3e:00:00:00 STALE
fe80::216:3eff:fe00:1234 dev eth0  FAILED

В чем причина неудачного обнаружения соседей здесь? Чего не хватает в моей реализации протокола ICMPv6, чтобы заставить контейнер принимать виртуальный адрес в качестве допустимого маршрута?

0 ответов

Другие вопросы по тегам