Configuring OpenWRT on an NSLU2
Problems have been reported setting up aiccu and radvd together on OpenWRT [[1]]. This page recounts what worked for me on a Linksys NSLU2 running OpenWRT 10.03.1-RC6. The NSLU2 offers one just wired ethernet port and two USB ports.
The general setup is a small home network connected to the ISP via a first-generation Apple Time Capsule. The machines on the network are Macs and Linux boxes and, apart from a fixed IP, there's nothing special about the network. The ISP doesn't offer IPv6, and I wanted world-routable static IPs. I wanted to set up the NSLU2 as simply as possible, so I turned off anything I didn't need or didn't understand.
I started by compiling OpenWRT 10.03.1-RC6.
Contents
Compiling OpenWRT
(For another account of compiling OpenWrt for this purpose, see [[2]] -- I just want to relate here what I did, specifically for OpenWRT 10.03.1-RC6 and the NSLU2.)
The first step is to get a basic version of OpenWRT with IPv6 support. To do this, I followed the directions at http://wiki.openwrt.org/doc/howto/build2 except for one thing: in the section entitled "Updating Feeds" it suggests installing all feeds with the command: ./scripts/feeds install -a. I don't do this.
Use menuconfig to select the target system and the target profile. Then select kmod-ipv6.
Target System > Intel IXP4xx Target Profile > Linksys NSLU2 Kernel Modules > Network Support > kmod-ipv6
Make sure this works: compile and install OpenWrt onto the NSLU2. You should get Link-Local IPv6 addresses appearing in the ifconfig listing:
root@OpenWrt:/# ifconfig br-lan Link encap:Ethernet HWaddr 00:1A:70:94:D1:ED inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::21a:70ff:fe94:d1ed/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:324 errors:0 dropped:0 overruns:0 frame:0 TX packets:44 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:106149 (103.6 KiB) TX bytes:4881 (4.7 KiB) eth0 Link encap:Ethernet HWaddr 00:1A:70:94:D1:ED UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:326 errors:0 dropped:0 overruns:0 frame:0 TX packets:45 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:106425 (103.9 KiB) TX bytes:4971 (4.8 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) root@OpenWrt:/#
OK, so far, so good. Now to install the packages needed for the sixxs tunnel and for the radvd router advertisement daemon:
$ ./scripts/feeds install aiccu radvd Installing package 'aiccu' Installing package 'ntpclient' Installing package 'radvd'
Next, use menuconfig to include them in the build:
IPv6 > aiccu IPv6 > radvd
A number of other packages are automatically included in the build. Compile and install, as before.
The aiccu and radvd packages include startup code so that the services will automagically be launched at boot time. They should fail to launch, however, (and may leave error messages), because they haven't yet been configured.
Obvious Stuff
I had plenty of trouble getting the tunnel and radvd to work properly together and so I wanted to eliminate as many confounding factors as possible. The first thing I did was to turn off the built-in DNS/DHCP server dnsmasq, which is enabled in the default build -- my local network already has these services.
Turn Off dnsmasq
root@OpenWrt:# /etc/init.d/dnsmasq stop Terminated root@OpenWrt:# /etc/init.d/dnsmasq disable root@OpenWrt:#
The next thing I did was to disable the IPv6 firewall.
Turn Off IPv6 Firewall
In the file /etc/config/firewall, look for the two lines:
# Uncomment this line to disable ipv6 rules # option disable_ipv6 1
and uncomment the second line. This will disable the IPv6 firewall.
Enable IPv6 Forwarding
Find this line in /etc/sysctl.conf and uncomment it:
# net.ipv6.conf.all.forwarding=1
The Core of the Problem
Recall that I wanted the NSLU2 to be as self-configuring as possible. In summary, what I wanted was for br-lan to pick up regular IPv4 information using DHCP, to pick up the relevant IPv6 information from radvd, and finally, of course, to function as an IPv6 tunneling router. That's what I got, eventually.
You might imagine that the network settings for IPv4 and IPv6 are independent of one another, but you'd be wrong. In OpenWrt, the behavior of radvd on the network interface br-lan is affected by the protocol setting static or dhcp. By default, the interface setting accept_ra [[3]] is false for an interface with a static protocol and true if the chosen protocol is dhcp.
If accept_ra is false (the default if the protocol setting is left at static), then radvd will not have any effect on br-lan. However, if accept_ra is true, (the default if the protocol setting is dhcp), then radvd will do two things: it will give br-lan an IPv6 address within the subnet it is advertising, (a good thing, IMHO), but it will also tell the NSLU2 to route all IPv6 packets through br-lan by default. Thus a packet routed from elsewhere on the network into the NSLU2 will actually be routed back to the port -- br-lan -- it came into the NSLU2 on. This is Not A Good Thing, for sure, and I think the cause of problems referred to elsewhere.
Sysctl Settings
To see what might actually be happening, and to fix it, take a look at the sysctl entries relating to IPv6 and br-lan. You can use the command
sysctl -a
to list all sysctl settings. Here is an extract of what you see if accept_ra is false:
net.ipv6.conf.br-lan.accept_ra = 0
If accept_ra is true you'll get this:
net.ipv6.conf.br-lan.accept_ra = 2
(See [[4]] or similar for an explanation of these settings.) What this means is that if the protocol is static, br-lan will ignore the periodic IPv6 router advertisements coming from radvd. That is unfortunate, but it isn't fatal. It's unfortunate because it means that you must manually give br-lan an IPv6 ip number within the subnet to be advertised by radvd.
If the protocol is dhcp, then br-lan will act on the router advertisements, automatically acquiring an IPv6 ip number within the subnet advertised. Unfortunately -- and fatally -- it will also acquire a default route which would be right for other devices on the network, but which is not right for the NSLU2 which is acting as a router, as it causes the forwarding loop already described. Happily, there is another setting in sysctl that controls whether a default route should be accepted from a router advertisement.
The setting:
net.ipv6.conf.br-lan.accept_ra_defrtr = 0
will instruct the interface not to accept default router information from radvd, even while it does accept an IPv6 ip number. This is exactly the behavior I want.
The Settings
/etc/sysctl.conf
Add this line to turn off default route acceptance on br-lan:
net.ipv6.conf.br-lan.accept_ra_defrtr=0
/etc/config/network
Turn on dhcp for eth0, making the file contents look like this:
# Copyright (C) 2006 OpenWrt.org
config interface loopback option ifname lo option proto static option ipaddr 127.0.0.1 option netmask 255.0.0.0 config interface lan option ifname eth0 option type bridge option proto dhcp
/etc/config/aiccu
Insert your tunnel details here. This is for an AYIYA tunnel.
config aiccu option username '<your username>' option password '<your password>' option protocol option server option interface 'sixxs' option tunnel_id option requiretls '0' option defaultroute '1' option nat '1' option heartbeat '1'
/etc/config/radvd
Insert your subnet details here.
config interface option interface 'lan' option AdvSendAdvert 1 option AdvManagedFlag 0 option AdvOtherConfigFlag 0 list client option ignore 0 config prefix option interface 'lan' # If not specified, a non-link-local prefix of the interface is used list prefix '<your subnet prefix>/64' option AdvOnLink 1 option AdvAutonomous 1 option AdvRouterAddr 0 option ignore 0 config route option interface 'lan' list prefix option ignore 1 config rdnss option interface 'lan' # If not specified, the link-local address of the interface is used list addr option ignore 1 config dnssl option interface 'lan' list suffix option ignore 1
Notice that the ignore flag is true for route, rdnss and dnssl, so they are ignored -- I haven't figured them out yet. Also notice that the name of the interface you specify here is "lan", and not "br-lan" -- the "br-" part is added automagically.
Try it out
Make sure your NSLU2's clock is nearly right, or the tunnel will collapse. Turn on aiccu and radvd using the commands:
/etc/init.d/aiccu start /etc/init.d/radvd start
and check that everything is working. It should be :)
The aiccu and radvd packages include code to ensure that each service is automatically enabled to start on boot.
This has been working very well for me. I hope you find the account of it useful.