IPv6 and unboud/stubby/dnscrypt-proxy


In this topic, I entered a screenshot of the different resolvers behind dnsmasq. As you can see and read, by using the hosts file, the name of each resolver is next to the graph, so I can exactly see witch resolver made dnsmasq happy. That is the goal, don’t lose track of it, when proposing solutions!

I’ve finally got my provider to exchange my docsis v2 modem for a v3 (no firewall/router/wifi - I’ve got a pfsense box to handle that), and after some hick ups, I’ve got a Global Unique address on my pi (PD 56 on the WAN, ‘track interface’ on the LAN adapters.

In the topic, mentioned earlier, you can see I’ve assigned a unique IPv4 address to each of the different resolvers, e.g. (unbound), (stubby) and (dnscrypt-proxy). This allowed me to modify the hosts file, as a result, the names are displayed with the graph. Raspian, my OS, seems to handle the routing between dnsmasq and the resolvers. If I traceroute the addresses of the resolvers, the request doesn’t even leave the pi, example:

traceroute to (, 30 hops max, 60 byte packets
 1 (  0.124 ms  0.042 ms  0.037 ms

Reading up on IPv6, I found an article that claimes, you can safely use a Local Unique Address to achieve having a unique address for the IPv6 resolvers, so I configured fd12:3456:789a:1::15b0 (unbound), fd12:3456:789a:1::15b1 (stubby) and fd12:3456:789a:1::15b2 (dnscrypt-proxy)

The intention, again, is to add these addresses to the hosts file to identify the different resolvers.

However, traceroute and the firewall shows the pi is now attempting to find the resolvers, using a route, witch is of course NOT defined.

traceroute fd12:3456:789a:1::15b1
traceroute to fd12:3456:789a:1::15b1 (fd12:3456:789a:1::15b1), 30 hops max, 80 byte packets
 1  2a02:1810:4d02:5602:20e:c4ff:fecf:f3cf (2a02:1810:4d02:5602:20e:c4ff:fecf:f3cf)  0.451 ms  0.300 ms  0.224 ms
 2  * * *
 3  * * *

The question (finally):
Is it possible (probably) to configure Raspbian to allow dnsmasq to find the resolvers on their respective IPv6 addresses, without having to revert to adding routes on the pfsense box, just like IPv4. This probably requires IPv6 routing configuration on the pi, but helas, I can’t find any web page that indicates how to achieve this.
If at all possible, the solution should avoid to use the GUA of the pi, since, according to the pfsense NDP table, the address is NOT permanent.


found the article regarding the ‘fd’ IPv6 network, added the link


One all-nighter later… I figured it out. It may not be the perfect solution, eager to read better solutions here.

On an IPv4 system, it looks like (correct me if I’m wrong) the address range 127.x.x.x simply exists. therefore a daemon, such as unbound, stubby and dnscrypt-proxy can be configured using these addresses without any further action to make it work. I’ve been using, and, but it looks like you can use whatever you like, as long as it starts with 127.

On an IPv6 system, it turns out there is no such thing. you can only use 0::1, but as I stated, I really wanted to be able to see the different resolvers in the graph.

The solution:
In order to be able to use an ‘fd’ address in the configuration, you need to ensure the address exists, otherwise the daemon cannot bind to it.

To add the address, simply enter the following command:

sudo ip -6 addr add fd12:3456:789a:1::15b0/128 dev eth0

You can verify the command was successful by checking the ‘ifconfig’ output:

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet netmask broadcast
inet6 fd12:3456:789a:1::15b0 prefixlen 128 scopeid 0x0
inet6 fe80::3703:77df:647a:75ec prefixlen 64 scopeid 0x20
inet6 2a02:1810:4d02:5602:1481:87d2:f08e:23b5 prefixlen 64 scopeid 0x0
ether b8:27:eb:a8:38:c7 txqueuelen 1000 (Ethernet)
RX packets 20463 bytes 4909000 (4.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 22475 bytes 7118580 (6.7 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

As you can see, there are now 3 inet6 entries, there were only 2 before you added one.
All you need to do now is ensure your resolver is configured to use the address, example unbound:

interface: fd12:3456:789a:1::15b0@5552

and restart the resolver, e.g. example for unbound:

sudo service unbound restart

For unbound, some additional changes are required in the configuration, dnscrypt-proxy and stubby seem to work with the configurations here:

‘do-ip6: no’ needs to be changed into ‘do-ip6: yes
access-control: fd12:3456:789a:1::15b0/128 allow’ needs to be added.

After updating the hosts files (add the new addresses and names) and updating the servers (edit /etc/dnsmasq.d/01-pihole.conf, or simply put your resolvers in a different file, so pihole -r or pihole -up want overwrite them), you need to restart dnsmasq (sudo service dnsmasq restart).
Result: see the graph above.

There is still one catch to this. The IPv6 address we added will disappear when you reboot the system. I’ve been reading and testing various solutions (add a file in /etc/network/interfaces.d/ - no result, edit /etc/dhcpcd.conf - no result) and finally found this document, so I modified /etc/rc.local. The content:

_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
sudo ip -6 addr add fd12:3456:789a:1::15b0/128 dev eth0
sudo ip -6 addr add fd12:3456:789a:1::15b1/128 dev eth0
sudo ip -6 addr add fd12:3456:789a:1::15b2/128 dev eth0
exit 0

Adding the 3 lines to this file, made the system add these IPv6 addresses at reboot, so the daemons could bind to them.
I’m sure this is NOT the best solution, but since I couldn’t get anything else to work …
If you have a better solution, eager to find out.

If you have configured all of the resolvers, as described here, you can now test your resolvers with these dig commands:

dig @ -p 5552 +dnssec www.raspberrypi.org
dig @ -p 5553 +dnssec www.raspberrypi.org
dig @ -p 5554 +dnssec www.raspberrypi.org
dig @fd12:3456:789a:1::15b0 -p 5552 +dnssec www.raspberrypi.org
dig @fd12:3456:789a:1::15b1 -p 5553 +dnssec www.raspberrypi.org
dig @fd12:3456:789a:1::15b2 -p 5554 +dnssec www.raspberrypi.org

They should all produce the same result (I’m lucky, they do…)

@DL6ER When I was testing, to find a working solution, I enabled only one resolver in dnsmasq, this to ensure I wasn’t getting DNS responses from another resolver. I noticed the graph changed, even if the resolver did not provide an answer. I could submit hundreds of queries to a non working resolver, yet the percentage for that resolver still increased.


Unbound, stubby or dnscrypt-proxy

Erm, sure, but this is what you would expect, no? After all it is a statistic about to which forward destinations a query got forwarded. It got forwarded to what you configured, even if there was no reply.
Do you think this needs to be changed?


I did expect the graph to show the percentage the resolvers actually responded, but now I know it’s the percentage dnsmasq asked the resolver for an answer…

It doesn’t really matter, it’s statistics only.


It’s like this to make the bookkeeping easier:

When we send the query upstream, we know to which forward destination we are currently sending it to :white_check_mark:

Once we receive a reply, dnsmasq doesn’t really care from where it comes as long as it matches a previously forwarded query and just forwards the result to the client. So, additional work would have to be invested here to identify the replying forward destination. Albeit possible, I doubt it would be worth the effort as you also already said.