I have a group of users connecting to my server via OpenVPN TCP and UDP (2 services). The two services are operating on tun0
and tun1
I'd like to be able to limit each user's bandwidth to say 5mb/s up and 5mb/s down using the TC command.
This was fairly easy to implement with PPTP as each user got their own interface, so I could just create a new class/filter for that interface limiting it to my desired speed limit using something like this:
IF=<taken from up script, i.e. ppp1>
tc qdisc del dev $IF root
tc qdisc add dev $IF root handle 1: cbq avpkt 1000 bandwidth 100mbit
tc class add dev $IF parent 1: classid 1:1 cbq rate 10mbit allot 1500 prio 5 bounded isolated
tc filter add dev $IF parent 1: protocol ip prio 16 u32 match ip src 0.0.0.0/0 flowid 1:1
tc qdisc add dev $IF parent 1:1 sfq perturb 10
As far as I can tell with OpenVPN users do not get their own interface, all traffic goes through the main tun0
and tun1
interfaces.
So I have 2 problems here.
1) The script above does not seem to work with OpenVPN for some reason (setting the interface name to tun0
or tun1
) my test user can still download at their internet's max speed.
2) I need to be able to filter this per source IP and add it in OpenVPN's up
script when they connect while maintaining the other filter/classes and remove that filter/class in the down
script, again without affecting the other connected user's limits (i.e. I can't simply delete the qdisc for tun0 each time a user connects).
The only help I can find when searching is
"you can use TC for that"
but no explanation of how…
thanks!
Best Answer
I once did something like this for individually firewalling each user's connection. I have implemented it using the
learn-address
script in OpenVPN which is called when a user connects or disconnects. I have adapted it for your use case.The script looks as follows:
The script needs to be installed in your OpenVPN's server.conf as follows:
script-security 3
is necessary so OpenVPN actually calls the script.When a user connects, the script is called as
<path-to-script> add <ip> <username>
, furthermore the network interface is placed in the environment variable$dev
(e.g.tun0
).The script configures the network interface for queueing discipline and attaches the necessary filters and classes to it. It keeps track of the IPs for which it installed filters and classes so it can later remove them if the user disconnects. That state is kept in the directory
/tmp
, this should probably be changed.Note that I'm not sure I have gotten the traffic control stuff 100% right. Download traffic shaping (i.e. from OpenVPN to the user) works fine, but limiting the upload isn't very precise, which is somewhat normal from what I have understood. Maybe you can find a better way and integrate it in the script.