After almost a year of frustration, I finally solved a super annoying problem with my home network. Since I found it almost impossible to find helpful information about this online, I thought I'd document the problem and solution here for future Googlers. With limited knowledge of IPv6 networking, I ended up literally digging through BSD kernel source code trying to figure out what was happening, but I was eventually able to piece it together.

The Problem

My macOS High Sierra (10.13) laptop would frequently lose its IPv6 address — as often as once a minute — and acquire a new one. This resulted in "connection reset" errors in Chrome, Firefox, and Safari, which broke websites.

It turns out the cause of the problem was that my pfSense home router was sending IPv6 router advertisements specifying a router lifetime value of only 60 seconds. This meant that after 60 seconds, if macOS hadn't seen a new router advertisement yet, it would assume that the IPv6 router prefix of its current IP address had become invalid and it would allocate a new IP, causing any connections using the old IP to be dropped.

Debugging

To see when macOS's IPv6 router prefix expires, you can open Console.app and search for ipv6 router expired. If you see frequent log messages from the configd process saying things like "en0: IPv6 router expired" and "Process IPv6 router expired", then you may be experiencing this problem.

If you're comfortable using the command line, you can run sudo tcpdump -nvvi en0 icmp6 to capture IPv6 router advertisements. Eventually you'll see some output like this:

tcpdump: listening on en0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:46:34.631000 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 136) fe80::1:1 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 136
hop limit 64, Flags [other stateful], pref high, router lifetime 60s, reachable time 0s, retrans time 0s

Look for the "router lifetime" value (in bold above). If it's something small, like "router lifetime 60s", then you may be experiencing this problem.

The Solution

In the pfSense web GUI, visit the DHCPv6 Router Advertisements page by going to Services -> DHCPv6 Server & RA -> Router Advertisements. Type a nice generous number in the Router lifetime field. I chose 1800 since this is the only router on my network and there's no reason its IPv6 prefix should expire often. After editing this field, click Save to save your changes.

I don't know why pfSense's default router lifetime is only 60 seconds. Presumably router advertisements are expected to be sent more frequently than that so it shouldn't be an issue, but for some reason on my network this wasn't happening reliably, which is why I was seeing intermittent connection reset errors. But at least everything's finally working now!