DD-WRT has recently been compiling firmware’s using the 3.x Linux kernel compared to the 2.4 and 2.6 builds. These newer kernel builds provide various improvements to the firmware. Being someone has been using K2.6 builds for a while, I decided to take the plunge and upgrade and check out how my setup worked on 3.x builds. One major setup I have is a Hurricane Electric tunnel setup on the router for IPv6. This didn’t work the same way it did on K2.6 and required some additional work. Here’s my adventures of IPv6 in DD-WRT on the 3.x builds. Hopefully providing some useful information for anyone else wanting to do the same thing
- Router: ASUS RT N66U
- Firmware: v24-sp2 22118 Big K3.x
- jffs – To store custom ipv6 modules, to load into the kernel
- USB – A flash/hard drive partitioned for Optware (See this guide)
- Optware using opkg: (See this Trac ticket)
A bit of a note, I’ll use the term Optware loosely here, On K2.6 Optware was available with various custom scripts written by frater and then further developed by basmaf. Optware on K3.x builds requires a complete overall due to the kernel change (ipkg/ipkg-opt can no longer be used). Currently the K3.x version of Optware is literally just using opkg (OpenWRT packages), with none of the previous custom scripts having been rebuilt for 3.x yet (this is a very big task). However the use of opkg will be perfect for IPv6 requirements, plus you can install many additional packages like nano, zabbix_agentd etc.
- This article assumes you already know how to setup an IPv6 tunnel on DD-WRT e.g. using HE.net (Hurricane Electric) or SixXS
- Basic Linux knowledge
- Comfortable with SSH access
- Have some spare time to do all of this!
What’s under the hood?
First of all, there are various different 3.x kernel builds around, you first need to establish what kernel you are running, a simple command like:
Will give your kernel version number. e.g. 3.10.2. You can run the command below that will automatically search for what IPv6 modules you have already in the firmware.
find /lib/modules/$(uname -r)/kernel/ -name *6*
The returned result will look something like this:
/lib/modules/3.10.2/kernel/crypto/sha256_generic.ko /lib/modules/3.10.2/kernel/fs/nls/nls_cp936.ko /lib/modules/3.10.2/kernel/lib/crc16.ko /lib/modules/3.10.2/kernel/lib/raid6 /lib/modules/3.10.2/kernel/lib/raid6/raid6_pq.ko /lib/modules/3.10.2/kernel/net/ipv6 /lib/modules/3.10.2/kernel/net/ipv6/ipv6.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/ip6_tables.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/ip6t_MASQUERADE.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/ip6t_NPT.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/ip6t_REJECT.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/ip6t_mh.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/ip6table_filter.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/ip6table_mangle.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/ip6table_nat.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/nf_conntrack_ipv6.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/nf_defrag_ipv6.ko /lib/modules/3.10.2/kernel/net/ipv6/netfilter/nf_nat_ipv6.ko /lib/modules/3.10.2/kernel/net/l2tp/l2tp_ip6.ko
The build I am running gives me nearly all the kernel modules required, the modules I was interested in were:
ip6_tables ip6t_REJECT ip6table_filter nf_defrag_ipv6 nf_conntrack_ipv6
Because I am running a fairly large size build, you will probably not have all these modules already in the firmware. If that is the case your going to need to get your hands dirty and compile them manually. Doing this, requires a fair bit of work initially and hence is covered in another post, but its valuable experience.
Regardless of the presence of the above modules there is also one module that I had to compile manually and that was:
Why do I need these IPv6 modules?
Assuming you’ve read the other post about compiling modules, hopefully it has been able to help you get the required IPv6 modules. These modules are in fact for ip6tables, which is the firewall solution we will use to protect our network. The truth is, you don’t have to have ip6tables to have IPv6 connectivity, but in reality, having no IPv6 firewall is a bad idea. Because IPv6 has no NAT, so this means ports like 3389 (Microsoft Remote Desktop) and other pretty serious ports are going to potentially be wide open to the outside world. So we need these modules to create strong ip6tables rules to firewall our IPv6 clients, while allowing IPv6 connectivity.
More tunnel related dependencies
Up until recently before the following change committed to SVN. DD-WRT did not automatically load the ip_tunnel module by default in the 3.x builds, this meant that any IPv6 stuff would fail, as ip_tunnel is a must for IPv6 tunnels, the sit module is also required which is loaded but because the ip_tunnel module is a dependency, it wouldn’t actually be loaded either. With this information you will need to make sure that you load the ip_tunnel module before the IPv6 stuff, this will be automatically loaded in builds after 22118, but for now you’ll need to load them.
Loading the custom ipv6 modules:
This is where jffs comes in handy, you have the modules but now what? Putting them on your jffs partition is a handy as ultimately you’ll be able to insmod the modules on boot in your .rc_startup script. For now however you’ll want to manually load each module in order to confirm each one loads without error.
Create a directory on jffs to hold the modules
mkdir -p /jffs/lib/modules/$(uname -r)
This will create a directory name matching your kernel version. Now move your custom ipv6 modules into this folder, you can do this via SCP, FTP many different ways. Now its time to test the modules to see if they work. This can be done using insmod, you should load the modules in the following order:
ip_tunnel sit ip6_tables ip6t_REJECT ip6table_filter nf_defrag_ipv6 nf_conntrack_ipv6 ip6t_rt
Now, if you are loading modules that are already within the firmware, you can simply run:
If however, you are wanting to insmod a custom compiled module stored on jffs, you will need to specify the full path e.g.
insmod /jffs/lib/modules/$(uname -r)/[module_name].ko
Replace [module_name] with the actual module name e.g. ip6r_rt. Observe any errors when loading the modules (if any), if you run the command and it completes without any output, its usually a good sign that the module loaded successfully, you can re-run the insmod command again, you will most likely get something like this:
insmod: can't insert 'ip_tunnel': File exists
This means the module loaded. If you get any errors, its usually because of dependencies. You can run:
To find out what caused the module not to load, often errors include, unknown symbol, which again is nearly always a missing module that is a dependency. See how BrainSlayer (Lead dev of DD-WRT) gave me a quick lesson in module dependencies.
Loading these modules on boot
Now that you have tested the modules, these need to be loaded on boot, you can put something similar to this in your startup script:
insmod ip_tunnel insmod sit insmod ip6_tables insmod ip6t_REJECT insmod ip6table_filter insmod nf_defrag_ipv6 insmod nf_conntrack_ipv6 insmod /jffs/lib/modules/$(uname -r)/ip6t_rt.ko
Note: Adjust the location of modules to match your setup. As I said earlier, having the big builds of DD-WRT allows the firmware to have most of the modules compiled in already, adjust paths accordingly for your situation, its likely you’ll be loading most of them off jffs.
Once you’ve done that, click save and these modules will now get loaded on boot permanently. Reboot your router to confirm, you can run:
To see the list of modules loaded. Confirm ALL the mentioned modules appear.
DD-WRT 3.x builds (or at least bigger builds) does come with ip6tables already compiled in, the problem is the version is a bit old (1.3.7) and this mean you could potentially end up seeing this error with various chains:
ip6tables v1.3.7: Couldn't find match `rt'
ip6tables 1.3.7 doesn’t work with rt, even if the module is loaded. An updated ip6tables version is required. In comes opkg to solve this problem:
opkg --force-depends install kmod-ip6tables opkg --force-depends install ip6tables
The output of this is going to look like it failed horribly, when in fact its actually OK. You don’t need to worry about this messing up your firmware, remember this is all on the /opt partition. Despite all of the errors a newer version of ip6tables should have installed, you can confirm this by running:
You should get two paths returned:
ip6tables: /usr/sbin/ip6tables /opt/usr/sbin/ip6tables
Reboot your router and ip6tables should now be using the opt version when it comes back up, you can confirm this by simply running “ip6tables” which should give you:
ip6tables v184.108.40.206: no command specified Try `ip6tables -h' or 'ip6tables --help' for more information.
The version number may differ, but if its higher than 1.3.7, you’ve got a newer version of ip6tables. Interestingly, iptables also seems to get a upgrade, but again this will function as normal, any rules you already have in your firewall startup script will continue to work!
This isn’t the most elegant solution to upgrading ip6tables, if you want a more cleaner solution, you could compile ip6tables yourself specifically for the MIPS architecture and then copy the compiled content onto /opt but I won’t go into that here. The dirty way is fine, though this will cause some errors to be printed each time you run opkg.
The IPv6 firewall with ip6tables
Now its time to load ip6tables with some firewall rules, the DD-WRT community has provided some great firewall solutions for two of the major IPv6 tunnel providers, HE.net and SixXS, you can find them here:
If you use another IPv6 tunnel broker, search around for some IPv6 firewall rules, or formulate generic rules.
With the above ip6tables rules, all you need to do is put them in your firewall script (where you put normal iptables a.k.a ipv4 rules). Reboot your router and see if you’ve got IPv6 connectivity. Some good test sites are:
After this you should have IPv6 connectivity with your IPv6 enabled clients protected by the firewall on the router.