Linuxで受信および送信トラフィックを制限する

この記事では、Linuxで着信および発信トラフィックを制限するシステムをどのように構築したかを説明します。
トラフィックアカウンティングと同様に、ネットワークの帯域幅を制限することは非常に重要なタスクですが、毎年最初はますますバックグラウンドに移行していますが、トラフィックのシェーピングは各システム/ネットワーク管理者にとって必要なタスクのままです。

トラフィックを制限する方法は何ですか?

この質問に答えるには、このトラフィックを制限する理由を決定する必要があります。
Ubuntuを実行しているゲートウェイを介してインターネットにアクセスする約50のジョブのネットワークに基づき、一部のユーザーはSMBプロトコルを使用してこのサーバーのローカルリソースを使用します。
私の目標は、ユーザー間で帯域幅を公平に共有して、インターネットへのデータ転送速度を制限することです。

私のタスクに基づいて、次の方法を使用して帯域幅を制限できます。
1. Squidプロキシを使用した制限。
この方法では、帯域幅を柔軟に制限する機能を使用して、すべてのwww、ftpユーザートラフィックを非常に柔軟に制御できます。
2. iproute2からのトラフィック制御を使用します。
前の方法のように、トラフィックを制限する非常に柔軟で最適な方法ですが、WWWトラフィックの制御は提供しません。
3.もちろん、iptablesに-m limitモジュールを使用して速度を制限することは可能ですが、これは受け入れられないと考えています。

一般的に、iproute2パッケージを使用してトラフィックを制限する方法に焦点を合わせることにしました。

何、どこで、どのように?

すでに述べたように、私はサーバーを使用しています:OS Ubuntu 10.04、カーネル2.6.32-30。 サーバーには3つのインターフェースがあります:eth0-内部ネットワーク、eth1-プロバイダー1、eth2-プロバイダー2。

目的:いくつかの条件に基づいて、クラスごとのトラフィックに優先順位を付けて、ユーザーの送受信トラフィックの速度を制限します。 ローカルトラフィックを制限しないでください。

理論のビット

ユーザーがyoutube.comとの接続を確立し、一部のビデオをHD品質で視聴している状況を想像してください。 ほとんどのトラフィックはサーバーから、この場合はyoutube.comからユーザーに送られます。 すべてのトラフィックがゲートウェイを通過することを考慮すると、内部ネットワークインターフェイスにトラフィックシェーパーをインストールすることにより、このトラフィックの伝送速度に影響を与えることができます。
ユーザーが休暇中に5000 x 3500ピクセルの解像度で300枚の写真で構成される写真レポートをオンライン写真ストレージサービスにアップロードする場合も、同様の状況が発生します。

当然、トラフィック制限システムが存在しない場合、このユーザーはチャネル全体を占有し、残りのユーザーにはインターネットでの通常の作業速度が提供されません。 ただし、サーバーの外部インターフェイスでユーザーがデータを送信する速度を制限することはできません。 NATはユーザーがインターネットにアクセスするために使用されます。アドレス変換後にトラフィックシェーピングが実行されると、サーバーの外部インターフェイスには内部ネットワークアドレスを持つパケットがなくなります。

クライアントからの発信トラフィックを制限する問題を解決するために、IFBデバイスを使用して、クライアントからのすべての発信トラフィックをリダイレクトしました。

トラフィック管理理論では、発信トラフィックのみを制限できます。 したがって、内部ネットワークのユーザーに向けられたトラフィックは、内部インターフェイスeth0に対して発信され、内部ネットワークのユーザーから送信されたトラフィックは、外部インターフェイスeth1に対して発信されます。

前述に基づいて、内部ネットワークインターフェイスでユーザーに着信するトラフィックをeth0に制限し、ユーザーからifb0仮想インターフェイスに着信するトラフィックを制限しました。

そのため、ユーザーがゲートウェイ上の帯域幅全体を占有して、大量のデータをダウンロードするために、sshを通常どおり使用できるようにし、pingが動作するように、トラフィックの優先順位付けを使用しました。

次のトラフィックを優先しました。
  1. icmp
  2. udp、ssh
  3. tcpスポーツ80
  4. 未分類のトラフィックを休ませる

パラメータが低いほど、トラフィックの優先度が高くなります。

分野、クラス、フィルター

すでに述べたように、ユーザーへの着信トラフィックはeth0インターフェースで制限され、ユーザーからの発信トラフィックはifb0仮想インターフェースで制限されます。

ifb0インターフェースを初期化するには、最初にインターフェース制御モジュールをロードする必要があります。
/sbin/modprobe ifb
モジュールを正常にロードした後、インターフェースを有効にする必要があります。
/sbin/ip link set dev ifb0 up
次に、インターフェースが解除された後、ユーザーからのすべての発信トラフィックをこのインターフェースにリダイレクトする必要があります。
/sbin/tc qdisc add dev eth0 ingress
/sbin/tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0

これで、eth0インターフェースでユーザーに着信するトラフィックとifb0インターフェースで発信するトラフィックのクラスとフィルターの作成を安全に開始できます。

次の原則は、トラフィックを制限するために使用されます。
  1. いわゆるルートキューハンドラーがインターフェイス上に作成されます
  2. この分野には、このクラスに分類されるデータの最大スループットに関する情報を含むクラスが添付されています。
  3. 特定のパラメーターを使用して、各パッケージを特定のクラスに割り当てるフィルターが追加されます。

クラスはネストできます。 つまり、クラス1:が1メガビットの最大帯域幅を記述する場合、サブクラスであるクラス1:1は、親の速度制限を超えることはできません。

ユーザーへの着信トラフィックを制限する

すべてのトラフィック操作は、eth0インターフェイスで実行されます。

まず、インターフェイス上にルートキューハンドラーを作成します。
/sbin/tc qdisc add dev eth0 root handle 1: htb default 900

したがって、ルートキューハンドラーをeth0インターフェイスにアタッチし、それに番号1を割り当て、すべての未分類トラフィックをクラス900に送信するHTBスケジューラーの使用を示しました。

次に、インターフェイス速度に等しいチャネル幅を持つ1対1の子クラスを作成します。
/sbin/tc class add dev eth0 parent 1: classid 1:1 htb rate 100Mbit burst 15k
後続のすべてのクラスは、作成したクラスのサブクラスになります。 これにより、データフローレートのより正確な優先順位付けと処理が可能になります。

ローカルトラフィック用のクラスを作成してみましょう。宛先アドレスまたは送信元アドレスはサーバーの内部アドレスになります。 これは、SSH、SMB、FTP、WWWなどのサーバーリソースを使用するのに便利です。 クラスによって記述される速度は50Mビットですが、親クラスの流量が100Mビット以上の場合、最大データ転送速度として80Mビットを使用できます。
/sbin/tc class add dev eth0 parent 1:1 classid 1:10 htb rate 50Mbit ceil 80Mbit burst 15k

次に、プロバイダーが提供する帯域幅と同じ速度のクラスを作成します。 私の場合、15Mbitです。
/sbin/tc class add dev eth0 parent 1:1 classid 1:100 htb rate 15Mbit burst 15k

プロバイダーが高速(18Mビットなど)を提供している場合でも、シェーパーのこの速度を1〜2メガビット下げることで、「より緩やかな」トラフィック制限を実現できます。
次に、以前に作成されたクラスのいずれにも該当しないすべてのデータパケットが送信されるクラスを作成します。
/sbin/tc class add dev eth0 parent 1:1 classid 1:900 htb rate 56Kbit ceil 128Kbit

ユーザーごとに、帯域幅が割り当てられた個別のサブクラスを作成し、このクラスのサブクラスを作成して、トラフィックに優先順位を付けます。
/sbin/tc class add dev eth0 parent 1:100 classid 1:101 htb rate 4Mbit ceil 6Mbit

このコマンドを使用して、番号1:101のクラスの作成をポイントしました。これは、番号1:100のクラスのサブクラスであり、クラスの帯域幅を4Mビットで示し、親クラスからの帯域幅が無料の場合、6Mビットの速度でクラスを最大で通過できるようにします。

次に、トラフィックに優先順位を付けるためのサブクラスを作成します。
# PRIO 1 -> icmp traffic -
/sbin/tc class add dev eth0 parent 1:101 classid 1:102 htb rate 33kbit ceil 6Mbit prio 1
# PRIO 2 -> udp, ssh
/sbin/tc class add dev eth0 parent 1:101 classid 1:103 htb rate 33kbit ceil 6Mbit prio 2
# PRIO 3 -> tcp sport 80 – WWW
/sbin/tc class add dev eth0 parent 1:101 classid 1:104 htb rate 33kbit ceil 6Mbit prio 3
# PRIO 4 -> unclassified traffic – , ,
/sbin/tc class add dev eth0 parent 1:101 classid 1:105 htb rate 33kbit ceil 6Mbit prio 4


クラスを作成したら、特定の基準に従ってトラフィックを分類するフィルターを作成します。

トラフィックを分類するにはいくつかの方法があります。
最も便利なのはu32分類子です 。これにより、宛先または送信者のアドレス、使用されているプロトコル、ポート番号などに基づいてパケットを分類でき、iptablesラベルに基づいた分類子を使用できます。 後者を使用するには、いくつかの条件に基づいて、まずPREROUTINGチェーン内のiptablesでパケットをマークし、次にtcを使用して、対応するラベルを持つパケットを目的のクラスに転送する必要があります。

u32分類器を使用することを好みました。

icmpトラフィックに最も低い優先度を割り当て、クラス1に送信します:102
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.10.78 \
match ip protocol 1 0xff flowid 1:102


UDPおよびSSHトラフィックはクラス1に送信されます:103
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dst 192.168.10.78 \
match ip protocol 17 0xff flowid 1:103
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dst 192.168.10.78 \
match ip protocol 6 0xff match ip sport 22 0xffff flowid 1:103


TCPポート80からのWWWトラフィックはクラス1に送信されます:104
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip dst 192.168.10.78 \
match ip protocol 6 0xff match ip sport 80 0xffff flowid 1:104


どの条件にも一致しないトラフィックはクラス1に送信されます:105
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 4 u32 match ip dst 192.168.10.78 flowid 1:105

優先順位付けは、トラフィックの優先度に応じて、各クラスに親クラスから最大帯域幅を借りる可能性がある最小帯域幅が割り当てられるという原則に基づいて動作します。したがって、tcpポート80からのWWWトラフィックでクラスが詰まる場合、icmpパケットを渡すときにWWWトラフィックよりも低い優先度の場合、優先度が与えられると順番にスキップされます。

発信トラフィックを制限する

ユーザーからのトラフィックを制限するには、着信トラフィックと同じアクションを実行します。ifb0仮想インターフェイスのみが使用されます。 次のトラフィックの宛先も変更する必要があります。dst192.168.10.78の代わりに、src 192.168.10.78をそれぞれ指定する必要があります。

自動化とスクリプトの仕組み

まず、速度制限プロセスを自動化するには、これらの制限で制限を設定する必要があるユーザーのアドレスをリストするファイルを作成する必要があります。

 root@mixer:/etc/rc.d/shape# cat ./users #CLIENT IP DOWN CEIL UP CEIL PROVIDER ID user1 192.168.10.78 1Mbit 2Mbit 1Mbit 4Mbit mageal 10 user2 192.168.10.44 1Mbit 1Mbit 2Mbit 3Mbit ukrtel 11 


ファイルは、タブまたはスペースで区切られたフィールドで、次の値が含まれます。
クライアント -ユーザー名。 レポートを簡単にするために必要
ネットワーク上のユーザーのIPアドレス
DOWN-ユーザーへのデータフローレート
CEIL-親クラスでこの帯域を使用できるユーザーへの着信トラフィックの最大速度
UP-ユーザーデータレート
CEIL-ユーザーへの着信トラフィックのCEILと同じ
PROVIDER-ユーザーリクエストの処理に使用されるプロバイダー(複数ある場合)
IDは、ユーザーのクラス番号です。 以下のクラス番号の詳細。
また、いくつかのbashスクリプトも使用しています。

root@steel:/etc/rc.d/shape# cat ./rc.shape

#!/bin/bash
. /etc/init.d/functions
/sbin/modprobe ifb
/sbin/ip link set dev ifb0 up

TC="/sbin/tc"
DEV_P1_DOWN="eth0"
DEV_P1_UP="ifb0"

stop(){
$TC qdisc del dev $DEV_P1_DOWN root
$TC qdisc del dev $DEV_P1_UP root
$TC qdisc del dev $DEV_P1_DOWN ingress
}
start(){
#
$TC qdisc del dev $DEV_P1_DOWN root
$TC qdisc del dev $DEV_P1_UP root
$TC qdisc del dev $DEV_P1_DOWN ingress

## ifb0
$TC qdisc add dev $DEV_P1_DOWN ingress
$TC filter add dev $DEV_P1_DOWN parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $DEV_P1_UP

#

. /etc/rc.d/shape/rc.shape.down.classes
. /etc/rc.d/shape/rc.shape.up.classes

# , 50 80.
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 1 u32 match ip dst 10.0.0.1 flowid 1:10
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 1 u32 match ip src 10.0.0.1 flowid 1:10

#
. /etc/rc.d/shape/rc.shape.filters
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
start
;;
*)
msg_usage "${0##*/} {restart|start|stop}"
RETVAL=1
esac


次にロードされるコードは次のとおりです。

クラス

root@steel:/etc/rc.d/shape# cat ./rc.shape.down.classes

#!/bin/bash
## DOWNLOAD CLASSES
##########################################################
#
$TC qdisc add dev $DEV_P1_DOWN root handle 1: htb default 900

#
$TC class add dev $DEV_P1_DOWN parent 1: classid 1:1 htb rate 100Mbit burst 15k

# (SERVER -> CLIENTS)
$TC class add dev $DEV_P1_DOWN parent 1:1 classid 1:10 htb rate 50Mbit ceil 80Mbit burst 15k

# (SERVER -> CLIENTS)
$TC class add dev $DEV_P1_DOWN parent 1:1 classid 1:100 htb rate 15Mbit burst 15k

# (SERVER -> CLIENTS)
$TC class add dev $DEV_P1_DOWN parent 1:1 classid 1:900 htb rate 128Kbit ceil 128Kbit

root@steel:/etc/rc.d/shape# cat ./rc.shape.up.classes
#!/bin/bash

## UPLOAD CLASSES
#############################################################
#
$TC qdisc add dev ifb0 root handle 1: htb default 900

#
$TC class add dev ifb0 parent 1: classid 1:1 htb rate 100Mbit burst 15k
# (CLIENTS -> SERVER)
$TC class add dev $DEV_P1_UP parent 1:1 classid 1:10 htb rate 50Mbit ceil 80Mbit burst 15k

# (CLIENTS -> SERVER)
$TC class add dev $DEV_P1_UP parent 1:1 classid 1:100 htb rate 5Mbit burst 15k
# (CLIENTS -> SERVER)
$TC class add dev $DEV_P1_UP parent 1:1 classid 1:900 htb rate 128Kbit ceil 128Kbit


そしてフィルター:

root@steel:/etc/rc.d/shape# cat ./rc.shape.filters
#!/bin/bash
# “users”
while read LINE
do
set -- $LINE
if [[ $1 =~ '^\#' ]]
then
continue
fi
################################################################
CLIENT_IP=$2
CLIENT_DOWN_RATE=$3
CLIENT_DOWN_CEIL=$4
################################################################
# DOWNSTREAM
#####################

#
$TC class add dev $DEV_P1_DOWN parent 1:100 classid 1:${8}1 htb rate $CLIENT_DOWN_RATE ceil $CLIENT_DOWN_CEIL

# PRIO 1 -> icmp traffic
$TC class add dev $DEV_P1_DOWN parent 1:${8}1 classid 1:${8}2 htb rate 33kbit ceil $CLIENT_DOWN_CEIL prio 1

# PRIO 2 -> udp, ssh
$TC class add dev $DEV_P1_DOWN parent 1:${8}1 classid 1:${8}3 htb rate 33kbit ceil $CLIENT_DOWN_CEIL prio 2

# PRIO 3 -> tcp sport 80
$TC class add dev $DEV_P1_DOWN parent 1:${8}1 classid 1:${8}4 htb rate 33kbit ceil $CLIENT_DOWN_CEIL prio 3

# PRIO 4 -> unclassified traffic
$TC class add dev $DEV_P1_DOWN parent 1:${8}1 classid 1:${8}5 htb rate 33kbit ceil $CLIENT_DOWN_CEIL prio 4

# icmp- icmp- 1
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 1 u32 match ip dst $CLIENT_IP \
match ip protocol 1 0xff flowid 1:${8}2

# udp
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 2 u32 match ip dst $CLIENT_IP \
match ip protocol 17 0xff flowid 1:${8}3
# ssh
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 2 u32 match ip dst $CLIENT_IP \
match ip protocol 6 0xff match ip sport 22 0xffff flowid 1:${8}3
# WWW, sport 80
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 3 u32 match ip dst $CLIENT_IP \
match ip protocol 6 0xff match ip sport 80 0xffff flowid 1:${8}4
# – ,
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 4 u32 match ip dst $CLIENT_IP flowid 1:${8}5

# UPSTREAM
#####################

CLIENT_UP_RATE=$5
CLIENT_UP_CEIL=$6

###

$TC class add dev $DEV_P1_UP parent 1:100 classid 1:${8}1 htb rate $CLIENT_UP_RATE ceil $CLIENT_UP_CEIL
# PRIO 1 -> icmp traffic
$TC class add dev $DEV_P1_UP parent 1:${8}1 classid 1:${8}2 htb rate 1kbit ceil $CLIENT_UP_CEIL prio 1
# PRIO 2 -> udp, ssh
$TC class add dev $DEV_P1_UP parent 1:${8}1 classid 1:${8}3 htb rate 1kbit ceil $CLIENT_UP_CEIL prio 2
# PRIO 3 -> unclassified traffic
$TC class add dev $DEV_P1_UP parent 1:${8}1 classid 1:${8}4 htb rate 1kbit ceil $CLIENT_UP_CEIL prio 3
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 1 u32 match ip src $CLIENT_IP \
match ip protocol 1 0xff flowid 1:${8}2
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 2 u32 match ip src $CLIENT_IP \
match ip protocol 17 0xff flowid 1:${8}3
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 2 u32 match ip src $CLIENT_IP \
match ip protocol 6 0xff match ip dport 22 0xffff flowid 1:${8}3
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 3 u32 match ip src $CLIENT_IP flowid 1:${8}4

done < ./users


これらのスクリプトは、次の1つのディレクトリに配置する必要があります。

chmod +x ./rc.shape

そして

./rc.shape start

トラフィックを制限する方法の1つを説明しました。 tcユーティリティは、トラフィック制限の点で非常に強力なものです。 この問題のより詳細な研究については、ドキュメントLARTC-HOWTOを読むことをお勧めします。

Source: https://habr.com/ru/post/J119611/


All Articles