LinuxでIPによるトラフィックシェーピングを行うにはどうすればよいですか?


15

透過的なプロキシ設定があります。Linuxでトラフィックシェーピングを探してみましたが、オンラインで見つけることができたのは、インターフェイス(eth0 / eth1 ...)によってトラフィックを制限することだけでした。

IPアドレスまたはIP範囲で帯域幅を制限する必要があります(特定の制限を超えないようにします)。その方法は見つかりません。

それを行う方法はありますか?

回答:


17

カーネルのトラフィックシェーピングレイヤーは、基本的に、ネットワークカードに接続されたパケットスケジューラです。したがって、1つのトラフィックシェーピングポリシーが1つのネットワークカードに適用されます。

あなたの場合、できることは、IPと接続された帯域幅のリストを作成し、次に各IPに対して次のものを作成することです。

  • classidによって識別される1つのトラフィックシェーピングルール
  • パケットを特定のマーク値にマークする1つのnetfilterルール
  • そのパケットマークをclassidにバインドする1つのフィルターは、指定されたパケットにトラフィック制御ルールを適用します。

@Zoredacheの例は機能しますが、パケットをフィルタリングするにはTCではなくNetfilter機能を、シャッピングアルゴリズムにはCBQではなくHTBを使用することを個人的に好みます。したがって、次のようなものを試すことができます(連想配列にはBash 4が必要です):

#! /bin/bash
NETCARD=eth0
MAXBANDWIDTH=100000

# reinit
tc qdisc del dev $NETCARD root handle 1
tc qdisc add dev $NETCARD root handle 1: htb default 9999

# create the default class
tc class add dev $NETCARD parent 1:0 classid 1:9999 htb rate $(( $MAXBANDWIDTH ))kbit ceil $(( $MAXBANDWIDTH ))kbit burst 5k prio 9999

# control bandwidth per IP
declare -A ipctrl
# define list of IP and bandwidth (in kilo bits per seconds) below
ipctrl[192.168.1.1]="256"
ipctrl[192.168.1.2]="128"
ipctrl[192.168.1.3]="512"
ipctrl[192.168.1.4]="32"

mark=0
for ip in "${!ipctrl[@]}"
do
    mark=$(( mark + 1 ))
    bandwidth=${ipctrl[$ip]}

    # traffic shaping rule
    tc class add dev $NETCARD parent 1:0 classid 1:$mark htb rate $(( $bandwidth ))kbit ceil $(( $bandwidth ))kbit burst 5k prio $mark

    # netfilter packet marking rule
    iptables -t mangle -A INPUT -i $NETCARD -s $ip -j CONNMARK --set-mark $mark

    # filter that bind the two
    tc filter add dev $NETCARD parent 1:0 protocol ip prio $mark handle $mark fw flowid 1:$mark

    echo "IP $ip is attached to mark $mark and limited to $bandwidth kbps"
done

#propagate netfilter marks on connections
iptables -t mangle -A POSTROUTING -j CONNMARK --restore-mark

-編集:デフォルトクラスを忘れて、スクリプトの最後にマークを伝播します。


うーん..リストにないものにデフォルトの帯域幅制限を追加する方法は?
Kokizzu

プリオ定義として$ markを使用しました。すべてに同じ優先順位を使用する方が良いでしょうか?
モトボイ

「iptables -t mangle -A INPUT」を「iptables -t mangle -A OUTPUT」に変更すると、サーバーから特定のIPへのレートを制御できますか?
フランクバルセナス

この後に設定を復元するにはどうすればよいですか?
ステファンロギン

Cant 'はこの機能を実現しているようで、1つのIPに対してループなしでコマンドを手動で記述します。
アドネスピトーゴ

5

このようなことは、請負業者のWebカメラを限られた帯域幅に制限するのに役立ちました。詳細については、tcのmanページをご覧ください。

#!/bin/bash
set -x

DEV=eth0
export DEV

tc qdisc del dev $DEV root
tc qdisc del dev $DEV root
tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 100mbit

# setup a class to limit to 1500 kilobits/s
tc class add dev $DEV parent 1: classid 1:1 cbq rate 1500kbit \
   allot 1500 prio 5 bounded isolated

# add traffic from 10.2.1.37 to that class
tc filter add dev $DEV parent 1: protocol ip prio 16 u32 \
   match ip src 10.2.1.37 flowid 1:1

3
CBQはビットがabandonnedされる...あなたは同じ結果を使用して取得するHTBがはるかに簡単に見つけるだろう
ジュリアンVehent

1
それだけ、このスクリプトで使用されている場合、輸出DEVする必要はありません....
ベルクデンゲルトバン

1

あなたの質問を正しく理解しているかどうかはわかりません。

ほとんどの着信データを制御するために、透過プロキシ(Squid for HTTPなど)が使用されます。トラフィックシェーピングは、発信データを制御するために使用されます。

詳細を提供する必要があります。HTTPプロキシの背後に多数のワークステーションがあり、それらのダウンロード速度を制限しようとしている場合、Squid + delay poolsのようなものをお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.