MC's Journal

IPv6 tunnel from HE with dynamic endpoint on FreeBSD

Hurricane Electric's tunnelbroker offers IPv6 tunnels that you can use without any extra client software. No need for AICCU, OpenVPN or anything else.

HE's tunnels use built-in support in most most operating systems for the 6in4 tunneling protocol. It even works if you're home router might an odd duck, such as Plan 9. It doesn't work in all the scenarios some of the other tunnel clients support and it doesn't protect from IP spoofing, but it might be preferable in some situations.

My case is an EdgeRouter Lite, a rather nice MIPS-based thing (based on Cavium Octeon) from Ubiquiti Networks. I installed FreeBSD on it, but since this is a rather odd FreeBSD platform I don't get any binary packages and have to rebuild the firmware myself if I want to upgrade. I also don't get any support for the built-in network acceleration hardware.

I tossed the original Linux, since I didn't fancy rewriting all my pf rules nor adding them through a web UI, however nice. I did, however, make a copy of the Linux image and I'm especially interested in what's inside cavium-ip-offload.ko and friends. But that's for another time, if I can find the time.

Typically, you set up a 6in4 tunnel like this on FreeBSD:

ifconfig gif0 create
ifconfig gif0 tunnel 83.249.0.22 216.66.80.90
ifconfig gif0 inet6 2001:470:27:9d2::2 2001:470:27:9d2::1 prefixlen 128
route -n add -inet6 default 2001:470:27:9d2::1
ifconfig gif0 up

where 83.249.0.22 is the current IPv4 tunnel endpoint on my home router. You want some of these in rc.conf to survive reboots:

gif_interfaces="gif0"
ifconfig_gif0_ipv6="inet6 2001:470:27:9d2::2 2001:470:27:9d2::1 prefixlen 128"
ipv6_defaultrouter="2001:470:27:9d2::1"

My router gets its IPv4 from my ISP's DHCP, so the tunnel endpoint on my end might change at any time. Luckily, Hurricane thought of that and provides a web service to change my IPv4 endpoint easily by accessing:

https://${userid}:${updatekey}@ipv4.tunnelbroker.net/nic/update?hostname=${tunnelid}

so I wrote a script, he.sh:

#! /bin/sh

tunnelgw=216.66.80.90
userid=my-id
updatekey=my-update-key
tunnelid=my-tunnel-id

if [ $# != 1 ]
then
    echo Usage he.sh ip-adress
    exit
fi

# $1 should be my own IP
ifconfig gif0 tunnel $1 $tunnelgw

fetch --no-verify-peer -o - "https://${userid}:${updatekey}@ipv4.tunnelbroker.net/nic/update?hostname=${tunnelid}"

ifconfig gif0 inet6 2001:470:27:9d2::2 2001:470:27:9d2::1 prefixlen 128

ifconfig gif0 up

and call it from /etc/dhclient-exit-hooks, a program which, if it exists, runs automatically by FreeBSD dhclient DHCP client.

#! /bin/sh

/root/he.sh $new_ip_address

Ta-da!