ULA means Unique Local Addresses. These addresses are used similarly to the IPv4 local addresses ( and They have the ipv6 prefix fd00::/8 and are not routable on the net.

Why use these addresses ?

Permanent addresses

These addresses allow to define a permanent addressing scheme in your network, which can be handy if you want to have/need a weird topology of your own, or your prefix is dynamic or you often change ISP.

Some ISP provide dynamic prefix, meaning the network part of the address change also. This means all your global addresses will regularly change. You cannot count on them for routing or addressing scheme. Anyway, you have to make it again at each change of ISP.

Those Unique Local Addresses allow you to make it fix.

Non-routable addresses

These addresses being non routable, it is not possible to reach/attack them from the internet. For example, it makes sense for the printer or the DNS resolver to use it.

They are also normally with a quite high priority in the routing table. Meaning they will be used first before global addresses.


[stephane@jabberwocky content]$ ip -6 route
fd00:2016:22:dec::/64 dev eno1 proto kernel metric 256  expires 3455sec pref medium
2001:470:28:2d4::/64 dev eno1 proto kernel metric 256  expires 3455sec pref medium
fe80::/64 dev eno1 proto kernel metric 256  pref medium
default via fe80::20d:b9ff:fe3e:a812 dev eno1 proto ra metric 1024  expires 2255sec hoplimit 255 pref medium

If a machine is in my network, then it should get a private ipv4, a private ipv6 (fd00:2016:22:dec::) and a global ipv6 (2001:470:28:2d4::). While doing DNS requests, the private ipv6 will be used first.

Advantage of controlling the router

This is all fine as long as you control the router. If, like most xDSL clients, you get a new box each time you change ISP, then you get to define again your addressing scheme (if you have one). Which makes the number one advantage of those addresses vanish.

NB: You would still have to define again passwords, wifi key, port forwarding in ipv4, but it comes out of the article.

As I built my own router, I control how and who/what I give addresses. For example, my smartphone has no ipv4 in the local network. It is on ipv6-only. I simply disabled ip(v4) on its identifiant/MAC address.

What do they look like ?

These addresses are in the fd00::/8 prefix.

As these addresses are not public, you can choose them a bit like you want. I decided to do them like fd00:2016:22:dec::/64. Which gives a date if you read it correctly. I could have made my birth date, but I did not think of it.

This is another advantage: you can set those addresses the way you want to remember them easily (with dates or simple short words). And that is priceless in ipv6.

To those who want to make it complicated, there are prefix generators. One can also make them to any size. Most will take ::/48 or ::/64.

How to distribute these addresses ?

Simple: assign a ULA address on the internal interface of your router, and router advertisements will do the job.

The machines will set static address with SLAAC, then the rest will follow (dynamic temporary addresses, etc).

Or you can assign them with the usual static mode.

An example

I run Unbound on a server with «public services» (mail, web server…), but if I can, I won’t expose it to the internet. Because it is good practice:

We will not expose services to the world when we do not need them and they could inadvertently cause a DDoS.

And the same, I won’t have to change every single piece of conf’ next time I change ISP.

I have therefor Unbound listening on fd00:2016:22:dec::3 and ::1 while NSD, authoritative server to my domains, listens on 2001:470:28:2d4::2, which is the public address of my server. Those two daemons run on the same machine. And everything is all right because the addresses are not the same.

Unbound will still request upper nameservers and root-servers via a global address, but it will not listen to it.

All of this is great when writing cross-configuration.

For example, I have Dnsmasq (on the router) and Unbound (on the server) and I like them to speak together. So in unbound.conf on the server :

    # verbosity number, 0 is least verbose. 1 is default.
    verbosity: 0

    interface: ::1
    interface: fd00:2016:22:dec::3
    interface: fe80::be5f:f4ff:fe73:a7e0%re0

    access-control: refuse
    access-control: allow
    access-control: allow

    access-control: ::0/0 refuse
    access-control: ::1/128 allow
    access-control: fe80::/64 allow
    access-control: fd00::/8 allow

    name: "10.in-addr.arpa."
    forward-addr: fd00:2016:22:dec::

    name: "22decembre.eu."
    forward-addr: fd00:2016:22:dec::

You see, Unbound’s conf’ is almost locked there. I won’t need to change its listening addresses and it forwards all local requests to Dnsmasq on the router.

The only thing I might need more (out of regular security check and improvement) is adding a forwarding zone once in a while.

And in dnsmasq.conf on the router :


# Add local-only domains here, queries in these domains are answered
# from /etc/hosts or DHCP only.


The router’s hosts file (used by Dnsmasq) :       localhost
::1             localhost        routeur

2001:470:28:2d4::   routeur
fd00:2016:22:dec::  routeur                     blackblock
2001:470:28:2d4::22:dec      blackblock
fd00:2016:22:dec::2          blackblock

fd00:2016:22:dec::3  unbound             unbound

And here we are. All this part of the server’s configuration should remain as it is now for quite a time, except in case of major evolution.

All client machines in the local network receive global and local ipv6. And all local DNS traffic goes through local addresses for Unbound and Dnsmasq.

The same, the gateway address to the server, written in mygate.conf, is the router’s ula address. This I am not sure pass well under all systems. But OpenBSD looks smart enough to understand multiplicity of addresses on a single node.

I should have native ipv6 connectivity in a week. All my public addresses will have to change. But this one part, which is closed to the world, will remain. That much mess less.


Have you seen that ? Unbound also got a hostname.

I can do that:

dig @unbound blackblock.22decembre.eu

I will obtain blackblock’s address as seen by my local network (Unbound will forward the request to Dnsmasq on the router).

dig @blackblock blackblock.22decembre.eu

I will obtain blackblock’s public address as sent by NSD.

And that is just amazing for DNS debugging !

PS: If you liked the article, or found it useful, or if you simply like me, you are very much welcome to tip or give via liberapay.