Cascading routers, dhcpv6 and unwanted EUI64 w/SLAAC on wan6

Look, the confusion obviously stems from the "unwanted SLAAC" part. And I agree that it's misleading, and that at that point I wasn't entirely in the clear yet about what I was looking at. I hadn't for example analyzed yet what my ISP does w/ me, stateful or stateless DHCPv6. Turns out it does the latter, so I do in fact need SLAAC on my ISP side. It just wasn't that obvious to guess from the addresses I obtained because I connect over PPPoE.

So with that - again - settled, let's again refocus on the main matter of concern. The global EUI64 addresses. Privacy. Not broadcasting information about the hardware you run to the Internet. Not provide information about potential attack vectors to the Internet. Etcetera:

And that part most certainly needs fixing.

1 Like

OK...I'm glad we can focus on that...

Now...since the Link Local IPv6 address is derived using this method, how do you suppose it be fixed?

...and still be compliant with this portion of RFC4862:

it is expected that routers will generate link-local addresses using the mechanism described in this document
In addition, routers are expected to successfully pass the
Duplicate Address Detection procedure described in this document on
all addresses prior to assigning them to an interface.

You already admitted it's necessary behavior for the router bordering the ISP, how does that paradigm end for downstream [IPv6] routers?

The odhcp6c client used by OpenWrt currently does not allow suppressing the prefix attribute in received RAs (which is the bit triggering setting of the SLAAC address).

I had a quick chat with @dedeckeh who's maintaining most of the IPv6 parts in OpenWrt nowadays and we came to the conclusion that a "supress SLAAC" option is conceptually possible without violating any RFCs but it does need to be implemented yet.

1 Like

The prefix attribute wouldn't be his issue. It's the 64 bits derived from the MAC address...which relates to the Duplicate Address Detection procedure.

Also, I'm quite certain that stateful DHCPv6 wouldn't be an issue, but as for not violating RFCs, unless you call informational ones violable:

The IPv6 CE router MUST support Stateless Address Autoconfiguration (SLAAC) [RFC4862].


EDIT: This likely isn't a concern, as long as someone doesn't redundantly connect IPv6 routers together with one another and/or the ISP. This is highly unlikely given they're dynamic IP addresses anyways.

Yeah, I noticed that all I get from my ISP is two prefixes, one by RA which is used for configuration of my WAN address, and one by DHCPv6 for delegation to my LAN. Technically you could grab your WAN address from the delegated pool, but the interface identifier part still needed to be autoconfigured in some compliant way. And that's what actually troubled me, the EUI64 autoconfiguration.

So that's what I'd like to have turned off, and I accomplished that by setting


in sysctl.conf. So no MAC address leakage anymore with that setting, which thankfully is left alone by the OpenWrt network configuration software. So the kernel can do its proper work and provide a stable SLAAC address w/o MAC encoding.

1 Like
root@OpenWrt:~# sysctl net.ipv6.conf.default.stable_secret
sysctl: error reading key 'net.ipv6.conf.default.stable_secret': I/O error

sysctl: error reading key 'net.ipv6.conf.eth0.6.stable_secret': I/O error

Message repeats for other interfaces...any ideas?

I think RFC 4862 autoconfiguration, I.e. SLAAC, is useful on misconfigured networks where the router isn't delegated an IPv6 prefix but instead has to use addresses that's on the WAN link for both itself and LAN devices.

With a delegated prefix you have more freedom when assigning addresses to the router. Any address within the prefix assigned to one of the router's interfaces can be used for both incoming and outgoing traffic to the Internet.

1 Like

That just says that the parameter isn't set yet. You have to assign a value that needs to be generated by you, like this

head -c 16 /dev/urandom | xxd -p | sed "s/..../:&/g; s/://"

Take that value, assign it and the error will go away. And I believe a simple restart of an interface will already make it pick up that setting. Can obviously be checked w/

sysctl -a | grep stable_secret

Plus, if you make the setting permanent in sysctl.conf no EUI64 anymore for global/ULA addresses on all your interfaces.

EDIT: and, of course, each such value should be used only for a single host. So if you have multiple routers, like me in my basic test setup, each one has to get its own "secret".

OK...this is what needs to be placed into the OpenWrt request!

I'm also I have to generate this value upon each boot?
And does that mean's it's a 16 byte "secret"?

If so, this definitely needs to be added as a UCI config...I also understand why this is not enabled by default. A lot of embeded devices have issue generating enough cryptographic entropy as it is.

It's normal that you can't read the secret, since it's a secret, but you can SET it no problem.

EDIT: I take it back, I think @rwberger is correct that you can't read the secret because it's not set, but after that you can read it... more info here:

1 Like

No. Generate the value once and then use it for permanent assignment in /etc/sysctl.conf. The 64bit interface identifier is then generated as a hash made from this value plus the interface prefix. So you get a stable interface identifier across reboots, as long as the prefix doesn't change. This not only provides stable identifiers w/o MAC leakage. It also prevents tracking of devices across networks. So compared to IPv4 that's just as good as the dynamic IPv4 address you get from your ISP, in terms of info leakage and trackability.

Yes. 128 (hopefully random) bits.

That's a valid concern. The EUI64 leakage issue still has to be addressed though, if only in terms of mere documentation. The foundation for this "secret" approach is RFC7217, by the way.

PS: the forum software made me wait w/ my reply for 5 hrs, because I'm a new user. Presumably some sort of pedagogic cool-off period. Sorry for the delay.

1 Like

This command isn't there a method to run this - without needing to install xxd or difftools?

Not my speciality, but I would assume that

hexdump -e '16/1 "%02x""\n"'

produces the same output as 'xxd -p'. Where hexdump is part of busybox. I'm just guessing right now though, and would have to check the printf docs again to be sure.

I did, it worked. Now I'm writing a script:

I think this will work:

euisecret=$(head -c 16 /dev/urandom | hexdump -e '16/1 "%02x""\n"' | sed "s/..../:&/g; s/://")
sysctl net.ipv6.conf.default.stable_secret=$euisecret

(I already had sed installed.)


root@OpenWrt:~# sysctl -a | grep stable_secret
sysctl: error reading key 'net.ipv6.conf.6in4-henet.stable_secret': I/O error
sysctl: error reading key 'net.ipv6.conf.all.stable_secret': I/O error
sysctl: error reading key 'net.ipv6.conf.azire_wireguard.stable_secret': I/O error
sysctl: error reading key '': I/O error
sysctl: error reading key '': I/O error
sysctl: error reading key '': I/O error
net.ipv6.conf.default.stable_secret = xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx

Should I configure it for all as well???

You could probably also use

head -c 16 /dev/urandom | hexdump -e '8/2 "%04x:" "\n"'| sed 's/.$//'

That's 8 iterations over 2 byte pairs, printed as 4 hex digits each, where hexdump itself includes the colon. You just have to strip the last colon then, with sed.

I myself did generate the number just once for each host, and stored it in /etc/sysctl.conf. Which is the recommended way if you want to have maximum interface identifier stability with infrequently changing prefixes. Like with ULAs, for example.


Ok, to close this, if I wanted to script the "secret" generation this is the command I would use:

dd if=/dev/urandom bs=16c count=1 2>/dev/null | hexdump -e '8/2 "%04x:" "\n"'| sed 's/:$//'

Why dd instead of head? Because I'm not so sure that head might not come up short if it doesn't get the 16 bytes quickly enough. With dd I'd be more confident that it'll wait - or "hang" - until it really received the requested number of bytes. But that's presumably just me being overcautious.

1 Like

No. This is my /etc/sysctl.conf:

# Defaults are configured in /etc/sysctl.d/* and can be customized in this file
net.ipv6.conf.default.stable_secret = 3380:954f:9799:8de2:7e5c:a416:510c:34b7

and that's it. (Modified the "secret" of course for this post).

Can't remember if I actually tested it, but I believe it doesn't even need a reboot. Just ifdown/ifup of each interface you want to configure that way. The kernel will then pick up the default "secret" and assign it to that interface.

PS: board software delayed me for 2 hours again. Pretty funny.


Interesting stuff!
If have done the following but I am not sure if the outcome is the same as you have mentioned above:

to /etc/sysctl.conf I added


rebooted and the check shows:

sysctl -a | grep stable_secret
sysctl: error reading key 'net.ipv6.conf.all.stable_secret': I/O error = 71c3:0126:4b41:96a4:a98f:5323:5341:2be9
net.ipv6.conf.default.stable_secret = 71c3:0126:4b41:96a4:a98f:5323:5341:2be9
sysctl: error reading key 'net.ipv6.conf.erspan0.stable_secret': I/O error
sysctl: error reading key 'net.ipv6.conf.eth0.stable_secret': I/O error
net.ipv6.conf.eth0.2.stable_secret = 71c3:0126:4b41:96a4:a98f:5323:5341:2be9
sysctl: error reading key 'net.ipv6.conf.eth1.stable_secret': I/O error
net.ipv6.conf.eth1.1.stable_secret = 71c3:0126:4b41:96a4:a98f:5323:5341:2be9
sysctl: error reading key 'net.ipv6.conf.gretap0.stable_secret': I/O error
sysctl: error reading key 'net.ipv6.conf.ifb0.stable_secret': I/O error
sysctl: error reading key 'net.ipv6.conf.ifb1.stable_secret': I/O error
sysctl: error reading key 'net.ipv6.conf.lo.stable_secret': I/O error
sysctl: error reading key 'net.ipv6.conf.sit0.stable_secret': I/O error
net.ipv6.conf.wlan0.stable_secret = 71c3:0126:4b41:96a4:a98f:5323:5341:2be9
net.ipv6.conf.wlan1.stable_secret = 71c3:0126:4b41:96a4:a98f:5323:5341:2be9

The /etc/sysctl.conf still shows one line only. I am running the Netgear R7800

1 Like

Looks the same w/ me. The kernel apparently assigns the default secret only to those devices that are configured to acquire an IPv6 address. And the secret is always the same.

It's then used together with the network prefix to hash together an interface identifier. So that's why the latter is different for different links, because the prefixes differ. But for a single link, as long as the prefix doesn't change the SLAAC configured IPv6 address stays the same across reboots.

1 Like