A year or two ago I had configured IPv6 on an old Linksys WRT54G running OpenWRT. Recently I attempted to make some changes to use Comcast's 6to4 mechanism, but the on-board flash chip stopped accepting file changes. Since the old WRT54G routers were limited to an older Linux kernel for the wireless chipset support (which prevents 6rd tunnels from working), I decided it was time to upgrade to a new router.
After doing some reading of the OpenWRT forums, I decided to go with the Buffalo WZR-HPG300NH. This device has a much faster CPU, more RAM and a much larger flash. It also has 802.11N as well as gig ethernet. All that for under $100! It appears to have the best features for the dollar.
The OpenWRT wiki has the necessary information for flashing the device and getting the basics to work. Once I had all the normal stuff configured, I started checking out information online regarding Comcast's IPv6 offerings. In the past I was using HE's Tunnel Broker, but using something from my ISP was preferable. I first configured a Comcast 6to4 tunnel. I roughly followed Jay R. Wren's post and had success. The only problem I noticed with 6to4 was that my browser prefered IPv4 over IPv6 unless the hostname only had an IPv6 address (both Firefox and Safari). So, I didn't get to see the turtle or unicorn. So sad..
So I decided to give Comcast's 6rd a try. Supposedly the 6rd tunnels are the better way to go. Some of the documentation on OpenWRT's wiki has question marks, so I wasn't really sure if the necessary bits were in the kernel. Since the OpenWRT documentation seemed to be lacking, I started out with the script in this Linux.com article. It didn't exactly work as I got errors with the "ip tunnel 6rd" command. I then stumbled on the IPv6 page on the DD-WRT site. I noticed they used a slightly different ip tunnel statement. After some tuning, I came up with the following /etc/init.d/comcast_6rd script.
#!/bin/sh /etc/rc.common
START=42
STOP=88
WANIF=eth1
LANIF=br-lan
SIXRDTUNIF=6rdtun
SIXRDTUNMTU=1280
SIXRDTUNTTL=64
WANIP=`ip -4 addr show dev $WANIF | awk '/inet / {print $2}' | cut -d/ -f 1`
WANIPSPACED=`echo $WANIP | tr . ' '`
ISP6RDPREFIX='2001:55c'
ISP6RDPREFIXLEN='32'
ISP6RDBR=`dig +short 6rd.comcast.net`
LOCAL6PREFIX=`printf "$ISP6RDPREFIX:%02x%02x:%02x%02x" $WANIPSPACED`
LOCAL6PREFIXLEN=64
start() {
# Setup the tunnel interface
ip tunnel add $SIXRDTUNIF mode sit ttl $SIXRDTUNTTL remote any local $WANIP
# Set the MTU
ip link set $SIXRDTUNIF mtu $SIXRDTUNMTU
# Bring up the tunnel interface
ip link set $SIXRDTUNIF up
# Set the tunnel interface IPv6 address
ip -6 addr add $LOCAL6PREFIX:0::1/$ISP6RDPREFIXLEN dev $SIXRDTUNIF
# Set the LAN interface IPv6 address
ip -6 addr add $LOCAL6PREFIX:1::1/$LOCAL6PREFIXLEN dev $LANIF
# Set the default IPv6 route to the ISP's IPv4/IPv6 boarder router
ip -6 route add 2000::/3 via ::$ISP6RDBR dev $SIXRDTUNIF
# Enable IPv6 Forwarding
sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null
}
stop() {
ip tunnel del $SIXRDTUNIF
ip -6 addr del $LOCAL6PREFIX:1::1/$LOCAL6PREFIXLEN dev $LANIF
}
This took care of the tunnel and I was able to ping ipv6.google.com. The next major piece was to configure the IPv6 firewall. Since the built-in scripts just handle IPv4, the best thing to do is add the necessary commands to /etc/firewall.user. I used an example from one of the tutorials except I added a variable for the tunnel interface.
# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start.
SIXRDTUNIF=6rdtun
# start with a clean slate
ip6tables -F
# allow icmpv6
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -I OUTPUT -p ipv6-icmp -j ACCEPT
ip6tables -I FORWARD -p ipv6-icmp -j ACCEPT
# allow loopback
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT
# allow anything out of the tunnel
ip6tables -A OUTPUT -o $SIXRDTUNIF -j ACCEPT
# allow LAN
ip6tables -A INPUT -i br-lan -j ACCEPT
ip6tables -A OUTPUT -o br-lan -j ACCEPT
# drop packets with a type 0 routing header
ip6tables -A INPUT -m rt --rt-type 0 -j DROP
ip6tables -A OUTPUT -m rt --rt-type 0 -j DROP
ip6tables -A FORWARD -m rt --rt-type 0 -j DROP
# allow link-local
ip6tables -A INPUT -s fe80::/10 -j ACCEPT
ip6tables -A INPUT -s fe80::/10 -j ACCEPT
# allow multicast
ip6tables -A INPUT -s ff00::/8 -j ACCEPT
ip6tables -A OUTPUT -s ff00::/8 -j ACCEPT
# allow forwarding
ip6tables -A FORWARD -i br-lan -j ACCEPT
ip6tables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
# forward ident requests
ip6tables -A FORWARD -p tcp --dport 113 -j ACCEPT
# default policy...
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT DROP
Now that I had this new IP space somewhat secured, the next thing to do is configure radvd. The radvd daemon advertises your IPv6 configuration to the client machines on your network. I saw a couple IPv6 tunnel scripts that dynamically generate the radvd.conf file when bringing up the tunnel and I wanted to avoid that. I had noticed a Base6to4Interface option in the manpage and was able to get that working with the 6to4 tunnel. The OpenWRT radvd init script didn't exactly generate the configuration I expected. Instead it grabbed the IPv6 prefix from my wan interface and used that even though I didn't specify it in the /etc/config/radvd file. I suspect that was a result of the init script parsing the Base6to4Interface option. I took a look at the init script, but it wasn't apparent what it was doing. Either way, the following /etc/config/radvd configuration file is working for me and it seems to be cleaner than other methods I've seen. I'm not sure if it's the proper way, so I fear it might break someday.
config interface
option interface 'lan'
option AdvSendAdvert 1
option AdvManagedFlag 0
option AdvOtherConfigFlag 0
option ignore 0
config prefix
option interface 'lan'
option AdvOnLink 1
option AdvAutonomous 1
option AdvRouterAddr 0
option Base6to4Interface 'eth1'
option ignore 0
config rdnss
option interface 'lan'
# If not specified, the link-local address of the interface is used
option addr ''
option ignore 1
I did try setting the rdnss option, but it didn't seem to have much effect on my Mac OS X clients. I actually wonder if it would be better to do DHCP so that I can do authoritative DDNS updates to ISC Bind. Maybe specifying the DNS servers in the DHCP configuration would work better with different client operating systems. I did find a big list of Comcast DNS servers. That might be helpful if I come back to the DNS issue.
So now I see the unicorn galloping and the turtle dancing. I guess I could re-use my Hurricane Electric tunnel on my Linode. I was really hoping they would have deployed native IPv6 by now though.