Ubuntu

使用 TC 限制/限制每個使用者的 OpenVPN 頻寬

  • January 31, 2019

我有一組使用者通過OpenVPN TCP 和 UDP(2 個服務)連接到我的伺服器。這兩項服務正在執行,tun0並且tun1

我希望能夠使用 TC 命令將每個使用者的頻寬限制為向上 5mb/s 和向下 5mb/s。

這很容易用 PPTP 實現,因為每個使用者都有自己的界面,所以我可以為該界面創建一個新的類/過濾器,將其限制為我想要的速度限制,如下所示:

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

據我所知,OpenVPN 使用者沒有自己的介面,所有流量都通過主介面tun0tun1介面。

所以我在這裡有兩個問題。

tun01) 由於某種原因(將介面名稱設置為或) ,上面的腳本似乎不適用於 OpenVPN,tun1我的測試使用者仍然可以以網際網路的最大速度下載。

2)我需要能夠過濾每個源IP,並up在它們連接時將其添加到OpenVPN的腳本中,同時維護其他過濾器/類並在down腳本中刪除該過濾器/類,再次不影響其他連接使用者的限制(即我不能在每次使用者連接時簡單地刪除 tun0 的 qdisc)。

搜尋時我能找到的唯一幫助是

“您可以為此使用 TC”

但沒有解釋如何…

謝謝!

我曾經做過類似的事情來單獨為每個使用者的連接設置防火牆。我已經使用learn-addressOpenVPN 中的腳本實現了它,該腳本在使用者連接或斷開連接時呼叫。我已經根據您的案例對其進行了調整。

該腳本如下所示:

#!/bin/bash

statedir=/tmp/

function bwlimit-enable() {
   ip=$1
   user=$2

   # Disable if already enabled.
   bwlimit-disable $ip

   # Find unique classid.
   if [ -f $statedir/$ip.classid ]; then
       # Reuse this IP's classid
       classid=`cat $statedir/$ip.classid`
   else
       if [ -f $statedir/last_classid ]; then
           classid=`cat $statedir/last_classid`
           classid=$((classid+1))
       else
           classid=1
       fi
       echo $classid > $statedir/last_classid
   fi

   # Find this user's bandwidth limit
   # downrate: from VPN server to the client
   # uprate: from client to the VPN server
   if [ "$user" == "myuser" ]; then
       downrate=10mbit
       uprate=10mbit
   elif [ "$user" == "anotheruser"]; then
       downrate=2mbit
       uprate=2mbit
   else
       downrate=5mbit
       uprate=5mbit
   fi

   # Limit traffic from VPN server to client
   tc class add dev $dev parent 1: classid 1:$classid htb rate $downrate
   tc filter add dev $dev protocol all parent 1:0 prio 1 u32 match ip dst $ip/32 flowid 1:$classid

   # Limit traffic from client to VPN server
   tc filter add dev $dev parent ffff: protocol all prio 1 u32 match ip src $ip/32 police rate $uprate burst 80k drop flowid :$classid

   # Store classid and dev for further use.
   echo $classid > $statedir/$ip.classid
   echo $dev > $statedir/$ip.dev
}

function bwlimit-disable() {
   ip=$1

   if [ ! -f $statedir/$ip.classid ]; then
       return
   fi
   if [ ! -f $statedir/$ip.dev ]; then
       return
   fi

   classid=`cat $statedir/$ip.classid`
   dev=`cat $statedir/$ip.dev`

   tc filter del dev $dev protocol all parent 1:0 prio 1 u32 match ip dst $ip/32
   tc class del dev $dev classid 1:$classid

   tc filter del dev $dev parent ffff: protocol all prio 1 u32 match ip src $ip/32

   # Remove .dev but keep .classid so it can be reused.
   rm $statedir/$ip.dev
}

# Make sure queueing discipline is enabled.
tc qdisc add dev $dev root handle 1: htb 2>/dev/null || /bin/true
tc qdisc add dev $dev handle ffff: ingress 2>/dev/null || /bin/true

case "$1" in
   add|update)
       bwlimit-enable $2 $3
       ;;
   delete)
       bwlimit-disable $2
       ;;
   *)
       echo "$0: unknown operation [$1]" >&2
       exit 1
       ;;
esac

exit 0

該腳本需要安裝在您的 OpenVPN 的 server.conf 中,如下所示:

learn-address <path-to-script>
script-security 3

script-security 3是必需的,因此 OpenVPN 實際上會呼叫該腳本。

當使用者連接時,腳本被稱為<path-to-script> add <ip> <username>,而且網路介面被放置在環境變數中$dev(例如tun0)。

該腳本為排隊規則配置網路介面,並為其附加必要的過濾器和類。它會跟踪為其安裝過濾器和類的 IP,以便以後在使用者斷開連接時將其刪除。該狀態保存在目錄/tmp中,這可能應該更改。

請注意,我不確定我是否 100% 正確完成了交通控制。下載流量整形(即從 OpenVPN 到使用者)工作正常,但限制上傳不是很精確,據我了解這有點正常。也許您可以找到更好的方法並將其集成到腳本中。

引用自:https://serverfault.com/questions/701194