2016-08-04 08:30 by pjotrp

1 Linux on the Wireless Router with OpenWRT (WNDR3700/3800)

or why you should run Linux on your coffee maker

All my computers run Linux. It gives a shared common platform, which is easy to secure and update. The investment in understanding workstations and servers (both physical and in the, so called, Cloud) is a one time event. I (secretly) smile when people struggle with Windows.

In 2010 I had to replace an old wifi router. I opted for Netgears running OpenWrt. These small devices are so powerful that they can act as little servers. The Netgear WNDR3700 or WNDR3800/N600 runs Linux, even from factory, and I can use it for computing, as well as data storage (it has USB 2.0). Apart from wifi, firewalling, NATing, QoS, I use it the Netgear to control with heyu the lights and waterbed through the X10 over USB. At last count I have five WNDR3700s and WNDR3800s, doing odd jobs and programmed with Coffeescript/Javascript! If your device has enough storage space (internal or external), you may even run Ruby or Python on it, openwrt has binary packages for these scripting languages. Today I updated a router (Aug. 2016). I am still running OpenWrt on five Netgears.

So, why do I want to replace perfectly good software that comes with a device? The reason is that I want predictable systems that I can upgrade and program! Upgrades are important, both for security and features. Recently we got IPv6 out of the box, and it works even on the oldest routers.

As an aside, it may be interesting to know that the Netgears come with a MIPS 24K CPU (680 MHz, 450 bogomips). The same chip instruction set that has been used in super computers and SGI graphics work horses. The history of MIPS is an interesting read. The WNDR3800 has 12 Mb of flash storage space for software on board and up to 128Mb RAM. An external storage can be hooked up through USB. That is a lot of computer for that money! And it has a lot more computing power than one of the first computers I owned (a 386 having 0.57 bogomips).

My wifi routers are always on devices which handle some traffic load. Sometimes I have them open for outsiders. Some advantages I may have with OpenWRT is to provide a closed and open network. I can combine wifi and LAN networks to appear as one. In addition I may be able to close down a humming backup server in the house, as well as control heating and play music from the router itself. And then, because the router has 2 radios, I can use it as a cheap and generic wifi repeater. Is that all? Probably not. One major advantage of a Linux system is that I get the programmable command prompt. A web interface for managing a device is nice, but being able to program repetitive tasks is much nicer. And you get useful tools, such as nmap, iw and traceroute.

OpenWRT is a Linux distribution for Wireless routers. Googling 'openwrt install WNDR3700' returned a number of useful sites. In particular the instructions on the OpenWrt Wiki. But, do make sure your device is supported by OpenWRT! The 3rd make of the 3700 is not supported - therefore avoid WNDR3700v3. Sometimes the chipset changes even under one model name (blame the manufacturer). Do double check those details.

First I hooked the Netgear up on the network, booted, and attached a laptop through the wifi. The web interface came up. I decided not to worry about saving the standard firmware, as Netgear has it for download and you can rescue this device into failsafe mode even when 'bricked'.

Choose a binary download for the relevant CPU, in this case something like openwrt-ar71xx-wndr3700-squashfs-factory.img from http://downloads.openwrt.org/ and upload it through the web interface (login admin:password, choose router or firmware upgrade, make sure the image matches your device, e.g. wndr3700, wndr3700v2, or wndr3800) using a local cable to the router (could it be that easy?).

After the reboot there was no wireless, so I had to hook up a cable to the router itself and use telnet to, but first on the laptop

  ifconfig wlan0 down
  dhclient eth0
  # or alternatively set up a virtual interface:
  ifconfig eth0:1 netmask

Man! That was easy.

BusyBox v1.22.1 (2014-09-20 22:01:35 CEST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

_______ ________ __ | |.-----.-----.-----.| | | |.----.| |_ | - || _ | -__| || | | || _|| _| |_______|| __|_____|__|__||________||__| |____| |__| W I R E L E S S F R E E D O M ----------------------------------------------------- BARRIER BREAKER (14.07, r42625) ----------------------------------------------------- * 1/2 oz Galliano Pour all ingredients into * 4 oz cold Coffee an irish coffee mug filled * 1 1/2 oz Dark Rum with crushed ice. Stir. * 2 tsp. Creme de Cacao ----------------------------------------------------- root@OpenWrt:~#

A command prompt!

After changing the root password with 'passwd' you can login with ssh. Your public ssh key can be copied into /etc/dropbear/authorized_keys.

At this point it is probably a good idea to record settings/configuration in /etc and /overlay/etc. I do that with git and (on the smallest routers) with scp and git (on the workstation).

After downloading some packages, as described on the OpenWRT wiki

root@OpenWrt:~# opkg update
root@OpenWrt:~# opkg install wpad-mini kmod-ath9k kmod-leds-wndr3700-usb
root@OpenWrt:~# wifi up

a diff shows

--- a/etc/config/wireless
+++ b/etc/config/wireless
@@ -0,0 +1,36 @@
+config wifi-device  radio0
+       option type     mac80211
+       option channel  5
+       option macaddr  30:46:9a:0b:91:59
+       option hwmode   11ng
+       option htmode   HT20
+       list ht_capab   SHORT-GI-40
+       list ht_capab   DSSS_CCK-40
+       option disabled 1
+config wifi-iface
+       option device   radio0
+       option network  lan
+       option mode     ap
+       option ssid     OpenWrt
+       option encryption none
+config wifi-device  radio1
+       option type     mac80211
+       option channel  36
+       option macaddr  30:46:9a:0b:91:5b
+       option hwmode   11na
+       option htmode   HT20
+       list ht_capab   SHORT-GI-40
+       list ht_capab   DSSS_CCK-40
+       option disabled 1
+config wifi-iface
+       option device   radio1
+       option network  lan
+       option mode     ap
+       option ssid     OpenWrt
+       option encryption none

Remove the disable line and reboot. Done!

Note: if opkg is not working you may need to change the network settings in /etc/config/network.

There even is a web interface. I used it to install an open and a private network - and you know what, I like it.

At this point you should have a fully functional wifi router.

1.1 Configuring the network

A fresh install has

root@OpenWrt:~# uci show network.wan
root@OpenWrt:~# uci show network.lan

When connecting the WAN it came on and only etc/ppp/resolv.conf was modified. The LAN is a perfect pass through.

My main change is the essid. After editing etc/config/wireless restart

wifi down
wifi up

At this stage the wlan is combined with the lan.

1.1.1 Blocking unknown MAC addresses

One of the brilliant uses of OpenWrt is standard iptables. Here we only allow some hardware MAC addresses to use the WIFI. First list the connected MAC adresses with

  cat /proc/net/arp

next add the following rules

  iptables -A forwarding_rule -i br-lan -j DROP
  iptables -I forwarding_rule -i br-lan -m mac --mac-source 00:1f:e2:14:1f:68 -j ACCEPT
  iptables -I forwarding_rule -i br-lan -m mac --mac -source 00:1d:e0:01:5c:07 -j ACCEPT

These rules can be stored in /etc/firewall.user or /etc/init.d/firewall.

This way you can find MAC addresses without even having to look them up on clients.

1.2 Encryption

  opkg update
  opkg install wpad-mini
  uci set wireless.@wifi-iface[0].encryption=psk2
  uci set wireless.@wifi-iface[0].key="your_password"
  uci set wireless.@wifi-iface[1].encryption=psk2
  uci set wireless.@wifi-iface[1].key="your_password"
  uci commit wireless

if you see 'WPA: Not enough entropy in random pool for secure operations' on 'wifi' you may want to add to /etc/init.d/boot:

  rm /dev/random ; ln -s /dev/urandom /dev/random

1.3 Port forwarding

Port forwarding is easy too. Edit /etc/config/firewall, or better /etc/firewall.user.

For using ssh on the router from a designated IP address:

        config 'rule'
        option '_name' 'ssh'
        option 'src' 'wan'
        option 'target' 'ACCEPT'
        option 'proto' 'tcp'
        option 'dest_port' '22'
        option src_ip ''

For forwarding a service on a desktop in the network using port 8080:

config 'redirect' 'torrent'
        option 'src' 'wan'
        option 'proto' 'tcp'
        option 'src_ip' ''
        option 'src_dport' '8080'
        option 'dest_ip' ''
        option 'dest_port' '8080'
config 'rule'
        option 'src' 'wan'
        option 'proto' 'tcp'
        option 'src_ip' ''
        option 'dest_ip' ''
        option 'dest_port' '8080'
        option 'target' 'ACCEPT'

and restart the firewall

  root@linuxwifi01:~# /etc/init.d/firewall restart &

1.4 Repeater function

One one router I use radio0 as a receiver, and radio1 as a transmitter. Surprisingly with little speed loss. This page contains instructions for setting up a receiver. What I did:

  1. in /etc/config/network config interface 'wan' option proto 'dhcp'
  2. in /etc/config/wireless config wifi-iface option 'device' 'radio0' option 'network' 'wan' option 'mode' 'sta' option 'ssid' 'AnyRouter_11' # connecting to remote SSID using key option 'encryption' 'psk' # replace with psk2 for WPA2 option 'key' '****'

config wifi-device 'radio0'
        option type 'mac80211'
        option channel '11'
        option hwmode '11ng'
        option path 'pci0000:00/0000:00:11.0'
        option htmode 'HT20'
        list ht_capab 'SHORT-GI-40'
        list ht_capab 'TX-STBC'
        list ht_capab 'RX-STBC1'
        list ht_capab 'DSSS_CCK-40'
        option mode 'sta'

Not much to it. Now you can have a strong signal everywhere by adding these little boxes running OpenWrt. Make sure every box has it's own unique subnet - conflicting networks are no fun. Also make sure the password is correct - I have been caught out twice that way.

The settings for radio1 are the same as the default wifi. If you screw up, simply move /etc/config/wireless somewhere and run 'wifi detect'.

1.5 USB storage

  opkg install kmod-usb2
  opkg install kmod-usb-storage
  opkg install kmod-fs-ext3
  opkg install kmod-fs-ext4

Add this to /etc/config/fstab

  config mount
    option target   /mnt/extdrive
    option device   /dev/sda2
    option fstype   ext3
    option options  rw,sync
    option enabled 1


  mount /dev/sda1 /mnt/extdrive

1.6 Monitoring traffic

To monitor the network you can install tcp

  opkg install tcpdump
  tcpdump -i eth1

An interesting tool is

  opkg install iftop
  iftop -i br-lan

Which shows the network load for each computer. Weed out those torrent users!

And there is nmap. Problem with nmap is that it needs space. But you can install it on an external drive with opkg! So after mounting the USB drive

tell opkg where install in /etc/opkg.conf, add the line

  dest usb /mnt/export


  opkg -dest usb install nmap

now run

  /mnt/export/usr/bin/nmap -sP

it'll complain about a few libraries, which can be symlinked, e.g.

  cd /usr/lib
  ln -s /mnt/export/usr/lib/libdnet.so.1

and I needed to get /etc/services from somewhere.

Even though above looks a bit tedious, it is very exciting that it just works:

  Starting Nmap 4.20 ( http://insecure.org ) at 2011-03-29 18:31 CEST
  Host appears to be up.
  Host appears to be up.
  Host appears to be up.
  Host appears to be up.
  Nmap finished: 256 IP addresses (4 hosts up) scanned in 4.890 seconds

Having an external USB drive opens tons of possibilities!

1.7 Restricting upload speeds

When someone maximizes router upload speed, other users may get very slow network speeds. Effectively denial of service. One of the great facilities of OpenWRT is quality of service (QoS). I use qos-scripts currently. For example:

  opkg install qos-scripts
  uci set qos.wan.upload=800           # Upload speed in kBits/s ~ 100 Kbs
  uci set qos.wan.download=16000       # Download speed in kBits/s
  uci commit qos


  /etc/init.d/qos start

On reboot

  /etc/init.d/qos enable

1.8 External IPv6 on the router

The Internet is running out of the IPv4 address space. OpenWRT is ready for IP6, and can be accessed from outside, provided your ADSL modem can pass it through. See, for example, this tutorial.

Note that IPv6 comes out of the box now (see below).

1.9 Rebuilding/upgrading OpenWRT

The next phase required rebuilding the OpenWRT image which you can do by downloading an upgrade image. I wanted serial-usb support for one and use a pcsensor temperature device on another which requires a rebuild. That turned out to be straightforward too - and brought back the days of Linux kernel configuration; so rare these days. Basically, download the source, configure modules and tools using menuconfig and build (all described on mentioned wiki page).

  git clone git://git.openwrt.org/openwrt.git
  cd openwrt
  vi feeds.conf.default
  ./scripts/feeds update -a
  ./scripts/feeds install -a
  make defconfig
  make menuconfig
  make -j 2

1.9.1 Upgrade the image

Next upload the built img with scp

  scp openwrt-ar71xx-generic-wndr3700-squashfs-sysupgrade.bin root@

(note the /tmp dir may have more space) and install the image with one command

  sysupgrade -v openwrt-ar71xx-generic-wndr3700-squashfs-sysupgrade.bin

The system saves config files (if you remove /etc/config they will get rewritten), flashes the new image, and reboots. This can also be done through the web interface.

Amazingly it just comes up as before. Even the logins are retained.

If you intend to write your own compiled software you'll need to use the OpenWrt SDK. A quick useful HOWTO can be found here. The quickest way to get going is to download an SDK binary for the target architecture. Note that you do not need to do this for the common interpreted languages, including Ruby, Python and JavaScript.

The package system is 'opkg', and is highly inspired by Debian's apt-get. To list all available packages

  opkg update
  opkg list

To make the wifi work again, don't forget to upgrade the earlier packages.

Standard packages I use are

  opkg install  wpad-mini kmod-ath9k kmod-leds-wndr3700-usb nmap git iftop

For programming OpenWrt comes with Ruby (600K), Python (2 Mb) and Javascript (300K). So I do

  opkg install  ruby js

Note: rebuilding your image is probably not required as most kernel modules (drivers) are available through opkg. I mounted a USB drive successfully and use it as a backup device now using secure rsync.

1.10 Running X10 controller

For years I have X10 to switch on the house lights and control the heating and waterbed. For this the 'heyu' command line tool does the job and can be installed with OpenWRT

  opkg update
  opkg install kmod-usb-serial-pl2303
  opkg install setserial
  opkg install heyu

Heyu uses the USB to communicate with an X10 device, so first disable the serial terminal by commenting out in /etc/inittab

  # ttyS0::askfirst:/bin/ash --login

Restart inittab

  kill -HUP 1

Heyu has a help system - try 'heyu help' - and configuration is in /etc/heyu/x10.conf. Modify the line

  TTY             /dev/ttyUSB0

To run on ttyS0 you may need to move it to IRQ 3 with

  setserial /dev/ttyS0 irq 3

When you plug in the X10 USB connector, the log should show:

  [  382.390000] pl2303 2-1:1.0: pl2303 converter detected
  [  382.410000] usb 2-1: pl2303 converter now attached to ttyUSB0
  heyu info

if above does not show, something is wring with the kernel/modules.

    starting heyu_relay
    09/08 15:51:50  Poll received unknown value (1 bytes), leading byte = a5
    Heyu version 2.9.1
    Configuration at /etc/heyu/x10.conf
    Powerline interface on /dev/ttyUSB0
    Firmware revision Level = 8
    Interface battery usage = Unknown
    Raw interface clock: Thu, Day 250, 15:51:51
    (--> Civil Time: Thu 08 Sep 2011   15:51:51 UTC)
    No schedule has been uploaded by Heyu.
    Housecode = A
    0 = off, 1 = on,               unit  16.......8...4..1
    Last addressed device =       0x0000 (0000000000000000)
    Status of monitored devices = 0x0000 (0000000000000000)
    Status of dimmed devices =    0x0000 (0000000000000000)

Now add an alias

ALIAS  light1             A1   StdAM

and switch it on from the command line with

  heyu on light1

The rest is up to you - read the Heyu documentation. Because Heyu/X10 is command line driven you can use any type of scheduler and web interface to drive your electronics! I wrote a Coffeescript/Javascript state machine for Heyu, which runs on OpenWRT. See the source code on github.

1.11 Reverse ssh

The default dropbear ssh allows you to connect from outside through a reverse ssh server, as described here. Basically

  mkdir ~/.ssh
  dropbearkey -t rsa -f ~/.ssh/id_rsa
  dropbearkey -y -f ~/.ssh/id_rsa | grep '^ssh-rsa' >> authorized_keys

copy that key to the server and you should be able to login the server without a password with 'ssh -i ~/.ssh/id_rsa'. Next, set up a tunnel

  ssh -i .ssh/id_rsa -L 42424:localhost:22 -f -N pjotr@myserver.org

now you can login with

  ssh -i .ssh/id_rsa -p 42424 pjotr@localhost

Next we try a reverse tunnel

  ssh -i .ssh/id_rsa -R 42424:localhost:22 -f -N pjotr@myserver.org

this time login on the remote with

  ssh -p 42424 root@localhost


Add the reverse tunnel to a CRON job. Make sure to enable the CRON daemon

  /etc/init.d/cron enable
  /etc/init.d/cron start

The CRON job (adapted from this blog) runs

% 10 * * * * ps |grep thebird|grep -v grep ; test \$? -ne 0 && ssh -i /root/.ssh/id_rsa -R 3702:localhost:22 -f -N pjotr@myserver.org
root@OpenWrt:~# cat watch_tunnel.sh
#! /bin/sh
COMMAND="ssh -i /root/.ssh/id_rsa -f -N -R $FPORT:$CONN $USERHOST -p $RPORT"
pgrep "ssh" > /dev/null 2>&1 || $COMMAND
ssh -i /root/.ssh/id_rsa $USERHOST -p $RPORT netstat -an | egrep \
  "tcp.*:$FPORT.*LISTEN">/dev/null 2>&1
if [ $? -ne 0 ] ; then
  # pkill -f -x "$COMMAND"
  killall ssh

which makes sure only one tunnel is running at a time.

The CRON entry reads:

1 * * * * /root/watch_tunnel.sh
0 */6 * * * killall ssh

Test cron with

    crond -c /etc/crontabs -l 0 -f

1.12 Time

To get CRON to work correctly, make sure ntpd works! In /etc/config/system

config rdate list server 'ptbtime1.ptb.de' list server 'ntp.xs4all.nl' list server 'ptbtime2.ptb.de'

config timeserver 'ntp'
        list server 'ntp.xs4all.nl'
        list server 'ptbtime1.ptb.de'
        option enable_server '0'

Note, this does not start ntp at reboot. You may want to add

/sbin/ntpd -g -u ntp:ntp -p /var/run/ntpd.pid

to /etc/rc.local.


1.13 Using git

Even git is supported on openwrt, and takes only 2Mb of your drive! Very useful when you start tweaking settings.

  opkg update
  opkg install git
  cd /etc
  git init
  git add .
  git commit -a -m 'first commit'

To tell it to use an ssh key, you need to wrap the ssh command

  cat /usr/bin/sshwkey
    #! /bin/sh
    ssh -i /root/.ssh/id_rsa \$*
  chmod a+x /usr/bin/sshwkey

Test it by logging in to your remote server. Next tell git to use this script for ssh access

  export GIT_SSH=/usr/bin/sshwkey

1.14 A running Netgear WNDR3700 (v1)

The following are the stats of a freshly installed OpenWrt WNDR3700 (v1) router with 64Mb of RAM. This is after a full day of use using two wifi radios and LAN to access the internet:

Mem: 31996K used, 29072K free, 84K shrd, 2080K buff, 6088K cached
CPU:   0% usr   0% sys   0% nic  98% idle   0% io   0% irq   0% sirq
Load average: 0.00 0.01 0.05 1/37 1688
 1544     1 root     S     1648   3%   0% /usr/sbin/hostapd -P /var/run/wifi-ph
 1688  1353 root     R     1364   2%   0% top
 1558     1 root     S     1648   3%   0% /usr/sbin/hostapd -P /var/run/wifi-ph
  838     1 root     S     1568   3%   0% /sbin/netifd
  804     1 root     S     1532   3%   0% /sbin/rpcd
    1     0 root     S     1408   2%   0% /sbin/procd
 1366     1 root     S     1364   2%   0% /usr/sbin/ntpd -n -S /usr/sbin/ntpd-h
 1353  1352 root     S     1364   2%   0% -ash
 1603  1602 root     S     1364   2%   0% -ash
 1230   838 root     S     1360   2%   0% udhcpc -p /var/run/udhcpc-eth1.pid -s
 1352   896 root     S     1244   2%   0% /usr/sbin/dropbear -F -P /var/run/dro
 1602   896 root     S     1244   2%   0% /usr/sbin/dropbear -F -P /var/run/dro
  863     1 root     S     1164   2%   0% /usr/sbin/odhcpd
  896     1 root     S     1152   2%   0% /usr/sbin/dropbear -F -P /var/run/dro
  795     1 root     S     1044   2%   0% /sbin/logd -S 16
 1284     1 nobody   S      952   2%   0% /usr/sbin/dnsmasq -C /var/etc/dnsmasq
  455     1 root     S      892   1%   0% /sbin/ubusd
 1228   838 root     S      800   1%   0% odhcp6c -s /lib/netifd/dhcpv6.script
  456     1 root     S      772   1%   0% /sbin/askfirst /bin/ash --login
qd^C3     2 root     SW       0   0%   0% [ksoftirqd/0]
root@huuske-fb:~# df
Filesystem           1K-blocks      Used Available Use% Mounted on
rootfs                    4224      1424      2800  34% /
/dev/root                 2304      2304         0 100% /rom
tmpfs                    30532        84     30448   0% /tmp
/dev/mtdblock5            4224      1424      2800  34% /overlay
overlayfs:/overlay        4224      1424      2800  34% /
tmpfs                      512         0       512   0% /dev
root@huuske-fb:~# free
             total         used         free       shared      buffers
Mem:         61068        32068        29000           84         2080
-/+ buffers:              29988        31080
Swap:            0            0            0
root@huuske-fb:~# df -h
Filesystem                Size      Used Available Use% Mounted on
rootfs                    4.1M      1.4M      2.7M  34% /
/dev/root                 2.3M      2.3M         0 100% /rom
tmpfs                    29.8M     84.0K     29.7M   0% /tmp
/dev/mtdblock5            4.1M      1.4M      2.7M  34% /overlay
overlayfs:/overlay        4.1M      1.4M      2.7M  34% /
tmpfs                   512.0K         0    512.0K   0% /dev

1.15 A full install

One router was installed over 4 years ago (in 2012) and faithfully running since(!). Upgrading the device to a recent 'chaos_calmer' (not least to get IPv6 support) it is probably wise to wipe the configuration in /etc. After doing a system upgrade as described above run 'firstboot' to erase all settings. After a reset/reboot the clean system should come up on telnet again. To get a minimal system I did additionally

  opkg update
  opkg install nmap iftop tcpdump curl
  opkg install wget git ruby js kmod-usb-storage kmod-fs-ext3 kmod-fs-ext4

note that many modules are already included these days. Also, the oldest WNDR3700 may not have the space to include largish git, nmap, ruby etc.

1.16 First configuration

Set the root password with


so ssh opens and telnet closes (the device is fully firewalled from the outside), and from the remote copy the fresh configuration with

  scp -r root@ .
  cd etc
  git init
  git add .
  git commit -a -m 'init'

now we can keep track of changes with git on your work station which also acts as a backup.

1.17 Disable the webserver

opkg remove --force-removal-of-dependent-packages luci uhttpd

reboot and check the ps table.

1.18 Configure sshd (dropbear)

After setting the password ssh is open through the lan and wifi, but not from the wan. I prefer to disable password access too. Create an RSA key (I keep one for the routers) and cp it into /etc/dropbear/authorized_keys. Make sure the file has 0600 permission.

When that works set passwordAuth to 'off' in /etc/config/dropbear.

Coming from another computer you should no longer have ssh password access. With key access I opened the wan also, so in /etc/conf/firewall

  config rule
        option src              wan
        option dest_port        22
        option target           ACCEPT
        option proto            tcp

1.19 Bricked a router?

If you brick a router, openwrt has a failsafe mode which will allow telnet access again.

You should try it. Switch the router off and then on. When the broadcast light blinks hit a button. It should start blinking faster. Next you can telnet to Reboot to get out of failsafe again.

1.20 Finally use IPv6

IPv6 comes out of the box! 'ifconfig' should show inet6 addr for all network devices, including the ones that get connected to the wifi. Awesome. Check the router wan interface with

  route -6
  ping6 fd57:348:5d34:0:3246:9aff:fe0b:915a
  nmap -6 fd57:348:5d34:0:3246:9aff:fe0b:915a
  ssh -i openwrt_key -v -6 root@fd57:348:5d34:0:3246:9aff:fe0b:915a

and we have a shell prompt. From the lan you can do

  ssh -6 -i openwrt_key root@fd2b:e412:1d9a::1