Connecting an IPv6 only site to an IPv4 only world

Many Internet provider are not able to offer a native IPv6 Internet connection. Even if there are many ways to send IPv6 packets over an IPv4 network, this post will show how an IPv6 only site can be interconnected to IPv4 only networks. For example we want to configure a small home/branch office using IPv6 only, avoiding slow 6to4 tunnel.

DNS64 and NAT64

An IPv6 only host can communicate with an IPv4 only host using NAT64. A NAT64 server is required to translate IPv6 addresses into IPv4 addresses and vice-versa. A virtual subnet will be deployed to map all IPv4 addresses.

An appropriate DNS server must be deployed: IPv6 only hosts will ask for AAAA DNS record, but IPv4 only host will have A record only. DNS64 is a mechanism to translate AAAA DNS requests into A requests.


The following scenario is deployed:

IPv6 Only Site


  • A Linux box is required to implement NAT64 and DNS64 services. Newest Cisco routers can act as a NAT64 and DNS64 servers, but in this case a Raspberry Pi box is used. Two connections are needed:

  • eth0 will be used to connect the Linux box to the Internet, using an IPv4 public address;

  • eth0.2 (802.1q) will be used to connect the IPv6 only network;

    • Because IPv6 addresses are not routed to the Internet, ULA (Unique Local Address) are used. ULA address are like private IPv4 address and cannot be routed into the Internet. An ULA IPv6 range should be registered using the SixXS registry. Two network are required:

    • fd9f:590a:b158::/64 is assigned to IPv6 only hosts;

    • fd9f:590a:b158:ffff:ffff::/96 is used to map IPv6 and IPv4 addresses: because IPv4 are 32 bits long, a 96 bit prefix is needed (however 64 bit prefix should be allocated).

  • An additional IPv4 network is needed for the TAYGA daemon, used to implement the NAT64 service.

Configuring the Raspberry Pi (IPv6 and 802.1q)

In this scenario a Raspberry Pi box is used with a 802.1q link. The following modules must be loaded:

# cat /etc/modules

The eth0.2 interface is used to interconnect IPv6 hosts:

# cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto eth0.2
iface eth0.2 inet6 static
    address fd9f:590a:b158::1
    netmask 64
    vlan-raw-device eth0

The radvd daemon must be installed and configured so IPv6 hosts can be autoconfigured:

# cat /etc/radvd.conf
interface eth0.2 {
        AdvSendAdvert on;
        MinRtrAdvInterval 3;
        MaxRtrAdvInterval 10;
        prefix fd9f:590a:b158::/64 {
                AdvOnLink on;
                AdvAutonomous on;

Finally the Raspberry Pi must be configured as a router (IP forwarding must be enabled):

# cat /etc/sysctl.conf

Configuring the DNS64 daemon

The famous DNS server BIND (a.k.a. named) can be used as a DNS64 server. IPv4 hosts user A records:

# dig +short @::1 A

IPv6 hosts look for AAAA records, so BIND must be configured to translate A records into AAAA ones:

# cat /etc/bind/named.conf.options
options {
        dns64 fd9f:590a:b158:ffff:ffff::/96 {
                recursive-only no;
                exclude {
                clients {

At this point if an AAAA records is requested, an A record is retrieved and mapped to an IPv6 address:

# dig +short @::1 AAAA

The exclude entry is added because this network has not IPv6 reachability. DNS64 translate only domain which does not have AAAA records. Without exclusions DNS64 answers with the real AAAA record:

# dig +short @::1 AAAA

With the exclusion configured, the DNS64 answers with mapped AAAA records, one for each A record:

# dig +short @::1 A
# dig +short @::1 AAAA

Configuring the NAT64 service

The TAYGA daemon can be used to convert IPv6 addresses into IPv4 addresses. The same IPv6 prefix configured above must be used:

# cat /etc/tayga.conf
tun-device nat64
prefix fd9f:590a:b158:ffff:ffff:ffff::/96
data-dir /var/spool/tayga
# cat /etc/default/tayga

NAT44 is disabled because we want to manually configure it. NAT44 is required to translate private ip addressed located in the network to a public IP address currently assigned to eth0 interface:

# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE


And finally IPv4 sites are reachable from IPv6 hosts:

# ping6 -c1 fd9f:590a:b158:ffff:ffff:ffff:5e8d:1616
PING fd9f:590a:b158:ffff:ffff:ffff:5e8d:1616(fd9f:590a:b158:ffff:ffff:ffff:5e8d:1616) 56 data bytes
64 bytes from fd9f:590a:b158:ffff:ffff:ffff:5e8d:1616: icmp_seq=1 ttl=52 time=61.7 ms

Also using DNS (mind that /etc/resolv.conf must be properly configured):

# ping6 -c1
PING 56 data bytes
64 bytes from icmp_seq=1 ttl=52 time=60.0 ms

Some protocols which embed L3 addresses into L4 datagram (like FTP or SIP) can behave unexpectedly; also DNSSEC cannot be used because of the DNS record manipulation.