Skip to content

Get Your DNS64

  • hosting
  • servers
  • infrastructure


Do you want an ipv6 only network that can still access all the ipv4 internet? Come along for the ride while we build a network using open source tools to do just that.

What you'll need.

An operating system, the one that introduced me to all this is OpenWRT. Do I suggest OpenWRT? Maybe, it depends. Openwrt is a router OS, and has a lot of things that make life easier. It's got docker and can run on arm and ras pi. So this is what I used for the first time. Pihole is commonly mentioned in this space. Proxmox can also run and have either or both run on the pi. What kind of overhead and latencies might be involved with different approaches? That's not what this is about.

Let's break it down

1) odhcpd ** 2) unbound 3) unbound-control ** 4) jool


This article isn't exactly hyper focused on simply dns64, it touches on DDI because frankly without all of the individual pieces in place none of them perform optimally. It takes a team.


This application is a dhcp server, when other computers or devices connect to your network, this is what assigns them an address on your network.

For dns64 this isn't strictly necessary. You could assign all the internal addresses by hand as static ip's in each device or vm's configuration.


Unbound is a DNS server, similar to bind9. It offers an option called 'dns64' , and a 'dns64_prefix' option. In order for ipv6 clients to resolve an ipv4 only website, this encodes the ipv4 address into the dns64_prefix if it's enabled.

unbound UCI config:

config unbound 'ub_main'
        option dns64 '1'
        option dns64_prefix '64:ff9b::/96'

Alternative Bind9 Config:

in named.conf.options inside the options {} object

** I copied and pasted this example from an external source. I did not write this. But I did use this, and copied it out of my config after I had disabled the entire things from my internal bind9's in favor of the unbound returning it so there was more of a single source of truth in my lan.

        dns64 64:ff9b::/96 {
        # Though serving standard DNS to the translator device
        # is perfectly normal, we want to exclude it from DNS64.
        # Why? Well, one reason is that the translator is
        # already connected to both IP protocols, so its own
        # traffic doesn't need 64:ff9b for anything.
        # But a more important reason is that Jool can only
        # translate on PREROUTING [0]; it specifically excludes
        # local traffic. If the Jool device itself attempts to
        # communicate with 64:ff9b, it will fail.
        # Listing !translator before our good clients here
        # ensures the translator is excluded from DNS64, even
        # when it belongs to the client networks.
        # clients { !translator; dns64-good-clients; };

        # Other options per prefix (if you need them) here.
        # More info here:
or more minimally
dns64 64:ff9b::/96 { 
        # clients { !translator; dns64-good-clients; };

OpenWRT Advantages

Because I'm using openwrt things are already designed to work together after enabling options in uci, odhcpd gets the self reported hostname of the device, runs some scripts with it and it's assigned ip's and creates DNS entries for unbound, and then runs unbound-control to update unbound.

OpenWRT Disadvantages

I tried to create a pool of 2000 ipv4 addresses in a /16 LAN for the dhcp server to allocate for vm's and clients and things didn't go well. I know it's a stupid large number but I wanted to see, it had extreme issues even issuing addresses for the same ~35 clients I had connected before and are still connected after setting it back to 150 address pool.

What's all this mean

This means now every device plugged in has a FQDN assigned to it based on the devices self reported hostname, and whatever domain I set in the unbound odhcpd configuration section. I hijacked - probably not a good idea but it's what I did. Probably should have used .lan or something.

But none of this makes anything ipv6 only?

That's true, but some basic groundwork is required. If you've tried to follow along you'll notice I'm not giving specific commands to type in, the reason being is it's more of a pattern that's common to different packages. Each of the things can be done differently, I've set up dns64 with Bind9 instead of unbound. I'm sure there's an alternative to jool, or 15 of them by now.

You need to have a DNS server under your control that can encode ipv4 only results. All should be able to do it these days. And you need a tunnel on your egress that can capture those ip's and translate them back to ipv4 for outgoing connections, and it has to maintain routing tables while the connection is alive.

If you've got that set up, then you can start simply disabling ipv4 in your vm's, and everything should still work. This isn't truely the case it seems however, things still break. Docker and IPv6 Are not friends.