Thursday, April 14, 2011

OpenBSD, Internode and IPv6

So, my ISP has enabled IPv6 on it's ADSL connections to begin testing the service, to keen technical users. Well, it actually started in November 2009, but there's nothing like getting it around to something you've wanted to do for a while, when the opportunity presents itself!

For me, the opportunity was that my modem died, so some family modem shuffling occurs, my folks end up with a nice new Netgear Modem/Router/WAP and I get their Netgear 632.
That's a fairly low-end piece of kit with just one USB port and one Ethernet port, no VoIP, no WAP, no anything else, just an ADSL2+ modem and a router.

So why "upgrade" from a Billion 7500G to this? It turns out that there are very few modems on the market that can do IPv6 at the moment - so all I needed was a modem that would give me a PPPoE connection that I could process myself.

After soring all of that out, it was time to change my network around to make the PPPoE translation happen on the OpenBSD firewall. This can be done in two slightly different ways:
1. Using userland PPP
2. Using the kernel pppoe interface

The advantage of using userland PPP is the level of debugging information that you get far outstrips what is available with the kernel pppoe interface. I personally setup PPP first and then translated the learnings to the kernel pppoe.
The advantage of kernel pppoe is that the processing overhead is greatly reduced, leading to higher throughput in my case.

PPP user-land PPPoE configuration

The first thing to do here is check your /etc/ppp/ppp.conf file, you need to tell PPP:
1. Where the ADSL modem is connected
2. How the connection is configured
3. What the username and password is

default:
set log Phase Chat IPCP IPV6CP CCP tun command
set redial 15 0
set reconnect 15 10000

#
# A PPPoE (PPP over Ethernet) setup may look like this:
#
pppoe:
set device "!/usr/sbin/pppoe -i em1"
#set mtu max 1492 - see http://www.mynetwatchman.com/kb/adsl/pppoemtu.htm
set mtu max 1454
set speed sync
disable acfcomp protocomp
deny acfcomp
set cd 5
set dial
set login
set timeout 0
set authname ttt@ipv6.internode.on.net
set authkey ttt
enable dns
enable mssfixup
add! default HISADDR


Important points from the configuration file are:
1. set device: tells ppp to run pppoe and talk to ethernet interface em1
2. set authname: tells pppoe what username to use (you need the ipv6 to make IPv6 start working)
3. set authkey: tells pppoe what the password is
4. enable mssfixup: munges the packet size to make sure the maximum packet size parameter is adhered to
5. add! default HISADDR: adds the IPv4 address automatically to the route table as the default.
6. set ... IPV6CP ...: adds IPv6 negotiation to the ppp logs

NOTE: I noticed that my first connections to Internode over IPv6 took quite a few attempts, so don't give up if it fails (quite) a few times.

After you bring up the pppoe interface (sudo ppp -ddial pppoe) performing an "ifconfig tun0" should bring up the IPv4 connection, and if you're lucky, an IPv6 "local link address" - that is an IPv6 address in the "fe80::" address range. This connection is only used to shuffle data backwards and forwards to Internode, so the next task is to get an outward facing IPv6 address.
This is achieved by installing "wide-dhcpv6" package - it comes with the dhcp6c (translation: DHCP IPv6 Client) which you can use to get your IPv6 address and the block of addresses to use in your network.

Create an appropriate dhcp6c.conf file: (/etc/dhcp6c.conf)
# tun0/pppoe0 is the PPPoE interface
interface tun0 {
send ia-pd 0;
};

# em1 is the modem interface
interface em1 {
information-only;
};

id-assoc pd {
# em0 is the interface to the internal network
prefix-interface em0 {
sla-id 1;
sla-len 4;
};
};


In my case, ethernet interface em1 is the pppoe modem, and em0 is the LAN. tun0 is the ppp connection.
Start the DHCP daemon and you should end up with an address.

sudo /usr/local/sbin/dhcp6c tun0


At this stage you should check that you now have a public address.

em0: flags=8843 mtu 1500
lladdr zz:zz:xx:xx:xx:xx
description: LAN
priority: 0
media: Ethernet autoselect (1000baseT full-duplex,master)
status: active
inet 172.16.3.1 netmask 0xffffff00 broadcast 172.16.3.255
inet6 fe80::xxx:xxxx:xxxx:xxxx%em0 prefixlen 64 scopeid 0x1
inet6 2001:44b8:yyy:yyyy:xxx:xxxx:xxxx:xxxx prefixlen 64
-bash-4.0$


Note the second "inet6" address starting with "Internode" - 2001:44b8 and followed on by the rest of the prefix assigned to my network yyy:yyyy. If this does not appear, it is more than likely your PF firewall is blocking the return packets.
Use
sudo tcpdump -i tun0
to check that you are sending request and receiving the response. It should be addressed using local link addresses (i.e. fe80::.....).

The next step is to enable router advertisements to your internal network. This effectively sends packets to your other computers telling them what the network prefix is. The computers choose their own suffix, which can sometimes be the final part of the MAC address, or an entirely different number (an extension to IPv6 called something like "privacy extensions"). In a future post we'll look at running our own DHCP6 server so that we can at least assign addresses a human being has half a chance of remembering.

This is as simple as setting a flag in your /etc/rc.conf.local:

rtadvd_flags=em0


For the impatient, you can run up rtadvd from the console:
sudo /usr/sbin/rtadvd em0


Next time we'll look at the transition to pppoe in the kernel...

No comments:

Post a Comment