My ISP is providing an /56 IPv6 prefix. Now I would like to give static IPv6 addresses to some of my clients with an DHCPv6 Server. I have the following configuration:
Or how an I handle the prefix change from 2003:f7:1234:5678::/56 to 2003:f7:aaaa:bbbb::/56. Have I overseen a setting from dhcpv6 server or is this a current limitation?
Unfortunately, like with many things that involve using the dynamic IPv6 prefix given to you by the ISP, scripting will be required.
But first, don't waste the /56 prefix provided by your ISP in a pool with pool-prefix-length=128. Instead, you should use pool-prefix-length=64 in the DHCP client setting.
Before being able to do that, go to this site to get a random ULA prefix. Let's assume that you got the prefix fdc3:7058:2954::/48. Use it to create a pool:
/ipv6 pool
add name=dhcpv6-ula prefix=fdc3:7058:2954::/80 prefix-length=128
Use that pool for the DHCPv6 server instance telekom-vlan16 instead of pppoe-telekom-dhcpv6-pool. The DHCPv6 server will gives out ULA addresses (instead of addresses with the prefix from the ISP). Also modify this DHCPv6 instance to shorten the lease time from the default 1d to 30 minutes or even shorter at 10 minutes. We don't want to wait up to one day for the clients to change their prefix after the ISP changes the prefix.
Now you can modify the DHCPv6 client, so that it uses pool-prefix-length=64 instead of pool-prefix-length=128 for the pool pppoe-telekom-dhcpv6-pool.
Then, use that pppoe-telekom-dhcpv6-pool pool to announce a /64 prefix from the pool on the interface vlan16-private. That way SLAAC will work on the interface and devices will get dynamic IPv6 addresses for them via SLAAC.
if (1=$"pd-valid") do={
/delay 2;
/system script run update_ipv6_prefix;
};
Go to the IPv6 -> DHCP Server -> Bindings table, that is now populated with bindings with ULA addresses with the fdc3:7058:2954:: prefix. Choose the entries that you want to make static and make them static, edit the suffix part of the addresses to your liking, such as ::0815, but before saving the entries, give them each a comment that must contain the text dynamic prefix "vlan16-private" somewhere in the comment.
Please note that vlan16-private in this case is the name of the interface that has SLAAC active, and that has a /64 prefix assigned from the ISP pool.
Once you have created the static bindings (still all with the ULA prefix), execute the script update_ipv6_prefix at least once. You'll see that all the static bindings now have their prefix changed to the correct prefix from the ISP, matching the prefix assigned to the vlan16-private interface. We'll need the lease time on the client to be at least 50% elapsed before the clients reflect the changes though.
And because the script is called everytime the DHCPv6 client obtains a new prefix, the bindings will have their prefix updated too.
That's how I am assigning GUA addresses from my ISP via DHCPv6 to my devices. The script above was adapted from an old thread on this forum, the original code updated the prefix in address list entries. However, the original author has since edited his post and removed the script content.
Thank you very much @CGGXANNX for your detailed explanation and the scripts. My hope was, that I can avoid scripting and have only overseen some dynamic setting.
After reading your script a few times, I think I have understood the most parts. I already played around with ULA for internal routing/connections. So I have a rough understanding of the ULA concept and configuration.
I have one question which came up when I tried to understand your concept and scripts.
So every device is already getting a dynamic IPv6 /64 address. (which is not relevant for the dhcpv6-server topic. Only for explaining my setup).
Why do I need the ULA address and ULA dhcpv6-server setup from your example? Your script would also work with my /128pppoe-telekom-dhcpv6-pool, right? For example:
The client getting a initial /128 binding.
I change the address once to a /64 address/postfix
Set prefix-pool="".
Set the comment to comment=dynamic prefix "vlan16-private"
When the script runs (in future) it will update the postfix for every binding.
Or have I overseen something? Is there any downside if I would configure it as described above?
Yes, you have . There was a reason why in my previous post I recommended you change the ISP prefix pool to a pool with pool-prefix-length=64 instead of pool-prefix-length=128. You probably changed to pool-prefix-length=128 because otherwise you wouldn't be able to use that pool to allocate DHCPv6 addresses through the DHCPv6 server instance. But doing that and use the same pool to advertise the prefix on the vlan16-private for SLAAC is wrong. Here is the reason:
When you create (either manually, or through the DHCPv6 client instance) an IPv6 pool with prefix-length=n, each time a prefix is requested from the pool, the pool will give out a /n prefix that has not been used, and mark that prefix as used. You can see the list of prefixes that the pools have given out in the IPv6 -> Pool -> Used Prefixes table.
With prefix-length=n the allocated prefixes usually are incremented by 2 ^ (128 - n) from the previous allocation, unless there are conflict with existing used prefixes, then it continues to increment and maybe loop around until a free slot is found (or all have been exhausted).
For example, the ISP gives you a /56 prefix and you creates pool with prefix-length=64, then each time you request a prefix, it increments at the Y position in ----:----:----:--XY:----:----:----:---- and may produce 256 prefixes (through the possible value of XY).
But if you choose prefix-length=128, the pool will allocate prefixes in increment of 1, at that last bit: ----:----:----:--XX:XXXX:XXXX:XXXX:XXXY.
For SLAAC, you normally have to advertise a /64 prefix on the interface (vlan16-private in your case). It's expected that the whole /64 range is used only for that interface. And if you look in the IPv6 -> Routes table, you'll see that RouterOS automatically create a dynamic route with destination to that /64 prefix, having the interface as gateway. This is a connected route with distance=0, scope=10, target-scope=5. It's just like when you add 192.168.88.1/24 to an interface, the IPv4 route table also has the connected route with destination 192.168.88.0/24 automatically created. Those connected route make sure that for all addresses in that subnet (/64 in case of IPv6 with SLAAC), the interface will be used as outgoing gateway if there are no other more precise routes (no /128 route for instance).
only a single /128 prefix has been taken out of the pool as marked as used/reserved. But the full subnet /64 is actually marked as allocated to that interface in the route table. The pool however doesn't know about that. The next time a prefix is requested from the pool, it will only increment the address by 1, and give out a prefix that almost very certainly still part of the same /64 subnet.
What happens when you add more VLANs or bridges or other kind of interfaces to your router (like WG) and want to give them GUA IPv6 prefixes with SLAAC too? If you assign addresses to those interfaces using the same method as above, with from-pool=pppoe-telekom-dhcpv6-pool you'll get something like this:
Here in this example, I have my dhcpv6-ula pool that has prefix-length=128. I've assigned two address entries to my two interfaces containers and vlan60 using from-pool=dhcpv6-ula. In the Used Prefix table, this is what I get:
Two allocations that only differ by the last hex digit. What about the IPv6 -> Addresses table?
Oops, here we have two interfaces that share the same /64 prefix. The addresses of the router on the two interfaces only differ by the last hex digit. But the important part, the prefix /64 that is announced to all the devices, are identical.
What about the connected routes that the router has dynamically created?
Oh! We have two routes with the same destination, same distance, but two different gateways. And there is the + sign, that because we have created two ECMP routes. Not only have we created a situation where devices on two different interfaces get addresses for themselves with the same prefixes as those on the other interface, we've also created a 50-50% chance that when some packet needs to be sent to one of the devices, it doesn't get delivered because ECMP picks the route that sends the packet to the other interface.
For those reasons, when you advertise /64 prefixes on an interface to be used for SLAAC, and get the prefixes from the pool, you have to make sure that the pool has prefix-length ≤ 64, so that the interfaces get distinct, non-overlapping prefixes.
Which means pppoe-telekom-dhcpv6-pool should not have prefix-length=128, but at least prefix-length=64. As a result, you can't use that pool directly in DHCPv6 server instances to give out addresses. And you can't create a pool with prefix-length=128 that use part of the Telekom prefix neither, because RouterOS doesn't allow two IPv6 pools to overlap.
That was the reason for the ULA pool. Of course, if you don't like ULA, and have other GUA ranges (for example, a GUA prefix from Hurricane Electric, then you can create prefix-length=128 pools from those ranges too, with the condition that the ranges of the different pools cannot overlap.
Of course, if you already created static bindings with the correct DUIDs and IAIDs that you want, then you don't need to remove them and let them get ULA bindings again. You just need to set the comments on those existing entries and run the script and the script will also clear the pool reference on those static bindings for you.
Thank you very much again for your detailed explaination. I will play around with your setup and scripts. One reason to have a static IPv6 is to reach internal services like webserver from outside via IPv6. So for my understanding I have also to create script to update related firewall rules.