Local only DSL

Update: Debian/Ubuntu version

I've finally jumped onto the local only DSL bandwagon. If you haven't done it yet, it's a great way to save some bucks. The idea is that you get a local only account like this, which costs a fraction per GiB compared to normal account. Then you get your router to connect to both simultaneously, and route intelligently between them.

Most ADSL routers won't let you connect 2 concurrent ADSL connections on the same ATM circuit. The solution is to use a separate modem and router. I'm using a basic Billion modem, in bridged mode, and a WRT54GL, running OpenWRT/kamikaze, as the router.

OpenWRT doesn't support 2 PPPoE connections out of the box, but I've found the problems, and got a few changes committed upstream, that solve them:

The firewall (/etc/init.d/firewall) needs to be modified with "WAN=ppp+" somewhere near the top, so that it masquerades all the ppp connections. This was a hack, apparently the firewall is being re-written soon.

There is also a bug that resets existing PPPoE connections on a ethernet interface when you fire up a new connection. This will apparently be fixed by the future interface aliasing support. For now, I just hacked around it in /lib/network/

prepare_interface() {
        local iface="$1"
        local config="$2"

        #SR: We don't want to reset any pppoe connections
        config_get proto "$config" proto
        [ "$proto" = "pppoe" ] && return 0

and /sbin/ifdown:

config_get ifname "$cfg" ifname
config_get device "$cfg" device

[ ."${proto%oe}" == ."ppp" ] && device=
[ ."$device" != ."$ifname" ] || device=
for dev in $ifname $device; do
        ifconfig "$dev" down >/dev/null 2>/dev/null

I got my local routes list from cocooncrash's site (he gets them from, aggregates them, and publishes every 6 hours). OpenWRT already has a static routing configuration system, but it's very verbose. So I wrote my own, adding the new configuration option routefile. I used these hotplug scripts to set up routing and source routing, with the help of iproute2:

$ ipkg install ip

$ mkdir /etc/routes
$ wget -O /etc/routes/zaroutes

You'll probably want to update that route file regularly. I don't run cron on my WRT54GL, so I do it manually. Up to you.


# ...local interfaces...

#### WAN configuration
config interface    wan
        option ifname   "eth0.1"
        option proto    pppoe
        option username ""
        option password "xxxxxx"
        option routefile "/etc/routes/exceptions"
        option defaultroute 1

config interface    localdsl
        option ifname   "eth0.1"
        option proto    pppoe
        option username ""
        option password "xxxxxx"
        option routefile "/etc/routes/zaroutes"
        option defaultroute 0


# reserved values
255     local
254     main
253     default
0       unspec
# local
1   wan
2   localdsl


case "$ACTION" in
    . /etc/
    include /lib/network
    config_get routefile "$INTERFACE" routefile

    # Does this interface have custom routes?
    if [ -e "$routefile" ]; then

      # Add routes for this interface
      cat "$routefile" | while read route; do
        ip route add "$route" dev "$DEVICE"

      # Set up source routing
      peer=`ip addr show dev $DEVICE | sed -n '/inet/ s#.* peer \([0-9.]*\)/.*#\1# p'`
      address=`ip addr show dev $DEVICE | sed -n '/inet/ s/.* inet \([0-9.]*\) .*/\1/ p'`

      ip route add "$peer" dev "$DEVICE" src "$address" table "$INTERFACE"
      ip route add default via "$peer" table "$INTERFACE"
      ip rule add from "$address" table "$INTERFACE"

    # Make sure this interface is present in all the custom routing tables:
    route=`ip route show dev "$DEVICE" | awk '/scope link  src/ {print $1}'`
    awk '/^[0-9]/ {if ($1 > 0 && $1 < 250) print $2}' /etc/iproute2/rt_tables | while read table; do
      ip route add "$route" dev "$DEVICE" table "$table"


case "$ACTION" in
    . /etc/
    include /lib/network

    # If this interface doesn't have a link local route, we don't need to bother
    route=`ip route show dev "$INTERFACE" | awk '/scope link  src/ {print $1}'`
    [ ."$route" = ."" ] && return 0

    # Add this interface's route to all custom routing tables
    awk '/^[0-9]/ {if ($1 > 0 && $1 < 250) print $2}' /etc/iproute2/rt_tables | while read table; do
      ip route add "$route" dev "$INTERFACE" table "$table"

Now, lastly, it won't bring up both interfaces by default. That will be fixed by aliasing in the future, but for now:


ifup wan
ifup localdsl
$ chmod 755 /etc/init.d/network-multiwan
$ ln -s ../init.d/network-multiwan /etc/rc.d/S49network-multiwan

That's it, and it's working beautifully :-)

What is source routing, people ask? The problem is that your router now has 2 WAN IP addresses. IP1 is used for local traffic, and IP2 for international. So if somebody in ZA tries to connect to IP2, the reply (local destination) will go out of Interface 1. The ISP on the other end of Interface 1 will drop this reply, because it's not coming from IP1.

Source routing tells the router that replies must go out of the same interface that the request came in on. I'm doing it by creating separate routing tables for traffic origionating from each WAN interface.


  • If you are using 2 different ISPs (say SAIX international and IS local), you must make sure that DNS queries get routed out the right interface. SAIX won't accept queries on their servers from IS, and vice versa.
  • SAIX Web proxies, Mail servers, and News servers don't accept traffic from local accounts. (especially from another ISP)

In Portland for Ubuntu Live

Ubuntu Live kicks off tomorrow in Portland, OR, USA, back to back with OSCON.

The tale of air travel

I left London yesterday morning (after my brother accidentally woke me up an hour early), and almost didn’t make it out of Gatwick - due to terrible weather, all flights were delayed, and many cancelled. I went through the Trainee security queue, and they all ogled my laptop bag on the Xray machine (filled to the brim with interesting equipment, power supplies, and adaptors, as usual). The lad who frisked me was clearly very green, and I don’t think I could have got an unauthorised toothpick through ;-) Thankfully I wasn’t picked out for “special attention” again after that, although maybe 10% of people got taken away from the Immigration queue, in at Newark, New York. It’s quite a scary process - the queue moves very slowly, because everyone gets interviewed for 2-10 minutes. People with children get a long interview, and if you didn’t dot every I and cross every T on your forms, you get sent away, dismissively. Then, as I said, about 10% of passengers fail their interview (or are just unlucky), their papers are put in a big, zip lock bag, and the immigration official shouts for an “ESCORT!” to take them away, down the white corridor, from whence we presume they will never return… There were only 2 escorts, and they were working flat out…

Oh, btw, I’m a huge fan of the air power wiki. My laptop has a negligible battery life, and likes being tethered to the mains. Talking of which, on the 767 from London to New York, there were 110V power sockets under the seats - w00t :-)

My plane to Portland was packed, and delayed for almost 2hrs, in the Friday rush. :-( But I got there mostly on time, and crawled into my hotel bed before midnight, after, literally, a 24hr day. The hotel is dingy, but cheap & clean. And right next door to the convention centre, and a MAX tram stop.

The tale of dodgy wifi

I get free wifi from the Hotel across the street (they have an agreement with mine), but it’s dodgy as hell. It just dies without warning, and when it’s dead, it’s AP seems to cause havoc (when I try and associate with other networks, I always end up connecting to it).

Portland has a free MetroFi service, ad-supported. Which sucks - badly. The signal is mostly pretty poor (I can only get it with my laptop screen right against the window in my room), and when I’m around the town there is normally little signal. They’ve spread their APs over all 4 non-overlapping channels, polluting the spectrum. When you do have signal, the ad system means you get lots of 302 redirects, which don’t agree with my RSS reader, or me. I find myself proxying out over an SSH tunnel, for my sanity. :-( MetroFi—

Portland so far

Portland is nice enough. There is free public transport inside the city centre, it’s leafy, and the people seem friendly enough. But I haven’t really got a feel for it yet.

I poked around the Saturday market this morning, which could have been just about anywhere in the world (excepting the men selling US flags, and almost all the stalls having credit card facilities :-) ). Some nice work, and some good food (I had a spectacular omlette). I left when it started raining.

I went to see the Body Worlds 3 exhibition at the Oregon Museum of Science and Industry. Very interesting. You get a good feeling for human anatomy and muscle structure. The exhibits of tumours and healthy body parts were quite enlightening. The posed, plastinated cadavers got rather repetitive, although all well worth a close look. I found the exhibits of blood vessels only to be the most beautiful. But overall, I didn’t find it to be as mind-blowing or offensive as the media has made it out to be.

Tonight, I’m off to find some fellow Ubuntu Live’ers, unless the Jetlag gets to me first.

Lighttpd mod_rewrite

I've migrated my teeny-weenie Xen web/mail server to Debian/etch. It hasn't even been rebooted (it would be a shame to spoil the uptime :-) ):

$ uprecords
     #               Uptime | System                                     Boot up
->   1   198 days, 06:16:44 | Linux      Thu Oct 12 10:12:51 2006
     2    99 days, 19:25:00 | Linux 2.6.12-xenU         Sun Oct  9 03:58:58 2005

It runs Lighttpd, a small and fast little webserver, popular in the Rails world. Lighttpd with PHP-fastcgi is probably faster than apache, and uses much less RAM.

With etch, I've finally been able to get mod_rewrite to work. So my Zapiro archive has nice URLs now :-)

Lighttpd has a very nice configuration style:

    # No WWW
    $HTTP["host"] =~ "^www\.((.+\.)?rivera\.za\.net)$" {
      url.redirect = ( ".*" => "http://%1$1" )
    # Add WWW:
    $HTTP["host"] =~ "^((foobar|someclient)\.co\.za)$" {
      url.redirect = ( ".*" => "http://www.%1$0" )
    # PHP Apps:
    $HTTP["host"] =~ "^(zapiro\.rivera\.za\.net)$" {
      url.redirect = ( "^/\?/(.*)" => "http://%1/$1" )
      url.rewrite-once = ( "^/(feed)$" => "/index.php?/$1",
                           "^/([0-9]+/[0-9]+/[0-9]+)$" => "/index.php?/$1" )

It's more logical than apache, but you have to watch out for rewrite->redirect->rewrite loops. So if you change to a clean URL syntax, you can't put in rewrites from index.php?/uglurl to /uglyurl because /uglyurl rewrites back to /index.php?/uglyurl, and you get a loop :-)

More ClugPark work

Well, we’ve now got a custom theme for (by superfly, thanks!) I still want to hack planetplanet to death, but that can wait until they decide on their direction…

In the meantime, I’ve been brushing up my mediawiki hacking for the ClugPark gallery. Mediawiki is a monster! The select query looks like this:

$select = "SELECT page_namespace, page_title, old_text, img_description "
          . "FROM " . $dbr->tableName(‘page’) . " "
          . "LEFT JOIN " . $dbr->tableName(‘revision’) . " ON page_latest = rev_id "
          . "LEFT JOIN " . $dbr->tableName(‘text’) . " ON old_id = rev_text_id "
          . "LEFT JOIN " . $dbr->tableName(‘image’) . " ON page_title = img_name "
          . "INNER JOIN " . $dbr->tableName(‘categorylinks’) . " "
          . "ON page_id = cl_from AND cl_to = " . $dbr->addQuotes($catKey) . " ";
$where = " WHERE page_namespace = " . $wgContLang->getNsIndex(‘Image’) . " "
         . "ORDER BY page_title ";

Yup. Lovely stuff. Anyway, when I’m happy with the extension, I’ll post it somewhere… (Same goes for my other mediawiki extenisons)


I’ve been doing some themeing work on Clug Park, and it’s pretty much ready to go now. It could still do with some theming work, and probably some more blogs (I bet there are other blogging CLUGgers out there).

It seems that PlanetPlanet might switch to an entirely re-written version of it’s software. That shouldn’t be a problem, I think the themes are still compatible.

We’ve hacked our planet to always display 2 entries from every member. If we switch, the hack will have to be ported. Which isn’t a bad thing, I don’t want to pass the patch upstream if planetplanet is about to switch to another trunk, anyway :-)

Syndicate content