How to stop SLAAC from handing out ULA IPv6 to clients?

I'm using an IPv6 prefix filter (wan6) on one of my LAN interfaces to restrict DHCPv6 addresses to my ISP's GUA since my ULA is being used by another interface for NAT6 purposes. This works great (only GUA is assigned) for anything that gets its addresses from DHCPv6 RA, however Android require SLAAC to get an IPv6 address (no GUA is assigned when SLAAC is disabled).

If I enable SLAAC, my Android devices get both the GUA and the ULA that I am trying to avoid. Is there any way to get SLAAC to stop handing out my ULA?

My main concern (security) can be rectified with firewall zones even if the ULA is present on those devices, but I just don't like that they are getting a ULA in the first place, and I'm not sure if it adds overhead to outbound queries. Presumably Android is smart enough to prefer the GUA over the ULA, but I'd rather just manually control this, especially since the ULA isn't a "true" ULA in the context of NAT6 (i.e. it isn't prefixed with "f" and is actually meant to act as a preferred default route on my other VLANs).

SLAAC and ip6class are not connected. If you don't assign a ULA on the interface with ip6class=wan6 then the RA will not contain the ULA prefix.
Post the configuration to make sure you have it right.
uci export network; uci export dhcp; ip -6 addr

1 Like

SLAAC and ip6class are not connected.

Yes, this is what I figured based on my results.

If you don't assign a ULA on the interface with ip6class=wan6 then the RA will not contain the ULA prefix.

Yes, this is exactly what I am doing and it works great for RA, I just need this same functionality applied to SLAAC as well.

package network

config interface 'loopback'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'
	option device 'lo'

config globals 'globals'
	option ula_prefix 'ddc2:9aea:13b1::/48'

config interface 'lan'
	option proto 'static'
	option netmask '255.255.255.0'
	option ipaddr '192.168.1.1'
	option ip6assign '64'
	option ip6ifaceid '::1'
	option ip6hint '1'
	option device 'br-lan'
	list ip6class 'wan6'

config interface 'wan'
	option proto 'dhcp'
	option device 'eth0'

config interface 'wan6'
	option proto 'dhcpv6'
	option reqaddress 'try'
	option reqprefix '56'
	option device 'eth0'
	option ip6table '2'

config interface 'wireguard'
	option proto 'wireguard'
	option private_key 'redacted'
	list addresses '10.65.redacted/32'
	list addresses 'fc00:bbbb:redacted/128'

config wireguard_wireguard
	option persistent_keepalive '25'
	option public_key 'redacted'
	option endpoint_host 'redacted'
	option description 'VPN'
	list allowed_ips '0.0.0.0/0'
	list allowed_ips '::0/0'
	option route_allowed_ips '1'
	option endpoint_port '51820'

config interface 'vpn'
	option proto 'static'
	option ipaddr '192.168.2.1'
	option netmask '255.255.255.0'
	list dns 'redacted'
	option device 'br-vpn'
	option ip6ifaceid '::1'
	option ip6assign '64'
	option ip6hint '2'
	list ip6class 'local'

config interface 'dmz'
	option proto 'static'
	option ipaddr '192.168.3.1'
	option netmask '255.255.255.0'
	option ip6assign '64'
	option ip6ifaceid '::1'
	option ip6hint '3'
	option device 'br-dmz'

config interface 'iot'
	option proto 'static'
	option ipaddr '192.168.4.1'
	option ip6assign '64'
	option ip6hint '4'
	option ip6ifaceid '::1'
	option netmask '255.255.255.0'
	option device 'br-iot'

config device
	option name 'br-lan'
	option type 'bridge'
	option stp '1'
	list ports 'eth1'

config device
	option name 'br-vpn'
	option type 'bridge'
	list ports 'eth1.2'
	option bridge_empty '1'
	option stp '1'

config device
	option name 'br-dmz'
	option type 'bridge'
	list ports 'eth1.3'

config device
	option name 'br-iot'
	option type 'bridge'
	list ports 'eth1.4'

package dhcp

config dnsmasq
	option domainneeded '1'
	option localise_queries '1'
	option rebind_protection '1'
	option rebind_localhost '1'
	option local '/lan/'
	option domain 'lan'
	option expandhosts '1'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
	option localservice '1'
	option sequential_ip '1'

config dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv6 'server'
	option ra 'server'
	list ra_flags 'managed-config'
	list ra_flags 'other-config'
	option ra_management '1'
	option ra_default '1'
	option force '1'

config dhcp 'wan'
	option interface 'wan'
	option ignore '1'
	list ra_flags 'none'

config odhcpd 'odhcpd'
	option maindhcp '0'
	option leasefile '/tmp/hosts/odhcpd'
	option leasetrigger '/usr/sbin/odhcpd-update'
	option loglevel '4'

config dhcp 'vpn'
	option interface 'vpn'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option force '1'
	option ra 'server'
	option dhcpv6 'server'
	list ra_flags 'none'

config dhcp 'VLAN'
	option interface 'VLAN'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option ra 'server'
	option dhcpv6 'server'
	option ra_management '1'

config dhcp 'dmz'
	option interface 'dmz'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option ra 'server'
	option dhcpv6 'server'
	option ra_management '1'
	option force '1'

config host
	option dns '1'
	option ip '192.168.2.10'
	option hostid '10'
	option name 'htpc'
	option mac '00:E0:4C:36:C0:33'

config dhcp 'IOT'
	option interface 'IOT'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option ra 'server'

config dhcp 'iot'
	option interface 'iot'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option force '1'
	list ra_flags 'none'

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2603:9000:redacted/128 scope global dynamic noprefixroute 
       valid_lft 566802sec preferred_lft 566802sec
    inet6 fe80::c453:a4ff:fea0:f935/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 fe80::1c19:3fff:fe86:d83f/64 scope link 
       valid_lft forever preferred_lft forever
19: br-dmz: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2603:9000:redacted/64 scope global dynamic noprefixroute 
       valid_lft 566802sec preferred_lft 566802sec
    inet6 ddc2:9aea:13b1:3::1/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::1c19:3fff:fe86:d83f/64 scope link 
       valid_lft forever preferred_lft forever
21: br-iot: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2603:9000:redacted/64 scope global dynamic noprefixroute 
       valid_lft 566802sec preferred_lft 566802sec
    inet6 ddc2:9aea:13b1:4::1/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::1c19:3fff:fe86:d83f/64 scope link 
       valid_lft forever preferred_lft forever
23: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2603:9000:redacted/64 scope global dynamic noprefixroute 
       valid_lft 566802sec preferred_lft 566802sec
    inet6 ddc2:9aea:13b1:1::1/64 scope global deprecated dynamic 
       valid_lft 3689sec preferred_lft 0sec
    inet6 fe80::1c19:3fff:fe86:d83f/64 scope link 
       valid_lft forever preferred_lft forever
24: br-vpn: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 ddc2:9aea:13b1:2::1/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::1c19:3fff:fe86:d83f/64 scope link 
       valid_lft forever preferred_lft forever
28: wireguard: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 state UNKNOWN qlen 1000
    inet6 fc00:bbbb:redacted/128 scope global 
       valid_lft forever preferred_lft forever

Remove this.

  • The Android needs a Global IP... and a link-local.
  • It is a ULA...I'm not sure how NAT6 is related...I assume that's what it uses...I never deeply studied technologies that went "backwards"

That's on my vpn interface, where I actually want SLAAC/RA ULA (for NAT6). I'm concerned about my lan interface and not exposing it to the NAT6 ULA.

It is a ULA...I'm not sure how NAT6 is related...I assume that's what it uses...I never deeply studied technologies that went "backwards"

NAT6 requires that the ULA be changed from an f* prefix to "something else" (in this case d*) so that clients will pick it up as the default route in the absence of GUA. This is how my vpn interface needs to work since I am assigned a /128 from my provider. I just want my LAN interface to ignore this completely, which is attainable with RA but not SLAAC, apparently. I would disable SLAAC but then I don't get any IPv6 on Android.

So I'm in a catch 22 of NAT6 for my vpn bleeding into my lan because of lack of SLAAC control.

Properly assign the SLACC and do not assign local. Works for me.

Example:

config interface 'lan'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option ip6assign '64'
        option ip6hint '1'
        option ip6ifaceid '::1'
        option device 'br-lan'
        list ip6class 'wan6'
  • I don't think you need an ipv6hint...and I just left your ifaceid
  • Never tested with a dynamic wan6 interface

Could you elaborate, I'm not sure what you mean here.

I don't think you need an ipv6hint...and I just left your ifaceid

I use the hints to provide different IPv6 subnets to my interfaces. I think openwrt would assign them automatically just fine, but I like them to match my IPv4 subnet/VLAN numbering scheme for tidyness. Maybe this is a bad practice.

That's the exact config I'm currently using, unless I'm missing something.

Where is a LAN client receiving the ULA?

Can you show it?

Is there a reason the link-local is not used?

It's on my Android devices connected to lan network.

I get a link-local address on the devices (good), a couple of GUAs (good), and my ULA, i.e. ddc2:9aea:redacted (bad). If I disable SLAAC I don't get GUA or ULA on Android. On my non-android devices on lan I do not get ULA either way (good) so I'm not sure if they just don't use SLAAC at all and/or respect my RA list ip6class 'wan6' setting as intended.

Is there a reason the link-local is not used?

NAT6 requires not using a link-local so devices will actually use the ULA as a default route.

Android needs slaac

And ipv6 dns will break pihole in android, for example.

At least I haven't found a good solution yet.

I not tested NAT6 lately because is broken in snapshot.

But I used 2001:10:: as local

Dhcpv6 work in windows

1 Like

Is there any way to assign a different ULA per interface? Maybe I can use a non-local ULA on vpn for NAT6 and a local ULA on lan so that it is ignored by clients.

You can do it in web gui

Where would I find that option? I can't seem to find anything in the interface settings regarding a custom ULA.

Maybe you have to add a address first

Ipv6 prefix filter should work

"Dhcp" is on lan

Remove local and select your interface

But as @trendy already pointed out, the prefix filter setting doesn't apply to SLAAC (it passes out the ULA and GUA, regardless). I have no problem controlling RA with the prefix filter, that part is working perfectly.

Basically what I am asking is if there is no way to stop SLAAC from giving out the ULA, maybe I can spoof it for that particular interface so it gives out a dummy ULA.

VLAN for androids

If you remove ula address from lan it should not advertise...

But how do I remove it from lan only? I can't see any obvious way to do this. My network is already segmented into VLANs. It's like SLAAC bypasses my interface and grabs the ULA regardless.

You can see lan is not even assigned a ULA, which is great! But SLAAC does not care and gives it to clients anyways.

Last time that I remove ula line, openwrt never boot anymore.

Maybe you should open a issue or do a request

Maybe a dummy ula prefix with low priority if possible

The problem is I need a working non-local ULA for NAT6.

I guess in the meantime I will just have to trust the firewall to handle it using vlan + fw zones and hope that Android "black boxes" prefer GUA to SLAAC ULA. It's just weird that SLAAC can "break out of the interface" to grab a ULA. But if Android would just allow DHCPv6 like everything else on earth this wouldn't even be an issue.

1 Like