Your embedded device has been running great for the past few weeks, and now all the sudden, it can’t be found on the network. You can’t
ssh into see what the problem is, it has just disappeared.
Lots of reasons why this may have happened, perhaps the program hit a bug and crashed, or more likely, it has forgotten its IPv4 address. Sure you can just “turn it off and on again” and that may fix the problem, or it could make it worse, if it was writing out to the SD Card at the time you pulled power.
The real answer is to log in and find out what is really going on, but as I said, for some reason your Pi, router, or device isn’t responding. So what do you do?
IPv6 to the Rescue
But if you setup your network as a dual-stack network, then your device already has not only an IPv4 address, but also an IPv6 address as well. And if you put the IPv6 address into your local DNS, then you can just
ssh to the hostname, and see what is going on with your device.
But what if you do have a dual-stack network (your ISP is providing IPv6) but you haven’t really done anything with IPv6. How can you use it to rescue your device?
ssh to the IPv6 address of the device, and Bob’s your uncle.
Finding the IPv6 Address of your device
Unlike IPv4 network scanners, scanning IPv6 networks is much more challenging. After all, instead of looking at 254 addresses, you are now looking to scan 18,446,744,073,709,551,616 or 18 quintillion addresses. Assuming that you use the fastest scanner zmap which claims to be able to scan the entire IPv4 internet (all 4 billion addresses) in 45 minutes. With 18 quintillion possible addresses, it is still going to take 367,719 years! (2^32 *45 min / 60 min/ 24 hours/ 365 days). And zmap doesn’t support IPv6 (and you can see why)
Fortunately, there are non-brute-force solutions to the problem.
IPv6 Basics, the all-nodes address
Although there is no broadcast in IPv6, there is a specific multicast address that all nodes must listen to. This is called the all-nodes address, or ff02::1. It is possible to send a ping to the all-nodes address, and get multiple responses back, similar to pinging the IPv4 broadcast address will (used to) return multiple responses.
$ ping6 -c 2 -I wlan0 ff02::1 PING ff02::1(ff02::1) from fe80::f203:8cff:fe3f:f041%wlan0 wlan0: 56 data bytes 64 bytes from fe80::f203:8cff:fe3f:f041%wlan0: icmp_seq=1 ttl=64 time=0.140 ms 64 bytes from fe80::2ac6:8eff:fe16:19d7%wlan0: icmp_seq=1 ttl=64 time=7.32 ms (DUP!) 64 bytes from fe80::21e:6ff:fe33:e990%wlan0: icmp_seq=1 ttl=64 time=7.66 ms (DUP!) 64 bytes from fe80::216:3eff:fea2:94e8%wlan0: icmp_seq=1 ttl=64 time=8.67 ms (DUP!) 64 bytes from fe80::ba27:ebff:fe89:bc51%wlan0: icmp_seq=1 ttl=64 time=9.60 ms (DUP!) 64 bytes from fe80::4aa2:12ff:fec2:16df%wlan0: icmp_seq=1 ttl=64 time=9.73 ms (DUP!) 64 bytes from fe80::216:3eff:feff:2f9d%wlan0: icmp_seq=1 ttl=64 time=10.6 ms (DUP!) 64 bytes from fe80::f203:8cff:fe3f:f041%wlan0: icmp_seq=2 ttl=64 time=0.686 ms --- ff02::1 ping statistics --- 2 packets transmitted, 2 received, +6 duplicates, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.140/6.814/10.696/3.840 ms
In IPv6, multicast addresses are associated with multiple interfaces (there is an all-nodes address on each interface), therefore it is necessary to specify an interface -I to ping.
OK, but how to we find the IPv6 address in my dual-stack network?
Using an open source utility, v6disc.sh, which uses the all-nodes technique discovers the nodes on your IPv6 network in a matter of seconds, rather than years.
$ ./v6disc.sh WARN: avahi utis not found, skipping mDNS check -- Searching for interface(s) -- Found interface(s): eth0 -- INT:eth0 prefixs: 2001:470:db8:101 -- Detecting hosts on eth0 link -- Discovered hosts for prefix: 2001:470:db8:101 on eth0 2001:470:db8:101::1 00:24:a5:f1:07:ca Buffalo 2001:470:db8:101:203:93ff:fe67:4362 00:03:93:67:43:62 Apple 2001:470:db8:101:211:24ff:fece:f1a 00:11:24:ce:0f:1a Apple 2001:470:db8:101:211:24ff:fee1:dbc8 00:11:24:e1:db:c8 Apple 2001:470:db8:101:226:bbff:fe1e:7e15 00:26:bb:1e:7e:15 Apple 2001:470:db8:101::303 d4:9a:20:01:e0:a4 Apple 2001:470:db8:101:3e2a:f4ff:fe37:dac4 3c:2a:f4:37:da:c4 BrotherI 2001:470:db8:101:6a1:51ff:fea0:9339 04:a1:51:a0:93:38 Netgear 2001:470:db8:101:b41f:18a3:a97c:4a0c 10:9a:dd:54:b6:34 Apple 2001:470:db8:101::9c5 b8:27:eb:89:bc:51 Raspberr
The utility looks up the Ethernet MAC address manufacturer and prints it in the third column.
As you can see it is easy to spot the Raspberry Pi on this network.
But wait, I don’t have a dual-stack network, now what?
So you have Shaw for an ISP, and they can’t spell IPv6, now what? Another IPv6 fact is that every device which has an IPv6 stack, must have a link-local address. The link-local address is used for all sorts of things, including Neighbour Discovery Protocol (NDP), the IPv6 equivalent of ARP. Therefore, even if your network doesn’t have an IPv6 connection to the internet, your IPv6-enabled device will have a link-local address.
Fortunately, v6disc.sh also can detect link-local addresses as fast as it detects IPv6 global addresses (in mere seconds).
$ ./v6disc.sh -i wlan0 -L WARN: avahi utis not found, skipping mDNS check -- INT:wlan0 prefixs: -- Detecting hosts on wlan0 link -- Discovered hosts for prefix: fe80: on wlan0 fe80::216:3eff:fea2:94e8 00:16:3e:a2:94:e8 Xensourc fe80::216:3eff:feff:2f9d 00:16:3e:ff:2f:9d Xensourc fe80::21e:6ff:fe33:e990 00:1e:06:33:e9:90 Wibrain fe80::2ac6:8eff:fe16:19d7 28:c6:8e:16:19:d7 Netgear fe80::4aa2:12ff:fec2:16df 48:a2:12:c2:16:df fe80::ba27:ebff:fe89:bc51 b8:27:eb:89:bc:51 Raspberr fe80::f203:8cff:fe3f:f041 f0:03:8c:3f:f0:41 Azurewav -- Pau
Link-local addresses are not globally unique, and therefore an interface must be specified with the -i, and the -L tells v6disc.sh to only detect link-local addresses.
Again, as you can see, it is easy to pick out the Raspberry Pi link-local address on this network.
Now I have the IPv6 address, how do I use it?
With the Global or link-local IPv6 address, all one need to do it
ssh into the lost device and find out what is going on.
If using the link-local address, the interface must also be specified with the %intf notation (e.g. <link-local_addr>%wlan0) :
$ ssh cvmiller@fe80::ba27:ebff:fe79:bc51%wlan0 cvmiller@fe80::ba27:ebff:fe79:bc51%wlan0's password: Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-1030-raspi2 armv7l) Last login: Mon Sep 30 19:57:11 2019 from fe80::2ac6:8eff:fe16:19d7%br0 $
Log in and fix it
And now you are logged into your wayward device, and you can troubleshoot to figure out what went wrong.