linuxで送信される(outboundな)パケットの帯域をIPアドレス+ポート毎に制限

cbq(Class Based Queueing) linuxのiproute と tc (traffic control) で出来るらしい。tcのコマンドがやたらと複雑なので、cbq.init というherlper script を使うと簡単で良いので素晴らしく便利。

cbq.init

redhat/centos なら iproute package にcbqコマンドが入っているので

# yum install iproute

とかする。もしくは http://sourceforge.net/projects/cbqinit/ からとってきて 適当な場所に置く。

debian はshaper packageに入ってる、という話を聞いたけど debian 6.0 squeeze にはshaper packageがなかったので、↑のsourceforge から取ってきて少し修正する。(設定ファイルを保存するディレクトリが redhat系の /etc/sysconfig/cbq になっているので/etc/default/cbq 、/etc/cbq 等に修正)

HOW DOES IT WORK?

HOW DOES IT WORK?
Every traffic class must be described by a file in the $CBQ_PATH directory
(/etc/sysconfig/cbq by default) - one file per class.

The config file names must obey mandatory format: cbq-. where
is two-byte hexadecimal number in range <0002-FFFF> (which in fact
is a CBQ class ID) and is the name of the class -- anything to help
you distinguish the configuration files. For small amount of classes it is
often possible (and convenient) to let resemble bandwidth of the
class.

Example of valid config name:
cbq-1280.My_first_shaper

設定ファイル

cbq.init で設定するディレクトリに置く。redhatなら /etc/sysconfig/cbq 以下に。ファイル名 "cbq-[id].[name]"というruleがあるので注意。

  • id
    • 他のファイルと重複しないid (16進数で0002 ~ FFFF)
  • name
    • 何でもいいので設定するポリシーがわかるようなものにする

書式

cbq.init のコメントに説明が書いてる。とりあえず必須なもの

DEVICE=<ifname>,<bandwidth>,[weight]
RATE=<speed>
WEIGHT=<speed>
RULE=[[saddr[/prefix]][:port[/mask]],][daddr[/prefix]][:port[/mask]]
DEVICE
  • ifname: interface名 (ex: eth0)
  • bandwidth: interfaceの物理的な帯域幅 (ex: 1000Mbit)
  • weight: "As a rule of thumb: = / 10" なのでbandwidthの1/10にしとく (ex: 100Mbit)
RATE

この値に書かれた速度で帯域制限をかける。 (ex: 10Mbit)

WEIGHT

"As a rule of thumb, use WEIGHT ~= RATE / 10." (ex: 1Mbit)

RULE

制限をかける"送信元IP:ポート,宛先IP:ポート"の条件を書く。

  • ex1) ftp,http サーバを動かしていて、ダウンロードされる帯域を制限したいとき

送信元は自分で、宛先は任意なので

# ftp server
RULE=:21,
# http
RULE=:80,

などに。送信元IP/portを指定するので最後のコンマを忘れずに。

  • ex2) 他のサーバへの帯域を制限したい。

例えばDB使ってるwebアプリに大量にアクセスが来た場合の対策で、DBサーバへのtrafficを抑えたいときとか。 (webサーバからdbサーバへのtraffic = SQLのリクエスト等で大したパケットが流れないから例にしたのは間違いだった。。。)

RULE=ip.address.to.server:8080

送信元は指定せずに、宛先のIP,ポートだけ書けば良い。

  • ex3) 全てのoutboundを制限する

RULEが空(コンマだけ)だったらダメだったので、
portを指定せず、自分のIPをコンマの左側に書いておけばいい
networkでも別に問題ないので設定をコピペするなら/24とかのほうが便利かも

RULE=192.168.0.0/24,

設定反映

# /etc/init.d/cbq.init start

設定値より大幅にスループットが落ちる場合

NICによってはtso(TCP Segumentation Offload)*1が有効な場合に、cbqで帯域制限を掛けると設定値より大幅にスループットが落ちるようだ。(家のパソコンでもなった;;)

1GbitのNICでRATEを10Mbitに設定したのに、実際の速度は150kbpsしか出ないとか。

tso の確認/設定変更
## 確認
# ethtool -k eth0 | grep tcp
tcp segmentation offload: on # tso が有効
## 無効にする
# ethtool -K eth0 tso off

tso を無効にするのだから、ネットワークの状況によっては全体的なスループットが落ちたり、CPU負荷が上がるかもしれないので設定する場合は注意したほうが良いかも?

*1:TCP/IPの処理をCPUで行わずに、NICで行いスループットを上げる機能。最近のNICにはだいたいついてる?