dd-wrt ip routing

I have a Linksys router and, naturally, I’ve got custom firmware on it.

I went for DD-WRT quite some time ago and I’ve gotten used to it. One of the best features is the ability to manage everything via SSH.

However, the biggest hurdle with doing that is getting to grips with the limitations of it’s shell (which is ash — not bash). Things that you would take for granted in bash, such as arrays, are not necessarily present in ash.

Function declaration is much stricter as well — requiring the () to be immediately after the function name with no spacing. You also can’t use the (albeit unnecessary) “function” declaration either.

Anyway — I had a need to route multiple external IP addresses to an internal machine and rather than doing the iptables commands every time, I thought I would write a script to do it for me.

#!/bin/sh

## Usage: __port_route__ [IPADDRESS] [EXTERNAL_PORT->INTERNAL_PORT : EXTERNAL_PORT->INTERNAL_PORT] ##
__port_route__() {
        ipaddress="${1}"
        ports="${2}"
        oldIFS=${IFS}
        IFS=" : "
        for route in ${ports}; do
                IFS="->"
                local i=0
                for port in ${route}; do
                        if [ ${i} == 0 ]; then
                                local extport=${port}
                        else
                                local intport=${port}
                        fi
                local i=1
                done
                iptables -t nat -I PREROUTING -p tcp --dport ${extport} -j DNAT --to ${ipaddress}:${intport}
                iptables -I FORWARD -p tcp -d ${ipaddress} --dport ${extport} -j ACCEPT
                echo "External port ${extport} routed to ${ipaddress}:${intport}"
        done
        IFS=${oldIFS}
}

## Fair warning -- port routing *MUST* be enclosed in quotes, preferably single quotes. otherwise you'll end up creating files. ##
__port_route__ ${1} ${2}

Usage:

portroute 255.255.255.255 '80->80 : 22->22 : 143->143'

I had to go round the houses to get the, potentially, different external and internal ports in as different variables so I could use them all in one go — however, I think considering the restrictions that the result is fairly clean.

Also, the ports and IP address mentioned in the script are not the ones I had used (they are all blocked again now anyway).

As usual, I’m not responsible for what you do with this script or if it breaks anything.

Imported from 2013/05/13

Import Note: I actually changed my router a few months ago, and I no longer use DD-WRT, mainly because the speed of a/b/g wasn’t fast enough to match my actual internet speed, and I have n capable laptops and phone now.

Instead, I’m using a Turris Omnia which is, frankly, fucking amazing. I’ll do an actual post on it at some point in the future.