Ping all IPv6 hosts on a channel

A few days remain before the start of a new stream at the rate "Network engineer" from OTUS. In this regard, we want to share with you a translation of useful material on the topic.

Ping all IPv6 hosts on a channel

IPv6 Ping (ICMPv6 Echo Request/Echo Reply) Tips and Tricks Blog Series

Note that I'm using Linux (specifically Fedora 31), however the ping command syntax for other operating systems should hopefully be very similar.

Ping all IPv6 hosts on a channel

The first and easiest tip is to ping all IPv6 hosts on the link.

IPv6 uses multicast addresses for all types of one-to-many communications. There are no broadcast (or broadcast) IPv6 addresses. This distinguishes IPv6 from IPv4, where there are several types of broadcast addresses, such as the "limited broadcast" address 255.255.255.255 [RFC1122].

However, there is an β€œall-nodes multicast” IPv6 address, so we will use it to ping all IPv6 nodes in the link. (A "broadcast" address is really just a specially named multicast address, which is a multicast group that includes all nodes. Note that, for example, the "group" or multicast address bit is turned on in Ethernet broadcast addresses at the link layer).

All-nodes multicast IPv6 address for channel: ff02::1. ff denotes a multicast IPv6 address. The next 0 is the part of the flag with the bits not set.

Next 2 defines the scope of the multicast group. Unlike IPv4 multicast addresses, IPv6 multicast addresses have a scope. The scope value specifies the part of the network over which the multicast packet is allowed to be sent. Once a packet reaches the boundary of the specified scope, the packet MUST be discarded, regardless of whether its Hop Count field is non-zero. Of course, if the hop count reaches zero before reaching the specified multicast group boundary, it is also reset immediately. Here is a complete list of scope IPv6 multicasts.

Finally, the ::1 specifies an all-nodes multicast group.

About the address ff02::1 it should be noted that it is ambiguous. On an IPv6 host with multiple interfaces, such as a router or multihomed host, the address ff02::1 there is nothing to tell which interface to send ICMPv6 echo requests or wait for ICMPv6 echo replies when they arrive. ff02::1 is valid and can be used on any of the interfaces and channels attached to the multi interface node.

Therefore, when we ping all IPv6 nodes on the link, we need to somehow also tell the utility ping for IPv6 which interface to use.

Interface Definition - Command Line Option

As we have seen, the all-nodes multicast address we want to use is ff02::1 - Provides no information on which interface to send and receive ICMPv6 echo request and echo reply packets.

So, how do we specify the interface that will be used for the multicast address space or unicast Link-Local address space?

The first and most obvious way is to provide it as a parameter to the application we are using.

For utility ping we provide it via option -I.

[mark@opy ~]$ ping -w 1 -I enp3s2 ff02::1
ping: Warning: source address might be selected on device other than: enp3s2
PING ff02::1(ff02::1) from :: enp3s2: 56 data bytes
64 bytes from fe80::1d36:1fff:fefd:82be%enp3s2: icmp_seq=1 ttl=64 time=0.438 ms
64 bytes from fe80::f31c:ccff:fe26:a6d9%enp3s2: icmp_seq=1 ttl=64 time=0.589 ms (DUP!)
64 bytes from fe80::7e31:f5ff:fe1b:9fdb%enp3s2: icmp_seq=1 ttl=64 time=5.15 ms (DUP!)
64 bytes from fe80::f7f8:15ff:fe6f:be6e%enp3s2: icmp_seq=1 ttl=64 time=58.0 ms (DUP!)
64 bytes from fe80::877d:4ff:fe1a:b881%enp3s2: icmp_seq=1 ttl=64 time=62.3 ms (DUP!)
64 bytes from fe80::877d:4ff:fe1a:ad79%enp3s2: icmp_seq=1 ttl=64 time=62.8 ms (DUP!)
 
--- ff02::1 ping statistics ---
1 packets transmitted, 1 received, +5 duplicates, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.438/31.544/62.786/29.566 ms
[mark@opy ~]$

With this all-nodes multicast ping, we received responses from 6 IPv6 nodes. Responses came from host Link-Local IPv6 addresses starting with prefix fe80::/10.

That ping didn't keep sending ICMPv6 echo requests indefinitely until we abort it, we usually specify the number of packets to send via the -c option. However, this also prevents ping from accepting and displaying more than one ICMPv6 echo reply when sending an ICMPv6 multicast echo request. Instead, we used the -w option to specify that ping should end after 1 second, no matter how many ICMPv6 pings or pings were sent or received.

Another thing to watch out for is (DUP!) output on the second and subsequent answers. These packets are identified as duplicate responses because they have the same ICMP sequence value as the individual ICMPv6 echo requests that were sent in the first place. They appear because a multicast ICMPv6 echo request results in multiple individual unicast responses. The number of duplicates is also indicated in the statistics summary.

Interface Definition - Zone ID

Another way to provide an interface to use is as part of an IPv6 address parameter.

We can see an example of this in the ping output, where the addresses of the responding IPv6 hosts also have the suffix %enp3s2, For example:

64 bytes from fe80::1d36:1fff:fefd:82be%enp3s2: icmp_seq=1 ttl=64 time=0.438 ms

This way of specifying interfaces is formally described in [RFC4007], "Architecture with Specified IPv6 Addresses". Although commonly referred to as an operating system interface, they actually define something more general - a "zone" or "scope".

The reason for having more general scopes or scopes is that, as mentioned in [RFC4007], an IPv6 node can have several different IPv6 interfaces connected to the same link. These interfaces are members of the same zone.

It should be possible to group multiple interfaces within a zone under an operating system; Currently I don't know if this is possible under Linux and how to do it.

Using the suffix %<zone_id>, we can remove the command line option -I ping.

[mark@opy ~]$ ping -w 1 ff02::1%enp3s2
PING ff02::1%enp3s2(ff02::1%enp3s2) 56 data bytes
64 bytes from fe80::2392:6213:a15b:66ff%enp3s2: icmp_seq=1 ttl=64 time=0.106 ms
64 bytes from fe80::1d36:1fff:fefd:82be%enp3s2: icmp_seq=1 ttl=64 time=0.453 ms (DUP!)
64 bytes from fe80::f31c:ccff:fe26:a6d9%enp3s2: icmp_seq=1 ttl=64 time=0.606 ms (DUP!)
64 bytes from fe80::7e31:f5ff:fe1b:9fdb%enp3s2: icmp_seq=1 ttl=64 time=6.23 ms (DUP!)
64 bytes from fe80::f7f8:15ff:fe6f:be6e%enp3s2: icmp_seq=1 ttl=64 time=157 ms (DUP!)
64 bytes from fe80::877d:4ff:fe1a:ad79%enp3s2: icmp_seq=1 ttl=64 time=159 ms (DUP!)
64 bytes from fe80::877d:4ff:fe1a:b881%enp3s2: icmp_seq=1 ttl=64 time=161 ms (DUP!)
64 bytes from fe80::23d:e8ff:feec:958c%enp3s2: icmp_seq=1 ttl=64 time=179 ms (DUP!)
 
--- ff02::1%enp3s2 ping statistics ---
1 packets transmitted, 1 received, +7 duplicates, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.106/82.858/179.216/81.281 ms
 
[mark@opy ~]$

Link-Local address responses

From this all-nodes multicast ping, we received a total of 6 unique responses.

These responses came from unicast Link-Local addresses of IPv6 nodes. For example, here is the first response:

64 bytes from fe80::2392:6213:a15b:66ff%enp3s2: icmp_seq=1 ttl=64 time=0.106 ms

Unicast Link-Local IPv6 addresses are required on all IPv6-enabled interfaces [RFC4291], "IP Addressing Architecture Version 6". The reason for this is that an IPv6 host always automatically has a unicast IPv6 address that it can use to at least communicate with other hosts over its directly connected links. This includes communicating with applications on other hosts via the Link-Local addresses of the hosts.

This simplifies the design and implementation of protocols such as IPv6 Neighbor Discovery and OSPFv3. It also allows end user applications on hosts to communicate over the link without requiring any other supporting IPv6 infrastructure on the link. Direct communication between connected IPv6 hosts does not require an IPv6 router or DHCPv6 server in the connection.

Link-Local addresses start with a 10-bit prefix fe80, followed by 54 bits of zeros and then a 64-bit interface identifier (IID). In the above first answer 2392:6213:a15b:66ff is a 64-bit IID.

Looped Multicast

By default, multicast packets are returned internally to the host that sent them. This happens for both IPv6 and IPv4 addressing.

The reason for this default behavior is that when sending multicast packets, there may also be a listening local multicast application running on the sending host itself, as well as somewhere on the network. This local application must also receive multicast packets.

We can see this multicast local loop in our ping output:

[mark@opy ~]$ ping -w 1 ff02::1%enp3s2
PING ff02::1%enp3s2(ff02::1%enp3s2) 56 data bytes
64 bytes from fe80::2392:6213:a15b:66ff%enp3s2: icmp_seq=1 ttl=64 time=0.106 ms
64 bytes from fe80::1d36:1fff:fefd:82be%enp3s2: icmp_seq=1 ttl=64 time=0.453 ms (DUP!)
...

The first and fastest response (0,106ms compared to 0,453ms) comes from the Link-Local address configured on the interface itself enp3s2.

[mark@opy ~]$ ip addr show dev enp3s2 | grep fe80
    inet6 fe80::2392:6213:a15b:66ff/64 scope link noprefixroute 
[mark@opy ~]$

Utility ping provides a way to suppress local multicast feedback using the parameter -L. If we send an all-nodes multicast ping with this flag, then the responses are limited to remote nodes. We do not receive a response from the Link-Local address of the sender's interface.

[mark@opy ~]$ ping -L -w 1 ff02::1%enp3s2
PING ff02::1%enp3s2(ff02::1%enp3s2) 56 data bytes
64 bytes from fe80::1d36:1fff:fefd:82be%enp3s2: icmp_seq=1 ttl=64 time=0.383 ms
 
64 bytes from fe80::f31c:ccff:fe26:a6d9%enp3s2: icmp_seq=1 ttl=64 time=0.467 ms (DUP!)
...

Ping Link-Local Addresses

As you might guess, unicast Link-Local addresses by themselves also don't provide enough information to indicate which interface to use to reach them. As with the all-nodes multicast ping, we also need to specify the interface as a command line parameter ping or a zone ID with an address when pinging Link-Local addresses.

This time we can use -cto limit the number of packets and responses sent and received ping, since we're doing a unicast ping.

[mark@opy ~]$ ping -c 1 fe80::f31c:ccff:fe26:a6d9%enp3s2
 
PING fe80::f31c:ccff:fe26:a6d9%enp3s2(fe80::fad1:11ff:feb7:3704%enp3s2) 56 data bytes
64 bytes from fe80::f31c:ccff:fe26:a6d9%enp3s2: icmp_seq=1 ttl=64 time=0.395 ms
 
--- fe80::f31c:ccff:fe26:a6d9%enp3s2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.395/0.395/0.395/0.000 ms
[mark@opy ~]$

Ping (all) other IPv6 addresses?

In this article, we saw how to ping all IPv6 nodes on a channel using an all-nodes multicast IPv6 address. ff02::1. We also saw how to specify which interface to use with an all-nodes multicast IPv6 address, since the address itself cannot provide this information. We used either the command line option ping, or specified interface via suffix %<zone_id>.

We then learned about unicast Link-Local addresses, which are the addresses used to respond to all-nodes multicast ICMPv6 echo requests.

We have also seen how multicast packets are returned to the default sending host and how to disable this for the utility. ping.

Finally, we pinged a single Link-Local address using the suffix %<zone_id>, since Link-Local addresses by themselves also do not provide information about the outgoing interface.

So what about pinging all other nodes and getting their Global Unicast Addresses (GUAs) (i.e. their public addresses on the Internet) or their Unique Local Unicast Addresses (ULAs)? We will cover this in the next blog post.

That's all.

You can find out more about our course at open house records.

Source: habr.com

Add a comment