userland traffic shaping
A short program to demonstrate network filtering with Lua. Although the kernel provides pf filtering and some bandwidth shaping facilities, they don’t cover every scenario. For example, consider the case where our server is connected to a network port where we pay for some amount of bandwidth, but have burstable speeds much faster than that. Commonly seen as 95th percentile billing. As long as we’re under our five minute quota, we want to pass traffic full speed, but as we approach that mark, we want to start clamping down. The pf.conf burst queueing rules can’t quite handle this situation.
For more flexibility, we can pass all our network traffic through userland using tun and have an arbitrary program analyze and shape it. This setup requires a whole mess of virtual interfaces to be configured with ifconfig, but it’s really not so bad. We want to pass ethernet frames, so we use the link0 flag.
ifconfig tun0 create link0 ifconfig bridge0 create add em0 add tun0 ifconfig tun1 create link0 ifconfig vether0 create ifconfig bridge1 create add vether0 add tun1
Now we have a vether interface connected, via bridges and tuns, to the network. We configure this interface with our IP (run dhclient if you like), and it effectively replaces em0 as the primary interface. This is an endpoint configuration; vether can be replaced by a physical interface for a router. All that’s missing is a program to pass traffic between the two tun interfaces.
Here’s a short Lua (luajit) program. It reads from the two tun interfaces and passes packets between them as they arrive. As the amount of traffic passed approaches our five minute quota, it starts probabilistically dropping packets. As written it lets you use 75% of your quota at full speed before rather sharply curtailing it. (As a bonus, it will occasionally print a frequency count of each byte to demonstrate other uses.)
See also trickle.