Spent some time this weekend working to make my network IPv6-first. Meaning IPv6-only wherever possible with DNS64/NAT64 for IPv4 connectivity, but I ran into some challenges with how Unraid selects its management address. Sorry for the book, just trying to be as complete as possible.
Goal: Unraid server with an IPv6-only management/host interface that has privacy extensions enabled and a listening IP that is a stable-private ULA (although all of this would apply to a dual-stack interface as well).
Challenge: When multiple IP addresses are configured on an interface via SLAAC (GUA and ULA in this case) Unraid seems to be designed to only use one IPv6 address and there is no way to select which address that is. Further, enabling privacy extensions does not enable stable-privacy so even the non-temporary address could change with reboots etc.
Desired State: Enabling privacy extensions on an interface also enables stable private addressing (RFC 7217). Web GUI provides a “Prefer GUA/Prefer ULA” toggle. I don't personally have a need for the server to listen on GUA and ULA at the same time but I could see that as a desirable configuration as well.
Possible intermediate solution/Questions: I did some digging through the boot and service restart scripts and have put some notes below. Ultimately I have two questions: Is there a reason to suspect implementing the below changes via a plugin or a user script will break anything? Are there any plans to enhance the IPv6 address selection process? Since address selection occurs before plugins are loaded and updating the address after the system initializes requires restarting all the listening services it seems better implemented in the base OS.
Notes:
Unraid seems to just grab the last ip address listed. What's the reason behind this selection? Is the permanent address always listed second with ip a? I couldn't find info on the default sort order for the command.
/usr/local/sbin/create_network_ini (Line 144)
NET6=($(ip -br -6 addr show $IFACE scope global|awk '{sub("/"," ",$NF);print $NF;exit}'))
Possible command for a "Prefer ULA" option
ip --json -6 addr show dev $IFACE | jq -r '.[0].addr_info[] | select((.scope == "global") and (.temporary != true) and (.local | test("^fc|fd"))) | "\(.local) \(.prefixlen)"'
It looks like /var/local/emhttp/network.ini could be updated by a script/plugin and /usr/local/emhttp/plugins/dynamix/scripts/reload_services could be called to use the new address but /etc/rc.d/rc.library.source also only checks for one IP.
/etc/rc.d/rc.library.source (Line 103)
min6 $(max6 $(wipe $*)|sort|head -1)
Conclusion:
My rough outline for configuration from a plugin/script standpoint would be:
Enable unraid privacy extensions option on the interface
Generate a stable secret to store in flash and assign to net.ipv6.conf.default.stable_secret
Update /etc/rc.d/rc.library.source to check the configured IP matches any IP assigned to the interface.
Update /var/local/emhttp/network.ini with the desired IP(s)
Run /usr/local/emhttp/plugins/dynamix/scripts/reload_services to reload services
I've started testing some of this but my server also decided to start it's parity check this afternoon and I don't have a dev server right now so I figured it was a good time to take a break and make sure I'm not going to completely break things. I realize mucking this low into the config could have unintended consequences but I do believe supporting this kind of setup is the way forward for IPv6.