Back in early June I started getting emails from updown.io warning me of IPv6 ping issues to my CHR edge router. I didn’t notice anything wrong, and everything seemingly worked just fine, so I muted the alarm and did summer stuff instead.

Lately I’ve noticed that wget and curl, when IPv6 was used, would often time out — not always, about half the time.

Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
Resolving kroki.io (kroki.io)... 2606:4700:3036::6815:1d99, 2606:4700:3033::ac43:956b, 104.21.29.153, ...
Connecting to kroki.io (kroki.io)|2606:4700:3036::6815:1d99|:443... failed: Network is unreachable.

I checked my IPv6 default routes and noticed there were two:

sigma ➜ ~ ip -6 route show default
default proto ra metric 20100 pref medium
nexthop via fe80::be24:xxxx:xxxx:xxxx dev enp7s0 weight 1
nexthop via fe80::7a9a:xxxx:xxxx:xxxx dev enp7s0 weight 1

Which is a bit odd, since I only have one router. One was my CHR edge router, but the other was a MikroTik CRS310 switch!? What! Why? The two routes with the same weight do explain why half my IPv6 packets were failing.

I have several MikroTik switches running RouterOS, but only the CRS310 was announcing itself as an IPv6 router. There was one difference though, the CRS310 was running RouterOS 7.23.1, while the others were running 7.22.1.

Some internet investigations revealed that RouterOS 7.23 changed how Router Advertisements are triggered:

ipv6,ra - fixed sending only DNS or MTU when prefix is set to "none";MikroTik v7.23 Release Notes

Prior to 7.23, RouterOS stayed silent unless a prefix was configured under /ipv6/nd/prefix. In 7.23, MikroTik changed this: the default /ipv6/nd rule (interface=all) now broadcasts RAs unconditionally — turning any switch running defaults into an accidental default gateway (detailed in the MikroTik forum thread).

On my CRS310 I turned off IPv6 forwarding, and disabled the neighbour discovery rule for all interfaces.

/ipv6/settings/set forward=no
/ipv6/nd/set [find] disabled=yes

Then flushed the routes:

sudo ip -6 route flush cache

But NetworkManager still remembered the RA from CRS310, so I waited for the RA lifetime of 1800 seconds to expire.

And sure enough, after that I had only one IPv6 default route. And! Suddenly my updown.io check stopped timing out.

Updown monitor showing last 24 hours

Clearly the CHR had accepted the CRS310 announcements and added them to its routing table, causing half of the ping responses to fail.

Updown monitor showing last 6 months