This isn't a complete answer, since I'm still working through some of the problems, but here's what I've got so far, trying to deploy a near-identical setup (though for somewhat different reasons).
The good news is: it can be done, within the specs. In fact, the specs were explicitly designed to encourage this sort of subdelegation of prefixes, largely to avoid the need for painful multiple NAT layers while still allowing flexibility in how networks are structured.
The bad news is: there are no "out-of-the-box" single pieces of software that will request a prefix from an upstream, configure addresses and routes locally, and hand out sub-prefixes to downstream networks. Hell, it doesn't even appear possible to wire up pre-existing pieces of software in Linux (without patching) to do what needs to be done. Worst of all, it doesn't look like anyone really cares about this.
What I've got setup and working so far looks like this:
I'm using WIDE DHCPv6 client (dhcp6c
) to request a prefix from the "upstream" network; I chose this client over ISC's DHCP client because, at the time I set it up, it was the only DHCPv6 client that would automatically assign addresses out of the received prefix to other interfaces. I would like to think that other DHCP clients have improved since then, but I couldn't be bothered to check at this point.
Unfortunately, it doesn't expose the delegated prefix details to its external hook script, meaning that you can't (easily) rewrite your "downstream" dhcpd config.
ISC DHCP server (in v6 mode) to assign prefixes to the "downstream" network. I chose this because WIDE's DHCP server, as far as I can tell, can only delegate prefixes statically, not dynamically. It's relatively easy to configure ISC DHCP server to do dynamic prefix delegation, surprisingly; something as simple as this will do the trick:
subnet6 2001:db8:1234:ffff::/64 {
prefix6 2001:db8:1234:a000:: 2001:db8:c0f:aff0:: /60;
}
This will listen on whatever interface has an address in 2001:db8:1234:ffff::/64
and will hand out /60s from the range specified. As long as you can coerce dhcp6c
to update the above config (next!), you can automatically update the dhcpd config when your delegated super-prefix changes.
dhcp6c
will, as previously mentioned, take a script
parameter in its config file, to run when a DHCPv6 response is received. Unfortunately, it only exposes parameters like the SIP server, and DNS resolvers, not useful info like the prefix that's been delegated. So, I've got the following scriptlet to do that for me:
#!/bin/sh
(sleep 3;
base_prefix="$(ip -6 ad sh eth0 | grep 'scope global' | cut -d ' ' -f 6 | cut -d : -f 1-4 | sed 's/00$//')"
if [ "$base_prefix" = "" ]; then
exit 0
fi
cat <<-EOF >/etc/dhcp/dhcpd6.conf
default-lease-time 1800;
max-lease-time 7200;
subnet6 ${base_prefix}00::/64 {
prefix6 ${base_prefix}a0:: ${base_prefix}f0:: /60;
}
EOF
svc -t /etc/service/dhcp6d) &
exit 0
Doing all the work in a sub-shell means that I can wait a little while (the sleep 3
) for the DHCP client to actually configure the interface (it appears to run the script before configuring the interface). It works reliably enough. Note that my ISP delegates me a /56
, hence why I'm only stripping the lasy two zeroes off the received prefix. If you're lucky enough to get a whole /48
, the pipeline to assign base_prefix
would be a lot simpler.
What doesn't already exist, and which I'm pretty sure requires patching source code, is setting up routes when a prefix gets delegated. So far as I can see, no DHCP server has the built-in ability to add the route automatically (I've carefully examined WIDE dhcp6s
, it certainly can't do it, and I can't find anything on the 'tubes to suggest that ISC DHCP does it). There isn't even the ability to run an external command that takes the prefix being delegated and the client's link-local address (ISC DHCP has on commit { execute(...) }
, but no way to get the client's link-local address to pass out).
The problem is that without this crucial bit of functionality, the router that's making the delegation can't know where to route the traffic for the prefix to afterwards. That's a fairly fundamental limitation, and I'm rather stunned that nobody appears to have dealt with this problem before -- or if they have, they're keeping really quiet about it.
I've just developed a patch to ISC DHCP to provide an extra "data expression" to the eval functionality; this allows me to shell out to an external program which can then add/remove routes on prefix allocation and release/expiry; the patch is available at https://github.com/mpalmer/isc-dhcp/commit/4c8ae763bcf83c9068d57a5d9f570690a581b6d6 (against ISC DHCP 4.3.1); I don't have a script to add the route (yet), but I'll probably add it under contrib
in that branch once I get it written.
ADDENDUM: It turns out that further modification was needed to allow routes to be removed again; that has now been added to the client-address-data-expression
branch, along with a small Ruby script that shows how it can all be combined together.
On automatic configuration of IPv6 addresses
Currently, IPv6 automatic configuration (in general) always relies on router discovery based on exchanges of ICMPv6 packets. The basic idea is to get the information about the network from the router to the client. Once the client receives the router advertisement with the information, it will also learn whether to use DHCP and especially whether to use it only for other configuration or also for address configuration. Specific configurations tested with NetworkManager are described in the Fedora Wiki.
Configuring IPv6 with NetworkManager
Since NetworkManager 0.9.6, the IPv6 support in NetworkManager is mostly usable but heavily relies on the limited kernel autoconfiguration features. Since NetworkManager 0.9.10 the IPv6 configuration is fully managed by the userspace and kernel is configured in ways that work much better. Current branch of NetworkManager is 1.0.
The following sections should help you configure a good testing setup of a host with NetworkManager, suitable for debugging similar issues.
Connection configuration
/etc/NetworkManager/system-connections/:
[ipv6]
method=auto
You must not use method=ignore
when you expect your IPv6 connections to work properly. While ignore allows for a limited kernel based IPv6 configuration without DNS and stuff like that, the preferred way is to let NetworkManager handle the IPv6 configuration. We actually hope to remove ignore in the future. There are also [known bugs][1] in the IPv6 autoconfiguration standards that NetworkManager is attempting to work around when method=auto
.
Make sure your firewall is not blocking important packets
For simple testing, make the firewall permissive:
ip6tables -P INPUT ACCEPT
ip6tables -F INPUT
ip6tables -P OUTPUT ACCEPT
ip6tables -F OUTPUT
Make sure you're not using privacy extensions
There have been issues with privacy extensions (also known as temporary addresses) in the past. You're using Linux Mint, which is one of the distributions that turn them on by default.
Note: The issue you are getting is not because of privacy extensions. You can probably skip this section but I'd like to keep it for anyone who might be debugging another issue with similar symptoms.
/etc/sysctl.conf:
net.ipv6.conf.default.use_tempaddr = 0
Normally you would just use all insetad of default but NetworkManager is reading the file and looking for default specifically. This setting should be enough to persuade NetworkManager that we don't want to use privacy extensions for any connections. NetworkManager should now ignore per-connection privacy configuration. Just restart NetworkManager afterwards.
Router solicitation and advertisement timing
From your updated question, I can see that when Networkmanager sends out router solicitation, the router immediately responds with router advertisement, which is good behavior from your host's point of view, as you receive the necessary information. The question is whether it happens always.
Also the router should send out router advertisements regularly, more often than the addresses time out. And your host should probably send out router solicitations when the time out is getting close, just in case you missed information from the router. With your version of NetworkManager, the would be a responsibility of the kernel.
From the other update, it is clear that the router doesn't send the router advertisement as often as it should. The validity of some of the information is as short as 360 seconds but the frequency of router advertisements is up to 600 seconds. The correct configuration would be to deliver you a couple of router advertisments in the 360 seconds time span just in case some of them get lost.
On the other hand, your host should probably ask for the information via router solicitation when the lifetime is about to expire. You can watch for solicitations and advertisements with tcpdump to see whether your kernel sends out a solicitation within roughly six minutes from the last advertisements. If it doesn't, the likely symptom is that your connection will only last for six minutes from the last advertisement, which means six or more minutes since the connection was established.
Recommended router configuration
The standards seem to recommend some values but I will rather use the common sense. On very bad links (which applies to wifi and others) you may lose a number of packets. So I would basically keep all lifetimes at least on good multiples of the maximum router advertisement interval.
Your MaxRtrAdvInterval is 600 seconds which is cool as you'll get updated information every ten minutes or less. The only purpose of MinRtrAdvInterval is to randomize the time a bit, so you can keep it or use 300 seconds for example. All of the lifetimes could be changed to e.g. five times the maximum interval, that would mean 3600 seconds which would mean all the information will be valid for an hour but updated roughly every ten minutes.
Final notes
You may want to contact the vendor to fix the timing in their machines. I don't know whether it's configurable. But changing the file directly will probably not help you as the router will rewrite it when commiting the configuration.
You may also want to contact kernel networking developers to comment on sending the router solicitation. Feel free to include me in any communication.
Best Answer
I got it working. Here's what I did:
ip -o addr
then showed that I had an IPv6 address. Actually, it has a couple of addresses which I don't understand yet./etc/pihole/setupVars.conf
. There I inserted my IPv6 address atIPV6_ADDRESS=2600:1700:(etc)
/etc/pihole/pihole-FTL.conf
, and addedAAAA_QUERY_ANALYSIS=yes
.pihole-FTL
with:systemctl restart pihole-FTL