| Title: Bandwidth limiting on OpenBSD 6.8 | |
| Author: Solène | |
| Date: 07 February 2021 | |
| Tags: openbsd unix network | |
| Description: | |
| This is a February 2021 update of a text originally published in April | |
| 2017. | |
| ## Introduction | |
| I will explain how to limit bandwidth on OpenBSD using its firewall PF | |
| (Packet Filter) queuing capability. It is a very powerful feature but | |
| it may be hard to understand at first. What is very important to | |
| understand is that it's technically not possible to limit the bandwidth | |
| of the whole system, because once data is getting on your network | |
| interface, it's already there and got by your router, what is possible | |
| is to limit the upload rate to cap the download rate. | |
| OpenBSD pf.conf man page about queuing | |
| ## Prerequisites | |
| My home internet access allows me to download at 1600 kB/s and upload | |
| at 95 kB/s. An easy way to limit bandwidth is to calculate a percent | |
| of your upload, that should apply that ratio to your download speed as | |
| well (this may not be very precise and may require tweaks). | |
| PF syntax requires bandwidth to be defined as kilo-bits (kb) and not | |
| kilo-bytes (kB), multiplying by 8 allow to switch from kB to kb. | |
| ## Configuration | |
| Edit the file /etc/pf.conf as root and add the following before any | |
| pass/match/drop rules, in the example my main interface is em0. | |
| ```OpenBSD packet filter configuration file sample | |
| # we define a main queue (requirement) | |
| queue main on em0 bandwidth 1G | |
| # set a queue for everything | |
| queue normal parent main bandwidth 200K max 200K default | |
| ``` | |
| And reload with `pfctl -f /etc/pf.conf` as root. You can monitor the | |
| queue working with `systat queue` | |
| ```Output of the command systat queue | |
| QUEUE BW/FL SCH PKTS BYTES DROP_P DROP_B QLEN | |
| main on em0 1000M fifo 0 0 0 0 0 | |
| normal 1000M fifo 535424 36032467 0 0 60 | |
| ``` | |
| ## More control (per user / protocol) | |
| This is only a global queuing rule that will apply to everything on the | |
| system. This can be greatly extended for specific need. For example, | |
| I use the program "oasis" which is a daemon for a peer to peer social | |
| network, sometimes it has upload burst because someone is syncing | |
| against my computer, I use the following rule to limit the upload | |
| bandwidth of this user. | |
| ```OpenBSD packet filter configuration file sample | |
| # within the queue rules | |
| queue oasis parent main bandwidth 150K max 150K | |
| # in your match rules | |
| match on egress proto tcp from any to any user oasis set queue oasis | |
| ``` | |
| Instead of a user, the rule could match a "to" address, I used to have | |
| such rules when I wanted to limit my upload bandwidth for uploading | |
| videos through peertube web interface. |