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 10.0.0.0/24 subnet gets marked with a 1, otherwise if the IP address is 10.0.0.5, they will get marked with a 5
iptables -t mangle -A shaper-out -s 10.0.0.0/24 -j MARK --set-mark 1
iptables -t mangle -A shaper-in -d 10.0.0.0/24 -j MARK --set-mark 1
iptables -t mangle -A shaper-out -s 10.0.0.5 -j MARK --set-mark 5
iptables -t mangle -A shaper-in -d 10.0.0.5 -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 10.0.0.5 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)
[…] 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 […]
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…
Doable?
Congrats for your work and thanks for sharing it. TIA for your time and any replies.
Best regards
FC
It can work with IP addresses and MAC addresses both, so what you want to do is very doable.
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 192.168.30.30 as no shaping, and everything else as 64kbps
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.
The
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.
Hello,
Thanks first.
How can i setup different rule for upload speed?
Thanks
Upload speed per user or for the whole connection?
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 !
Honestly, I don’t remember. Try it out and let me know!