Note 2015-07-18 – The setup described in this article will be obsolete starting in August 2015, as Deutsche Telekom announced that multisession PPPoE will cease to be a supported feature for their T-DSL endpoints. However, they do now offer native IPv6 with static prefixes as part of their "DeutschlandLAN Voice/Data S" packages. This is probably the best option to replace a IPv6/IPv4 multisession PPPoE setup. Another option is to use tunneling or to switch to another L2 provider, but choices are still limited here, as most providers only offer dynamic prefixes.

Native IPv6 NOW!


Skip blathering and go to the example»

When it comes to IPv6 adoption, one could get the impression that not much has changed since the days of 6BONE. Still, few people talk about it, and it's not visible in the marketing of any of the big carriers.

Rather, more and more bizarre ways to get along with IPv4 somehow seem to emerge. (Once you get an IPv6 link and see how easy it is to set up, you'll have even more difficulties understanding why this is the case.) A particularly bad trend seems to be carrier-level NAT, which you probably already experienced if you once tried to hook up a LAN on the Internet with 3G networking in Germany. I can only imagine what other peculiarities might come out of that corner in the future as the price tag for IPv4 addresses increases.

But: It's 2010, and everything we need for IPv6 is in place.

While for IPv6-enabled ISPs, their systems might still be in prototype status and their administration will possibly not yet achieve the level of automatization that we're used to for IPv4, IPv6 is definitely mature enough to be taken seriously and in fact, once the links are set up it's easy to forget that you're using it completely, were it not for the benefit of being able to have as many hosts as you wish on the Internet that does remind you often enough it was worth making the change!

But even if the technology is there, there are two major fortresses that will probably require a long time before they're taken, particularly in Europe and the US.

For company LANs, there's not much to be done right now. Tunneling is of course not an option at client level. What will most likely happen is that the existing HTTP proxies will be made IPv6-safe at some point and offer a "window" into the IPv6 world (actually, much as they currently open a window into the Internet outside the LAN), while legacy services in the LAN will continue to use IPv4 for as long as they wish. I think we're looking at something that's going to take a long time, could well be between five to ten years from now.

For the SOHO area, NAT-safe tunneling is an option that should technically be available to everyone right now. But only hassle-free approaches such as Vista's Teredo support have the potential to make a real change here.

Seeing all this, it is almost understandable that most of the prominent content providers on the net are very reluctant at the moment when it comes to publishing AAAA records for their services, thus essentially blocking the advance of the IPv6 Web.

I have recently made myself IPv6-proof by

It's easy! See the description of my configuration below.

ADSL With IPv6 Support (Multi-Homed FreeBSD Router Example)

The type of IPv6-capable ADSL you can get right now everywhere in Germany is based on T-DSL's "ZISP" model where a DSL line operated by Deutsche Telekom can be used with another ISP who handle the PPP link. I have heard of offers that can get you IPv6 on various SDSL carriers as well, but admittedly, I don't have that much insight in this part of the market.

What I'll describe here is the T-DSL based variant, using TAL.DE as IPv4/IPv6 provider. Because it's T-DSL, that means you're stuck with Deutsche Telekom as low-level provider. Strictly speaking they don't need to be more than that, meaning you don't necessarily have to use their IP layer (T-Online). At least in theory. In practice, it's nearly impossible to evade their T-Online bundles. Traditionally, the layer-3 providers would handle that sort of negotiation, because normally once you dare enter one of Deutsche Telekom's shops you will go home with a T-Online contract.

However, TAL.DE don't offer help in that situation right now.

No problem. I saved myself the hassle anyway since TAL.DE's billing is based on data transfer, while T-Online's plans are flat, so I chose to have a T-Online account in addition to the TAL.DE account for the more bandwidth-demanding services, that will still use IPv4 then of course. This means I use two PPPoE logins simultaneously on the ADSL line. This is possible without problems (actually, in the days of client-side RASPPPOE installations it was quite a common setup) but it does rule out the option of using one of the common SOHO ADSL router appliances, at least the ones that I know of.

In my case, I use a FreeBSD PC as router configured to meet the following requirements:

Note that this is just one way to do it. For example, I think NAT could as well be handled by IPFW, as could packet filtering. Or alternatively, one of FreeBSD's other packet filtering frameworks could be employed. Much of what I've chosen simply depends on my personal taste.

Now what about DNS? I know that in the days of private IPv4 subnets it was quite common to run a local DNS for some bogus domain it was configured to be master for. For IPv4 addresses on the LAN, that's still an option that can run alongside IPv6, but doing the same for IPv6 addresses doesn't make sense! That's because your hosts are global now and they should be entered in a real DNS that's configured to serve a real zone. The two options that are possible here are:

  1. You promote your DNS to global visibility by entering it in the NS record of your domain.
  2. You don't use your DNS for IPv6 but tell your ISP to answer all forward and reverse inquiries. (For forward queries it can actually be some ISP where you can influence DNS records.)

Of these, the first option is pretty pointless for a small LAN since authoritative DNS servers ought to have better availability than you can guarantee in your kitchen or bedroom.

Instead, use the traditional low-cost method and rely on your ISP's DNS. They're usually quick to answer all the typical requests that you might have, normally you phone them or write them a mail and they set up the DNS records within hours. Often there's even a Web interface. In the case of TAL.DE, the Web interface is somewhat lacking at the moment in the IPv6 area but the email support is very good.

Possibly, you might want to keep some hostnames off the Internet, even if they have IPv6 now, and still handle them in a local-only zone. This could make sense for hosts that are planned to be blocked by the packet filter anyway.

Setting Up the PPPoE Links

As outlined above, I use a FreeBSD PC as DSL router. This PC accesses a Netgear DG834, which was put in modem mode using the next_file=mode.htm hack, through a normal switched Ethernet. This means the DG834 acts as Ethernet bridge. Any DSL modem or router with PPPoE pass-through could be used in its place.

This setup obviously does not support IPv4 client-induced gateway reconfiguration through UPnP. This means that gaming or Torrent machines need appropriate port-forwarding configurations. An example is shown below.

Also, since user-ppp on FreeBSD uses the tunx devices, it is useful to hard-wire their device names in the configuration so that they do not interfere with the ones created by other software, such as OpenVPN, and so that the device names can safely be referenced in packet filter rules. For this setup, I use tun1 for the T-Online link, and tun2 for TAL.DE.

The PPP devices use different physical Ethernet devices to talk to the DSL modem (or rather, to the ADSL Access Concentrator through the modem). In my setup, it's fxp0 for TAL.DE, and re0 for T-Online.

Why so? The type of setup you get with T-DSL is: You can talk to one Access Concentrator, and service tags are not used. Instead, Deutsche Telekom identify the layer-3 providers through the PPPoE login. You can figure this out easily by listening to the PPPoE traffic with tcpdump – while entering dial in an interactive PPP session that's configured to establish a PPPoE link – like so:

tcpdump -i re0 -n  # assuming re0 is exclusively used for PPPoE, here

You notice that you get one Access Concentrator, and that there are no service tags announced. Now if you try to connect two links simultaneously through only one underlying Ethernet device, you'll notice that the second PADR remains unanswered. If you use separate Ethernet devices however, the second PADR will be answered.

Actually, I'm not sure if T-DSL conforms with RFC 2516 here. Judging from there, paragraph 5.2, the second PADI should already have remained unanswered if their Access Concentrator wasn't happy with the MAC. Also, paragraph 5 states that the combination of MAC address and PPPoE session ID identify a session, not the MAC alone, so I cannot see why having two sessions through one Ethernet device should be a problem. But anyway, it's not a big issue.

To enable user-ppp with the two links, add the following to /etc/rc.conf:

# ...
ppp_profile="dtagdialin dtagtal1"

You notice that the unit numbers are assigned explicitly, and that NAT is enabled for both links (affects IPv4 only).

To also enable IPv6 – and routing for IPv6 – add the following in the same file:

# ...

The actual user-ppp configuration is entered in /etc/ppp/ppp.conf. The following example also shows a port forwarding configuration as well as a simple packet filtering setup. You will also notice that /etc/resolv.conf is left alone, because there is a local BIND on the machine which is statically configured to forward requests to Deutsche Telekom's servers. Generally, to get the addresses of your ISP's DNS servers, you could run ppp with DNS set to "read-only", so that you can grab them from /var/log/ppp.log. In the case of Deutsche Telekom just be sure to deactivate the "Navigationshilfe" on their Web site in advance, otherwise they'll announce DNS servers that answer unmatched queries with advertising content.

The example sets T-Online as default route for IPv4, and TAL.DE as default route for IPv6.


 set log Phase tun command
 ident user-ppp VERSION (built COMPILATIONDATE)

 # ... default dialing configuration can remain here ...

 # Example of a port forwarding configuration to a non-public
 # IPv4 host:
 nat port tcp nt1:6881 6881

 set device PPPoE:re0
 set MTU 1492
 set MRU 1492
 set dial
 set crtscts off
 set speed sync
 accept lqr
 disable deflate
 disable pred1
 disable vjcomp
 disable acfcomp
 disable protocomp
 set ifaddr
 add default HISADDR
 set login
 set authname NOT_SHOWN
 set authkey NOT_SHOWN
 # Filter configuration. No low server ports allowed.
 # Open otherwise.
 set filter in 0 deny tcp dst lt 1024
 set filter in 1 permit

 set device PPPoE:fxp0
 set MTU 1456
 set MRU 1456
 set dial
 set crtscts off
 set speed sync
 accept lqr
 disable deflate
 disable pred1
 disable vjcomp
 disable acfcomp
 disable protocomp
 set ifaddr
 add default HISADDR6
 set login
 set authname NOT_SHOWN
 set authkey NOT_SHOWN

 set filter in  0 permit tcp dst eq 22
 set filter in  1 permit icmp
 set filter in  2 permit ipv6-icmp
 set filter in  3 permit tcp estab
 # More restrictive filtering here, since this link reaches all IPv6
 # hosts on the LAN
 set filter in  5 deny   tcp dst eq 3306 
 set filter in  7 deny   tcp dst eq 2049 
 set filter in  8 deny   tcp dst eq 6000 
 set filter in  9 deny   tcp dst eq 4045 
 set filter in 10 deny   tcp dst eq 7100 
 set filter in 11 permit tcp dst gt 1023 
 set filter in 12 permit udp dst gt 1023 
 set filter in 13 deny 

 set filter out  0 permit tcp src eq 22
 set filter out  1 permit icmp
 set filter out  2 permit ipv6-icmp
 set filter out  3 permit tcp src gt 1023 
 set filter out  4 permit udp src gt 1023 
 set filter out  5 deny

Now after starting user-ppp with /etc/rc.d/ppp/start, you'll see the IPv6 route in place:

netstat -r -f inet6 | head

Note that the LAN is not yet fully configured for IPv6. See below for the missing step of announcing your IPv6 prefix.

IPv4 Routing Policies

Before going on with IPv6 configuration, IPv4 routing policies shall be employed to make certain protocols use the TAL.DE link, which offers a static IPv4 address. In this example it's SSH and OpenVPN, two likely candidates. (Were they kept on the T-Online link, I would have to use dynamic DNS – and get exploding known_hosts files on the clients.)

The example uses the ipfw fwd and the ipfw setfib commands (the latter mainly for ICMP). It's not complicated, but the FreeBSD kernel needs to be rebuilt with the IPFIREWALL_FORWARD and ROUTETABLES=4 options, e. g. with a kernel configuration file like:

include GENERIC
ident "KERN-RS-8.0-20100417"


The policy should be that the necessary IPFW changes are automatically made depending on the PPP link status.

For this, the commands are put in a shell script which is referred to in the /etc/ppp/ppp.linkup and /etc/ppp/ppp.linkdown files.

  !bg /bin/sh /root/fw/ tun2up HISADDR
 ! /bin/sh /root/fw/ tun2down

The following script /root/fw/ contains the IPFW rules:



ipfwadd="ipfw -q add"
ipfwdel="ipfw -q delete"

# For first-time initialization:
if [ -z "$mode" ]
    ipfw -q -f flush
    $ipfwadd 0100 allow ip from any to any via lo0
    $ipfwadd 0500 allow ip from any to any

them4="{ not $us4 }"

setfib 1 route delete default

    $ipfwdel 450 220 210 200

if [ "$mode" = "tun2up" ]

    if [ -z "$gw4" ]
            netstat -f inet -rn \
                | grep link.\*tun2 \
                | awk '{print $1}'

    $ipfwadd 200 fwd $gw4 tcp from me 22 to $them4
    $ipfwadd 210 fwd $gw4 ip4 from me 1194 to $them4

    $ipfwadd 220 fwd $gw4 tcp from $us4 to $them4 22

    setfib 1 route add default -iface tun2
    $ipfwadd 450 setfib 1 ip4 from any to any via tun2

elif [ "$mode" = "tun2down" ]



This script can optionally read the default IPv4 gateway from netstat, so that it can also be used from the command line.

Configuring IPv6 on the LAN

Now might be a good time to familiarize yourself with basic IPv6 concepts here (in German) and read the appropriate section in the FreeBSD Handbook.

At the moment, when you order an IPv6 prefix for a LAN, you're considered a "site" and get a /48 block without further ado. Per convention, the 16 bits following the 48 bit prefix then denote the "subnet" (which you can choose to have 64K of) and the remaining 64 bits are interface address local to a subnet.

It's been said before, but compared to the hard dollars you pay for every single darned IPv4 address that's really pretty cool.

Leased servers in data centers obviously are considered hosts rather than sites, and when running such machines you may get as many addresses as your operator deems suitable; but I've not heard of any who try to be restrictive here (wouldn't make sense anyway). Often you still have a /64 or /96 block. Good for subdomains with SSL support!

IPv6 comes with various techniques to automatically assign addresses relative to your subnet prefix, based on the MAC addresses of the network interfaces and with built-in conflict resolution. You can choose to use those or assign your own, bravely starting numbering with 1. The latter is nice because then you have shorter addresses. Also, for public hosts it is better to not rely on the outcome of stateless autoconfiguration since that will change from time to time. So you could use stateful autoconfiguration (not covered here) or just set addresses manually.

With FreeBSD, IPv6 addresses are set just as the IPv4 ones in /etc/rc.conf.

# ...
# em0 is the LAN-side interface here

In reality, IPv6 addresses are hard to handle even if you assign short ones, so DNS can be considered essential. As mentioned before, this is not covered here as I assume you use an ISP-operated DNS, and a local one merely for caching.

Even so, you should at least configure that local one to also listen on IPv6 sockets. Note there is a caveat which generally applies to listening sockets once IPv6 is configured. It's the net.inet6.ip6.v6only sysctl (called net.ipv6.bindv6only on Linux) which determines whether such sockets are always automatically opened for IPv4 as well for applications that do not distinguish. Nowadays this does more harm than good, I recommend disabling it unless it's really necessary. This just means that a line like ipv6_ipv4mapping="YES" should not appear in /etc/rc.conf.

To make BIND listen on IPv6, insert the following in the "options" section in /etc/namedb/named.conf (using your interface's address):

# ...
listen-on-v6 { 2001:db8:1033::3; };

After restarting BIND (and dependent software such as mountd), a

dig @2001:db8:1033::3 -6

should yield the correct result (which is still an A record by default; the type of connection to the DNS server naturally doesn't influence how dig understands its commands).

To finally actually announce the IPv6 prefix and the default route on the LAN, the rtadvd service needs to be started.

Create the file /etc/rtadvd.conf with the following contents:


Additionally, add to /etc/rc.conf:

# ...

Now the LAN receives its IPv6 prefix. Typically, there is no further configuration needed on any of the other hosts on the LAN to obtain IPv6 connectivity. I tested this with Debian 5.0 and Solaris 10 10/08. Some notes though:

Although DHCP is not necessary to announce addresses – at least if you stick with the default ones –, for DNS propagation it is still useful. To announce IPv6 DNS server addresses, you would need DHCPv6 obviously. I wouldn't deem it essential right now for a mixed IPv4/IPv6 LAN, since I am assuming that an IPv4 DHCP service will keep running anyway and the DNS that it announces can perfectly use IPv4 to deliver AAAA records.

At least until something like Yahoo's DNS Hack Proposal comes through, which is a questionable idea of how to make the transition less painful for Web site operators, also discussed (in German) here. (If a BIND is available on the LAN, that sort of development could still be countered by configuring its forwarding to use IPv6 exclusively though.)

An IPv6 Capable Virtual Server

Compared to the somewhat lengthy procedure of setting up an IPv6 ADSL router as described above, installing a virtual server hosted in some data center is a lot less work. I am referring to the typical case of a Linux VPS here which can typically be ordered and set up within minutes. You just have to find a hoster who enable IPv6 on their interfaces (and offer an option to configure appropriate reverse DNS records).

Unfortunately, while VPSes in Germany are normally quite inexpensive and currently (2010-05-13) offer 750 GB transfer with 512 MB RAM for EUR 10/month, asking about IPv6 changes the picture drastically. Most just say "not possible" without explaining their migration plans, some at least say they're planning it for this year, while others charge a hefty EUR 30 only for IPv6 connectivity. (What also sucks about German hosters are their super-longlasting contracts that always automatically renew themselves for another year.)

So it's necessary to move a little farther away in Cyberspace. I haven't checked the more obscure corners on the continent, but in terms of IP connectivity, the Netherlands are always a good choice. However, the only (English-speaking) offers I found aren't very cheap. Another good option is London which can also be reached from Germany with very low latency. Bitfolk, Bytemark, and Goscomb Technologies come to mind. The problem with UK hosters in general seems to be that while the hardware specs are OK, they charge a lot for the traffic, their plans starting with as little as < 100 GB.

For now I have chosen HostVirtual who are based in San Jose and offer reasonable pricing. They also have VNC console support which is good if you screw up your network configuration. The location is obviously not so good for the ping times but for a mail and Web server it is tolerable.

The only thing I needed to configure on the machine was to set the IPv6 address that was assigned to me with "ifconfig add", as eth0 was initially configured only with the EUI address. The file /etc/network/interfaces didn't need a change though.