This weekend, I finally reinstalled OpenWrt on my home router. I've been using a nightly build for several months now, and it had been working just fine, but unfortunately, the opkg (OpenWrt's package manager) repositories for the nightly builds are updated every few days, and all of the kernel modules have hard dependencies on a specific kernel version. So in order to install a new kernel module, I would have to upgrade my OpenWrt version every time – not very convenient.
Luckily, there is a release candidate for the newest version, called "Attitude Adjustment", which is what I upgraded to. This went without any major problems and I was even able to keep my configuration, but I had to reinstall all packages not included by default. At this opportunity, I decided to document my configuration and installed packages.
Bufferbloat is a nasty phenomenon that occurs mostly on residential internet connections. In a nutshell, hugely oversized buffers combined with static queue management in cable and DSL modems cause huge delays during large uploads, which can lead to a very bad experience for interactive applications. I use a SIP phone to make voice calls, and previously to my solution, it was nearly impossible to make a phone call at the same time as somebody uploading pictures or videos on the same network – now it works just fine.
The solution to Bufferbloat is two-fold: First, the available bandwidth has to be limited on the router to just below the bandwith actually available to the modem, in order to avoid any buffering in the modem. Then, some adaptive or even "fair" queueing algorithm like CoDel can be used. Both tasks can be achieved via the Linux packet scheduler and its managment tool,
tc. Both are available as OpenWrt packages:
opkg install tc kmod-sched
uci, OpenWrt's configuration system, doesn't support custom packet schedulers yet, so my setup script is implemented as a shell script that is executed once at every boot of the router.
# Insert the necessary kernel modules
# Reset the queueing disciplines
tc qdisc del dev eth1 root
tc qdisc del dev br-lan root
# Add a HTB queue to the internal interface (to limit upload speeds)
tc qdisc add dev eth1 root handle 1: htb default 1
# Limit the upload speed to 2048 kbit/s (adjust this to just below your actual upload speed!)
tc class add dev eth1 parent 1: classid 1:1 htb rate 2048kbit
# Enable CoDel as a queueing algorithm for the queue
tc qdisc add dev eth1 parent 1:1 handle 11: fq_codel
# The same for download speeds - adjust accordingly
tc qdisc add dev br-lan root handle 1: htb default 1
tc class add dev br-lan parent 1: classid 1:1 htb rate 32768kbit
tc qdisc add dev br-lan parent 1:1 handle 11: fq_codel
This solved the Bufferbloat issue completely for me, but if it works for you depends on a lot of factors - test the script before enabling it at every boot.
IPv6 connectivity via an HE 6in4 tunnel
OpenWrt works with IPv6 out of the box. If your provider isn't supplying you with native v6 connectivity yet (which is unfortunately still very likely), you can use a free tunnel provided by Hurricane Electric. The registration process is pretty straightforward, and HE even provide configuration samples for many routers and operating systems. The one for OpenWrt didn't work for me (which was probably my fault, so you should give it a try!), but this one does:
First, the 6in4 tunneling module has to be installed:
Then, the tunnel interface can be configured in
For the local network, an IPv6 address has to be configured for the router. It can be any address in one of the "Routed IPv6 Prefixed" shown in the tunnel details on tunnelbroker.net, so if you were assigned the prefix
2001:470:1b:1234::/64, you could choose
config interface 'lan'
option ifname 'eth0'
option type 'bridge'
option proto 'static'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
option ip6addr '2001:470:1b:1234:1/48'
The 6in4 tunnel interface has to be configured like this (assuming your "Client IPv6 address" is
2001:470:1a:1234::2, your "Server IPv4 address" is
220.127.116.11, and your "Tunnel ID" is
config interface 'henet'
option proto '6in4'
option peeraddr '18.104.22.168'
option ip6addr '2001:470:1a:1234::2/64'
option tunnelid '12345'
option username 'your.username'
option password 'yourpassword'
Username and password are not identical to your HE login credentials – they can be retrieved on the "Example Configurations" tab on the "Tunnel Details" page.
To configure the firewall, you can exceuted the command provided by HE (
uci set firewall.@zone.network='wan henet'), or manually insert the line
option network 'wan henet' to the
wan block in the file
If you want to use one of IPv6's nicest features, stateless autoconfiguration,
radvd has to be installed...
...and configured like this (in
option interface 'lan'
option AdvSendAdvert 1
option AdvManagedFlag 0
option AdvOtherConfigFlag 0
list client ''
option ignore 0
option interface 'lan'
list prefix '2001:470:1b:1234::/64'
option AdvOnLink 1
option AdvAutonomous 1
option AdvRouterAddr 0
option ignore 0
OpenWrt has built-in support for many dynamic DNS services, and the documentation on their wiki has all you need to configure it.
Specific ports of devices behind the OpenWrt NAT can be made reachable by a block like this in
option 'name' 'myhomeserver'
option 'src' 'wan'
option 'proto' 'tcp'
option 'src_dport' '22'
option 'dest_ip' '192.168.1.123'
option 'dest_port' '22'
option 'target' 'DNAT'
option 'dest' 'lan'
Port mirroring with iptables
My main motivation for upgrading to the release candidate was actually an iptables module called
tee. It can be used to duplicate all or a subset of all packets going throuth the router and transmit them to some other host running a packet analyzer like Wireshark. This can be very useful to debug embedded wireless devices without having to resort to a Wifi card running as a packet sniffer, which was my previous approach.
In order for the following command to work, the
tee module has to be installed on the router. For some reason,
ip6tables is also required, or loading the module will fail:
opkg install iptables-mod-tee ip6tables
To forward all traffic going through the router to a machine in the private network at 192.168.1.123, simply exceute this command in a shell:
iptables -A POSTROUTING -t mangle -j TEE --gateway 192.168.1.123
The forwarded packets will still show the internal IP addresses, which makes finding a specific device much easier.
To be continued
That's my configuration for now – I hope to be able to update this blog regularly if I find some improvements to my setup.
There are comments.