Hacking the Fonera social router

Motivation

I'd like to use the Fonera social router as a gateway routing my local cable-bound network to our wireless network. The Fonera should still provide network access to all other Foneros, as intended by Fon.

In this document I documented all my steps and all those things I discovered which might be usefull to other people as well.

Getting access

I used the 'grammofon' method described in #2 and used the Foneras serial console using #3 as a reference for the connector pinout for a resurrection (the dhcp client I started from an initscript didn't return leaving the system in an unusable state). using the serial connector

Architecture

The Fonera social router is a Atheros System on a Chip (Soc). Its Firmware is a customized OpenWRT. For more information take a look at #1.

Filesystems

root@OpenWrt:~# mount
/dev/root on /rom type squashfs (ro)
none on /dev type devfs (rw)
none on /proc type proc (rw)
none on /tmp type tmpfs (rw,nosuid,nodev)
none on /dev/pts type devpts (rw)
/dev/mtdblock/2 on /jffs type jffs2 (rw)
/ on / type mini_fo (rw)
        

/ is a unionfs of /rom (stored in flash memory) and /jffs (writable persistend storage). So every file thats modified is copied to /jffs first and is used instead of its counterpart in /rom.

Boot process

The Fonera uses SYSV style init (from busybox). There are a couple of scripts in /etc/init.d:

root@OpenWrt:~# cd /etc/init.d ; ls
N10conncheck   N50chillispot  S45firewall  S50telnet    S65watchdog  rcS
N40thinclient  S20madwifi     S50httpd     S60cron      boot
N45ntpclient   S40network     S50qos       S60redirect  dropbear
        

rcS is the script called by init. It first executes boot, aquires locks on the files /var/run/network-connection and /var/run/restart-services, starts S*, waits on /var/run/network-connection and starts N*.

The lock on /var/run/network-connection is released in /etc/hotplug.d/iface/10-netdetect.

The script then enters an unconditional loop: { If the lock on /var/run/restart-services is released, all chillispot and dnsmasq are killed, the network interfaces are reinitialized and the S45firewall und N* scripts are run again. }

hotplug daemon

The hotplug daemon (/sbin/hotplug) is a script calling each script matching /etc/hotplug.d/$1/* with $1 beeing one of {iface,net}.

Busybox

Busybox is a multicall binary implementing most posix programs for small and embedded systems. Calling busybox gives a list of all programs (modules) compiled in.

root@OpenWrt:~# busybox
BusyBox v1.1.3 (2006.11.21-19:49+0000) multi-call binary

Usage: busybox [function] [arguments]...
   or: [function] [arguments]...

        BusyBox is a multi-call binary that combines many common Unix
        utilities into a single executable.  Most people will create a
        link to busybox for each function they wish to use and BusyBox
        will act like whatever it was invoked as!

Currently defined functions:
        [, [[, arping, ash, awk, basename, bunzip2, busybox, bzcat, cat,
        chgrp, chmod, chown, chroot, clear, cp, crond, crontab, cut, date,
        dd, df, dirname, dmesg, du, echo, egrep, env, expr, false, fgrep,
        find, free, grep, gunzip, gzip, halt, head, hexdump, hostid, httpd,
        id, ifconfig, init, insmod, ipkg, kill, killall, killall5, klogd,
        length, ln, lock, logger, logread, ls, lsmod, md5sum, mesg, mkdir,
        mkfifo, mktemp, more, mount, mv, nc, netmsg, netstat, nslookup,
        passwd, pidof, ping, ping6, pivot_root, poweroff, printf, ps,
        pwd, rdate, reboot, reset, rm, rmdir, rmmod, route, sed, seq,
        sh, sleep, sort, strings, switch_root, sync, sysctl, syslogd,
        tail, tar, tee, telnet, telnetd, test, time, top, touch, tr, traceroute,
        true, udhcpc, umount, uname, uniq, uptime, vconfig, vi, watchdog,
        wc, wget, which, xargs, yes, zcat
        

Logging

Logging is done via the syslogd implemented in busybox. It is configured to use a circular buffer instead of a file on the disk to save any messages. You can access the log via logread.

IPTables hell

Have you ever seen pf? Well...

WAN_HOOK

This drops all packets with the destination address of your internal lan. Used to shield it from FON_AP users. Note that ath2 is the interface used to access the internal network. Its IP range is 192.168.0.0/24.

root@OpenWrt:~# iptables -L WAN_HOOK -v
Chain WAN_HOOK (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  any    ath2    anywhere             192.168.0.0/24
          

NET_ACCESS

Each packet arriving on the "FON_AP" access point (the interface is tun0) is routed to the chain NET_ACCESS.

root@OpenWrt:~# iptables -L NET_ACCESS -v
Chain NET_ACCESS (3 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:3990 
   28  1946 ACCEPT     udp  --  any    any     anywhere             anywhere            udp dpt:53 
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:53 
    0     0 WAN_HOOK   all  --  any    any     anywhere             anywhere            
    0     0 ACCEPT     all  --  any    ath2    anywhere             anywhere            
    0     0 ACCEPT     all  --  ath2   any     anywhere             anywhere            
    0     0 ACCEPT     all  --  any    ath1    anywhere             anywhere            
    0     0 ACCEPT     all  --  ath1   any     anywhere             anywhere            
    0     0 ACCEPT     all  --  any    eth0    anywhere             anywhere            
    0     0 ACCEPT     all  --  eth0   any     anywhere             anywhere            
    0     0 DROP       all  --  any    any     anywhere             anywhere
          

My modifications

Starting dropbear sshd at bootup

This is described in #3:

root@OpenWrt:~# mv /etc/init.d/dropbear /etc/init.d/S50dropbear

Prevent Fon from executing code on your box

as described in #2

root@OpenWrt:~# sed -i -e 's/\. \/tmp\/\.thinclient.sh/#\. \/tmp\/\.thinclient.sh/' /bin/thinclient
root@OpenWrt:~# echo 'mv /tmp/.thinclient.sh /tmp/thinclient-$(date "+%Y%m%d-%H%M")' >> /bin/thinclient

Don't phone home that often

The Fonera is configured to phone home every hour, and saving 33 bytes (which is the size of the default nothing to do message) every hour needs lots of space. So lets slow it down a little.

root@OpenWrt:~# echo '0 0 * * * /bin/thinclient cron' > /etc/crontabs/root

How not to write software

It is amazing, how low the quality of the code inside all those bourne shell scripts is. Just take a look at the following snippets:

/sbin/ifdown
      case "$1" in                                                                                                         
              lan) (                                                                                                       
                      killall -KILL dnsmasq                                                                                
                      killall -KILL hostapd                                                                                
                      ifconfig ath1 down                                                                                   
                      wlanconfig ath1 destroy                                                                              
              ) > /dev/null 2>/dev/null ;;
      

Yeah right. Just to redirect the output of those commands to /dev/null, this makes debugging a breeze. No ordinary user sees the output anyway. And note how all those interfaces are hardcoded even if they have a file called /tmp/network-config, which is sourced by most scripts. I for one hope, that there's not going to be a Fonera2 with more nics...

Resources

  1. http://wiki.openwrt.org/OpenWrtDocs/Hardware/Fon/Fonera
  2. http://stefans.datenbruch.de/lafonera/
  3. http://jauzsi.hu/2006/10/13/inside-of-the-fonera

Justus Winter
Last modified: Mon Mar 26 23:44:24 CEST 2007