Jan 272013

I recently got my Raspberry Pi to act as a WiFi Router with shaping by using hostapd, tc, and iptables together to broadcast as an Access Point, apply shaping rules, and apply packet marking respectively.

This can be done on any device with 2 NICs but this may come in useful for anyone using the Pi as a router but doesn’t want people using all the bandwidth.

I will be going through the iptables and tc configuration in this post, but I won’t go through the hostapd setup as that was the same as part 3 of my Raspi WiFi Access point guide.

I started off with a blank slate of Raspbian Server Edition again, and I didn’t need to install any utilities as iptables and tc are installed by default.
**Note** All command are run as root. If you are not running as root, prepend sudo to all commands

Setting up tc

tc is the program that is in charge of setting up the shaping rules.

Step 1
Firstly, we will setup the default rule for the interface, which is wlan0 in this instance.

These 2 commands sets the default policy on wlan0 to shape everyone’s download speed to 64 kilobytes a second.

tc qdisc add dev wlan0 root handle 1:0 htb default 10
tc class add dev wlan0 parent 1:0 classid 1:10 htb rate 64kbps ceil 64kbps prio 0

Step 2
Next, we’ll setup another class to shape certain addresses to a higher speed.
We also need to setup a filter so that any packets marked as such go through this rule

tc class add dev wlan0 parent 1:1 classid 1:5 htb rate 256kbps ceil 256kbps prio 1
tc filter add dev wlan0 parent 1:0 prio 1 handle 5 fw flowid 1:5

Once that class is setup, we’ll need to setup iptables to mark the specific packets we want to shape as such.

Setting up iptables

Step 1
Firstly, we’ll create the mangle table that we need. I’ve used a custom chain in the mangle table in this snippet
The below code creates the new chains of shaper-in and shaper-out, and then sets up some rules for any packets coming in and out of wlan0 and eth0 to go through the new chains.

iptables -t mangle -N shaper-out
iptables -t mangle -N shaper-in

iptables -t mangle -I POSTROUTING -o wlan0 -j shaper-in
iptables -t mangle -I PREROUTING -i wlan0 -j shaper-out
iptables -t mangle -I PREROUTING -i eth0 -j shaper-in
iptables -t mangle -I POSTROUTING -o eth0 -j shaper-out

Step 2
Once that is done, we can then setup the packet marking so that any packets from the subnet gets marked with a 1, otherwise if the IP address is, they will get marked with a 5

iptables -t mangle -A shaper-out -s -j MARK --set-mark 1
iptables -t mangle -A shaper-in -d -j MARK --set-mark 1

iptables -t mangle -A shaper-out -s -j MARK --set-mark 5
iptables -t mangle -A shaper-in -d -j MARK --set-mark 5

With that done, any connections going through wlan0 should now be shaped to 64kbps unless you have the IP address of in which case you will be shaped to 256kbps

If more shaping speeds or IP addresses are required, then step 2 in the respective sections will need to be modified / added onto to give you the extra options.
I used Speedtest Mini hosted on my own webserver to test the speeds while I was shaping the connections as it provided an easy to use interface, but wget on a big file can also be used to test the speeds.

Setting up router to auto-start

If you want the shaping to start automatically, put all the commands into 1 or 2 shell script files in /etc/network/if-up.d and they will be run automatically.
e.g. /etc/network/if-up.d/router and /etc/network/if-up.d/shaper
make sure they have both been chmodded to be executable by running this on both files

chmod +x /etc/network/if-up.d/router

Sources :
tc: Linux HTTP Outgoing Traffic Shaping (Port 80 Traffic Shaping)


  11 Responses to “How To : Turn the Raspberry Pi Into a Shaping WiFi Router”

  1. […] kann den Raspberry Pi nun zur Analyse von Netzwerktraffic nutzen, mit iptables auch traffic-shaping betreiben oder sonstiges, aber er bietet sich auch prima als Angriffspunkt für Man-in-the-Middle […]

  2. Very nice!. I’m new to IPtablets. Does it work only with IP addresses or can it also work at the level of MAC addresses?

    Basically what I want to do is make a RasPi work as an AP, like yours, but with the following rule
    “clients with MAC ADDRESS on this list” (say list.txt which contains two mac addresses) are UNLIMITED in at what speed they can transfer, while EVERYONE ELSE is limited to, say 1Mbit…


    Congrats for your work and thanks for sharing it. TIA for your time and any replies.

    Best regards

  3. Can I let other servers (e.g. openvpn) run on the Pi while this is running and is the traffic from the Pi also being shaped?

    • You can definitely run other servers on the Pi.
      You can configure shaping to your needs by using marking in iptables and tc classes.
      e.g. iptables can mark any packets from IP address as no shaping, and everything else as 64kbps

  4. Hello,

    I know, that this is a very old post, but i have problems with using this script.

    I’m not using a RPi, but a Debian distribution.

    Eth0 is connected to my internal Network.
    Eth1 is connected to the external(Internet) Network.

    So I’ve followed your instruction and replaced wlan0 with eth0 and eth0 with eth1. The traffic shaping works for the download, but somehow not for the upload.

    What could be wrong?

    Thanks in advance.


    • You might need to add rules to both interfaces and not just eth0. It’s been a while since I’ve played with the shaping stuff so not too sure on that one.

  5. Hello,

    Thanks first.

    How can i setup different rule for upload speed?


  6. Hello !

    Thanks a lot for the tutorial:

    One question, on step 2:

    tc class add dev wlan0 parent 1:1 classid 1:5 htb rate 256kbps ceil 256kbps prio 1

    It is not supposed to be:

    tc class add dev wlan0 parent 1:0 classid 1:5 htb rate 256kbps ceil 256kbps prio 1

    Because it refers to the root parent 0 ?

    Thanks !

Leave a Reply to SirLagz Cancel reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>



This site uses Akismet to reduce spam. Learn how your comment data is processed.