Skip to content

Instantly share code, notes, and snippets.

@jiphex
Created July 27, 2015 08:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jiphex/e48082ce2bc0e8716d8e to your computer and use it in GitHub Desktop.
Save jiphex/e48082ce2bc0e8716d8e to your computer and use it in GitHub Desktop.
6to4

IPv6-only LAN with OpenBSD

My ISP provides IPv6 for their home broadband networks, soon other ISPs will too (notably BT who are running a trial of it at the moment). Unless they do it in some insane way, this means that every broadband subscriber will be allocated a /64 of IPv6 space to do with as they please.

The normal way to use this is to "dual-stack" your network, keeping DHCPv4 to hand out NAT-ed RFC1918 addresses to your machines while also using SLAAC to advertise your IPv6 prefix from the router so that machines on the network can autoconfigure themselves an IPv6 address.

If you only want to access IPv6 sites from networked machines, you can disable DHCPv4 altogether on your network, and subject to some caveats[1] your machines will work just fine when they access sites with working AAAA records (such as Facebook and Google).

The problem comes when your machines try and access websites which don't have AAAA records - these will just display a browser error.

Using OpenBSD, it's possible to fix this (without giving the machines IPv4 addresses) fairly simply:

  • We'll use a special DNS forwarder which will normally proxy DNS queries to an upstream DNS provider, but will respond specifically to AAAA queries with no answers by providing a special "magic" IPv6 address
  • We'll use pf to effectively NAT these special IPv6 addresses into their original IPv4 addresses and keep track of the states necessary to return the connection to the requesting machine.
  • We'll configure rtadvd to tell connected clients about our "special" recursive DNS server using ND RDNSS

It's important to note that with this setup, most clients won't notice a difference when connected to the IPv6-only network. Although web browsing to IPv6 sites won't be affected and browsing to IPv4 only sites will appear the same to a casual observer - a few things will stop working, notably:

  • Browsing or connecting directly to numeric IPv4 addresses will not work, as the machines will not have a route to the IPv4 network space
  • Some UDP applications which rely on IPv4 (such as UDP OpenVPN with an IPv4 transport) will not work, as they won't be able to bind an IPv4 address to an interface to listen for incoming packets

With the release of iOS9, Apple will only be accepting Application submissions from apps which work in this environment (DNS64/NAT64), and claim that they'll be testing apps to make sure that this is the case. Android doesn't have such a requirement, but as most apps will just try and use DNS normally, this shouldn't be an issue, although this relies on developer support.

All devices you connect to the network will need to support ND RDNSS which allows router advertisement messages to contain the IPv6 address of a recursive DNS server - this means Android >= 5 - support in other operating systems may vary, see this page for details.

Configuration

So after this - the configuration is actually pretty simple.

First we have to setup our network. Whichever interface you set this up on is going to need to have an IPv6 address configured, no IPv4 address and no DHCP server. You'll need to be running rtadvd on the interface with a specific configuration (you probably wouldn't have used an rtadvd configuration file before since it's not needed for normal operation).

Your router will need to be in IPv6 routing mode and the kernel will need to be appropriately configured to do the right thing about router advertisement messages and neighbour discovery.

Now we should configure totd to provide the magic DNS forwarder on the LAN interface. Install it with pkg_add and check the manpage - totd.conf(4). Basically the default config is what you want - just make sure it's configured to bind to the right interface and with a valid upstream DNS provider (for example unbound bound to another interface). If you're already running unbound you might need to change the interface or port that it listens on to stop a conflict from occurring.

Make sure you list a valid prefix in the totd.conf file - a good one is 64:ff9b:: - whatever you choose shouldn't conflict with any real addresses and should be at least a /96 (so that totd can fit the full 32-bit IPv4 address in the remaining address space, 128-32=96)

When it's done right, you should be able to use dig to send recursive DNS queries to the interface (port 53) and receive valid answers - dig with no arguments should return a list of the root nameservers, A queries should return as normal, AAAA queries to domains (such as google.com) with valid records should return a real address in the 2000::/3 range and, most importantly, AAAA queries against domains with no valid IPv6 record (such as ipv4.icanhazip.com) should return an address in the 64:ff9b::/96 address range (or whatever you configured in totd.conf).

Since there's no DHCP in place which would normally inform connected clients about the IP address of the network's recursive DNS server (probably a public one such as Google's DNS or your router's IPv4 address) - we need to configure rtadvd to do the needful. This is simple - (see rtadvd.conf(5) for details) - basically just add this to your /etc/rtadvd.conf file (creating it if necessary, replacing vlan101 with the name of your LAN interface and the IPv6 address with the IP address of your router on the LAN interface):

vlan101:\
    rdnss="2000:db8:1234:1234::1"

Once this is all setup - you should find you can connect to the network with a laptop or mobile device and browse to IPv6 websites (such as facebook, google, ipv6.icanhazip.com) without an issue - make sure you can do this before you continue. Check that you don't have an IPv4 address, and that your recursive DNS resolver (check resolv.conf) is set to only the v6 address we configured in rtsold.conf. At this point browsing to legacy domains with no valid AAAA record should just timeout (as the resolver will be returning a 64:ff9b::/96 address but nothing will be rewriting that to the IPv4 address.

There's just one step left - configuring pf to perform the mapping from the 64:ff9b:: addresses back to valid IPv4 addresses. Add a rule like this to your pf.conf, making sure to place it before any nat-to rules:

pass in on any inet6 from any to 64:ff9b::/96 af-to inet from (egress:0)

Once this is added, and you've reloaded the pf config (pfctl -f /etc/pf.conf) your IPv6 only network should be all set! Try browsing to ipv4.icanhazip.com - check that it works and make sure you don't have any IPv4 addresses configured on the test machine!

[1]: To tell SLAAC clients about your caching DNS resolver you will need to have a router solicitation daemon and clients that supports "ND RDNSS"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment