使用 TC 限制/限制每個使用者的 OpenVPN 頻寬
我有一組使用者通過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 使用者沒有自己的介面,所有流量都通過主介面
tun0
和tun1
介面。所以我在這裡有兩個問題。
tun0
1) 由於某種原因(將介面名稱設置為或) ,上面的腳本似乎不適用於 OpenVPN,tun1
我的測試使用者仍然可以以網際網路的最大速度下載。2)我需要能夠過濾每個源IP,並
up
在它們連接時將其添加到OpenVPN的腳本中,同時維護其他過濾器/類並在down
腳本中刪除該過濾器/類,再次不影響其他連接使用者的限制(即我不能在每次使用者連接時簡單地刪除 tun0 的 qdisc)。搜尋時我能找到的唯一幫助是
“您可以為此使用 TC”
但沒有解釋如何…
謝謝!
我曾經做過類似的事情來單獨為每個使用者的連接設置防火牆。我已經使用
learn-address
OpenVPN 中的腳本實現了它,該腳本在使用者連接或斷開連接時呼叫。我已經根據您的案例對其進行了調整。該腳本如下所示:
#!/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 到使用者)工作正常,但限制上傳不是很精確,據我了解這有點正常。也許您可以找到更好的方法並將其集成到腳本中。