ネットワークトラフィック制御の仕組み

以下のテキストは、執筆時当時の情報を元に書いたものであり、 現在の情勢にそぐわないことを含む場合があるので注意されたい。 また、テキストは最終提出原稿で校正を経る前のものなので、実際にUNIXUSER 本誌に記載されたものとは異なる。誤字脱字等そのままである。

致命的な誤り以外は加筆修正等は行なわないので情報の鮮度に気をつけつつ 利用して欲しい。

目次


●●●● ネットワークトラフィックを制御せよ ●●●●

Mbps単位のインターネット接続が一般家庭レベルにまで浸透し、もはやアナログ
モデムでのダイヤルアップなどのことは忘れかけている。そのせいか「低速回線
への配慮」などを忘れたページが増えて来たり、動画などの巨大なデータをやり
とりする人も増えて来た。そしていつのまにか別のサービスに支障が出るように
なってしまった、といったことはないだろうか。特定のサービスによる通信量が
突発的に肥大しても他のサービスに影響を及ぼさず QoS(Quiality of Service)
を保つように先手を打っておくことが肝要だ。
第1特集ではトラフィック制御の基本的な仕組みや、それをPC-Unixで利用するた
めの方針をマスターしよう。


===========================================
Part1 ネットワークトラフィック制御の仕組み
===========================================
単に特定のサービスのデータ転送速度を絞るだけではせっかく十分な幅を持った
物理回線を無駄にしているだけである。トラフィック制御では帯域幅を大切な
「資源」ととらえ、それを複数のサービスでいかに上手に分け合うかを決めるの
が重要だ。まずは、基本的な仕組みから押さえて行こう。


■
■トラフィック制御の必要性
■

常時接続が安価に実現できるようになって久しいが、特に最近では固定IPアドレ
スのための追加費用も目に見えて下がって来た。そうした好材料が揃ったおかげ
で自分の管理するサーバをインターネットに公開することが容易になった。同時
に低速回線による接続が減った影響で、「重い」コンテンツを置くことに対する
「遠慮」も減って来た。P2Pによる巨大データの授受、音声や動画の配信なども
一般化し、それらを無条件で転送していると普段使う基幹的なサービスが使い物
にならなくなる恐れが出ている。

こんな事例を考えよう。たとえば管理運営しているメイリングリスト(ML)があっ
たとしよう。そのMLに巨大なデータファイルが投稿されたらどうなるだろうか。
「全員に配送されるまで時間がかかるだろうなあ」という心配程度では済まされ
ないのだ。

qmailの登場以来、SMTPコネクションは並列で張るのが主流となっている。
sendmailを利用する場合でもsmtpfeedを利用して並列配送することで、複数の宛
先に配送するのが高速に処理される。しかし、巨大なメッセージを並列配送する
と、それがサイトに与えられたネットワーク帯域幅を全て食い尽くしてしまう。
結果、全てのネットワーク通信が使い物にならないほど遅くなる【註 を】。もちろん、
SSHでログインしてそれを修復しようとしても、コマンド入力に異様に時間がか
かったり、SSH接続自体がタイムアウトしてしまう可能性もある。結果として、
DoS攻撃を受けたのと同じ被害を受け、しばらくの間外部から制御不能な状態が
続く。
---[註 を]------------------------------------------------------------
実際に筆者が管理しているドメインの運用を開始した頃にこのトラブルに遭遇し
た。巨大メッセージをmail queue から削除するまで何時間もかかったのを記憶
している。
----------------------------------------------------------------------

管理運用しているサーバのコンソール前に常にいるのなら問題ないのだが、そう
でない場合はSSHでのログイン作業に支障が出ないよう保証しておかなければ危険
である。上述した巨大ファイルのML投稿の例に限らず、DoS的な外部からのアクセ
スがあった場合、それを回避する設定を行なうためにはSSH接続が安定した速度で
行なえるように設定しておく必要がある。このようなときに効果的なのがトラ
フィック制御である。

■
■トラフィック制御の主な方式
■

●制御をかける位置

トラフィック制御はデータの流れに対する制限であるから、データの送出源と中
継箇所で制限をかけることができる【図 い】。

---[図 い]------------------------------------------------------------
  +-- サーバホスト --+                       +-------------+
  | +-----------+    |ネットワークI/F        |   ルータ    |
  | |サーバ     |   +++ (2)		     |	 	   |
  | |プログラム-+---:-:----------------------+-------------+---->Internet
  | |       (1) |   | |			     |	(3)	   |
  | +-----------+   +++			     |		   |
  |                  |			     +--------------
  +------------------+
----------------------------------------------------------------------

(1)サーバプログラムによる制御

   ネットワークサービスデーモンが、接続クライアントにデータを送出する部分
   で単位時間あたりの送出バイト数を制御する機能を持っている場合がある。た
   とえば、ProFTPDでは1つのクライアントにたいしてデータをどの程度の速さで
   送信するか(の上限値)を設定できる。この場合、制御をかけたいサービスを確
   実に指定することができる代わりに、サービスデーモンがこのような機能を持っ
   ていなければ実現できない。

(2)サーバホストのネットワークインタフェースでの制御

   サーバホストからクライアントに向けて送信されるパケットがどのネットワー
   クインタフェースを通過するかに着目し、そのインタフェースを通過するパ
   ケットの「発信元 IPアドレス/ポート」、「送信先 IPアドレス/ポート」、
   「パケット種別」などを基準に制御する。(1)の場合と違い制御をかける対象
   としてプログラム(サービスデーモン)を直接指定するわけではないため、厳
   密な意味での制御対象指定にはならない。

(3)中継地点での制御

   LANと外部をむすぶルータなどの機器で(2)と同様の選別基準で制御対象を決定
   し、トラフィック制御する。PCルータを使う場合は制御のための設定方法は
   (2)と全く同じになるだろう。

注意が必要なのは、パケットを受け取る側でトラフィック制御を行なっても意味
が薄いという点である。なぜなら、受信ホストにパケットが届くときには、既に
ネットワーク資源を消費しているからだ【註 ち】。このため通常トラフィック制
御は、パケットの送出側(かそれに近い場所)で行なう。

---[註 ち]------------------------------------------------------------
もっとも、受信側の速度が遅ければ送出側の調整により
期待した速度に最終的に収束する場合が多い。
----------------------------------------------------------------------

今回の特集では、サーバ管理者自らがトラフィック制御を意識的に操作し、その
効果を自在に制御できるようになることを目標とするので、PC-Unixを利用する場
合のトラフィック制御方法を解説する。Part1ではトラフィック制御機構の主なア
プローチを紹介する。Part2では代表的なトラフィック制御実装である
ipfw+dummynet(FreeBSD) と iproute2+tc(Linux) をとりあげ、簡単かつ典型的な
トラフィック制御を行なう事例とともに実践的な設定方法を解説する。

●代表的なトラフィック制御方式

トラフィック制御の方式を理解するためには「キュー」という概念を知る必要が
ある。といってもさして難しいわけではなく、「待ち行列」を思い浮かべれば良
い。どんなに多くのサービスデーモンが動いているホストでも、外部にパケット
が出て行くときには最終的には1本のネットワークケーブルに流れる電気的信号
に変換される。CPUの処理にたとえると、「複数のプロセスが同時に動いている
ように見えるけれども実はCPUが時分割で利用されミクロな視点で見れば1つのコー
ドが動いている」のと同様、ネットワークトラフィックも「複数のサービスが同
時に発信しているようにみえるパケットも、実際にはミクロの視点で見れば一つ
のパケットだけが送出されている」ことになる。

実際に送出されるパケットが、送出されるべき順番に並んで待機している状態の
待ち行列のことをキューという。この状態に関しては、純粋に自動販売機に並ぶ
人の列を思い浮かべるのでそう遠く外れていない。

以下、標準的なキューイング方式からトラフィック制御に利用されている方式の
代表的なものを示す。Part2で利用する制御方式の基本となる考え方なので、も
しPart2の設定を行なっていて分からなくなったら以下の部分を読み返すと良い
だろう。

・FIFO(First In First Out) キュー

  基本となるキューで、トラフィック制御をかけないデフォルト状態がこれにあ
  たる。FIFO自身は帯域制御のためのものではないが、以下で説明する帯域制御
  の方式の最終的な出口はFIFOに渡されることと、FIFOを応用した帯域制御方式
  もあるので理解しておきたい。

  FIFOでは送出依頼があったパケットを待ち行列の最後尾に配置する、つまり、
  最初に来たパケットを最初に送り出すの【図 ろ】。

---[図 ろ]------------------------------------------------------------

    <<左半分>>					<<右半分>>


 +----------------------------+	            | [ SSH] | (末尾)
 |  銀行の窓口から少し離れた		    | [HTTP] |
 |  位置に一列に並んで客が		    | [SMTP] |  ↓
 |  待っている絵			    | [ SSH] |
 +-----------------------------		    | [ SSH] |
 					    | [HTTP] | (先頭)
					    \----|---/ |(I/F)
					        ↓
						↓ 順番に出て行く
----------------------------------------------------------------------

・PRIQ/PQ(Priority Queueing)

  FIFOでは全てのパケットを平等に並ばせたが、そうではなくパケットの種類に
  応じて優先度をつけるのが Priority Queueing である。「帯域制御」という
  よりは「優先制御」にあたる。パケットの分類には、TCP/UDPの種別やポート
  番号、UID、送信元アドレス/宛先アドレスなどが利用される【図 は】。

---[図 は]------------------------------------------------------------

    <<左半分>>					<<右半分>>

  銀行の窓口から少し離れた位置に	 優先度1     優先度2    優先度3
  「足の不自由な方」			|       |  |        |  | [SMTP] |
  「妊娠中・赤ちゃん連れの方」		|       |  | [HTTP] |  | [ FTP] |
  「その他の方」			| [SSH] |  | [HTTP] |  | [ FTP] |
   という三つの看板があり		\---\---/  \----|---/  \---/----/
   その看板の後に3列の行列が		     \	        |         /
   できている絵				      \         |        /
   					       \ 	|	/
					        \	|      /
						 \	|     /
						  \	|    /
						   \	|   /
						   |         |
						   | [ SSH ] |
						   \----|----/
							↓ 優先度の高い
							↓ ものが先に選
  							↓ ばれて出て行く

----------------------------------------------------------------------

  送出依頼の発生したパケットは、それに応じた優先度を持つキューに入れられ
  る。そして、優先度の高いキューにあるものが先に送出される。優先度の高い
  キューが空になったときに初めて次点の優先度を持つキューの中味が処理され
  る。裏を返せば、優先度の高いキューに分類されるパケットが送り出され続け
  ていると、優先度の低いキューはなかなか処理されなくなる。したがって、
  PRIQを下手に設定すると特定のサービスが実用にならない事態に陥ることもあ
  るので注意が必要だ。

  ストリーム配信を行なうサーバなど、他のサービス用の通信スループットは犠
  牲にしても優先させたいものがある場合に有効である。


・WFQ(Weighted Fair Queueing)

  PRIQではキューに対する優先度を絶対的な処理順位として扱ったが、複数の
  キューに対してそれぞれ「重み付け」を行ない、低優先度を持つキューも高優
  先度のものより先に処理される可能性を与えたものが Weighted Fair
  Queueing である。【図 ほ】の例では、3つのキューが優先度の比率 5 :
  3 : 2 という割合で処理される。つまり、3 つのキュー全てに送出待ちパケッ
  トがある場合、それらは 5 : 3 : 2 の割合で取り出されて送出キューに送ら
  れる。その結果として3つのキュー全体に与えられた帯域幅の 5/10、3/10、
  2/10 が各キューに与えられることになる。

---[図 ほ]------------------------------------------------------------

 優先度      優先度    優先度
   5      :     3     :    2
|       |  |        |  | [SMTP] |
|       |  | [HTTP] |  | [SMTP] |
| [SSH] |  | [HTTP] |  | [ FTP] |
\---\---/  \----|---/  \---/----/
     \	        |         /
      \         |        /
       \ 	|	/
        \	|      /
	 \	|     /
	  \	|    /
	   \	|   /
	   |         |
	   | [ SSH ] |
	   \----|----/
		↓
		↓
		↓

----------------------------------------------------------------------

  Part2で利用するipfw(FreeBSD)では、WFQを効率化したWF2Q+(Worst-case Fair
  Weighted Fair Queueing) を採用している。


・帯域制限(Traffic Shaping)

  特定のパケットを分類し、そのパケットの送出速度があらかじめ指定した一定
  の値を超えないように調整する【図 に】。
---[図 に]------------------------------------------------------------

   smtpdと書いてある   httpdと書いた	     sshdと書いた
   ゼッケンをつけた    ゼッケンをつけた	     ゼッケンをつけた
   デーモン君	       デーモン君	     デーモン君
     ↓		        ↓		     ↓
      ○~		○~		     ○~
     /|\	       /|\		    /|\
     smtpd     	       httpd		    sshd
     /\      	       /\		    /\
             3人のデーモン君がバケツに大量に入ったパケットを注いでる

   +--------	     +--------            +---------
   | [SMTP]	     | [HTTP]		  |  [SSH]
   | [SMTP]\	     | [HTTP]\		  |  [SSH]\
   +--------\	     +--------\		  +--------\
         \   :    /            :		    :
  64Kbps→\64Kbps/	       :         	    :
  という   \    /	       :		    :
  ラベルが  |  |	       :		    :
  貼られた  |  |	       :		    :
  じょうご  |  |	       :		    :
  	     :  	       :		    :
  	     :  	       :		    :
         |						  |
	 |						  | ←おおきな
	  \--------\                             /--------/   じょうご
	            --------\           /--------
		             |         |
		             | [ SSH]  |
		             | [HTTP]  |
		             | [SMTP]  |
		             | [HTTP]  |
		             | [ SSH]  |
		             | [ SSH]  |
		             | [HTTP]  |
		             | [ SSH]  |
			     |         |
			         ↓
			         ↓
			         ↓

----------------------------------------------------------------------

  単純なトラフィック制御の方式ではあるが、FTPのような帯域消費の激しい通
  信が他のサービスの通信に与える悪影響を軽減するなどの目的には適している。
  ただし、【図 に】の例でいえば、どんなに回線が空いているときでもSMTPの
  配送速度が64Kbpsに制限されるので、単体での利用は効率的といえない面もあ
  る。


・CBQ(Class Based Queueing)

  帯域制限のパケット分類方法を発展させ、親子関係を持つグループに分類して
  制限をかけられるようにしたものが Class Based Queueing である。単純な
  Traffic Shaping の方式を、通信回線の帯域という「資源」を主眼とした考え
  方で見ると【図 へ】のようになる。

---[図 へ]------------------------------------------------------------
(※四角い枠で書いていますが丸枠の方がイメージを掴みやすいので
   丸枠でお願いします)


       通信回線全体
         (512Kbps)
   +------------------------------------------------------+
   |                                                      |
   |  +-----64Kbps-----------+                   	  |
   |  |                      |				  |
   |  |     [SMTP]	     |      [SSH]     [HTTP]	  |
   |  | [SMTP]        [SMTP] |  [FTP]	      		  |
   |  |         [SMTP]	     |				  |
   |  +----------------------+			[SSH]	  |
   |                           [RSYNC]    		  |
   |                     [HTTPS]	[SSH]		  |
   |			 	  [FTP]			  |
   +------------------------------------------------------+

           図: SMTPのみに64Kbpsの制限をかけている例

----------------------------------------------------------------------

  帯域制限がかけられているSMTPは、絶対に64Kbpsを超えることが許されない反
  面、それ以外(SSHなど)は回線が空いていれば帯域ぎりぎりまで使うことがで
  きる。ただし、SSHが帯域を消費し尽くすと他のサービスに悪影響が出る。こ
  れを解決するため、CBQでは階層関係を持ったグループを「クラス」として
  定義する【図 と】。

---[図 と]------------------------------------------------------------

       通信回線全体
         (512Kbps)
   +------------------------------------------------------+
   |                                                      |
   |  +-----64Kbps-----------+ +---------448Kbps-------+  |
   |  |                      | | +---384Kbps for SSH-+ |  |
   |  |     [SMTP]	     | | |  [SSH]     [SSH]  | |  |
   |  | [SMTP]        [SMTP] | | | [SSH] [SSH]	     | |  |
   |  |         [SMTP]	     | | |                   | |  |
   |  +----------------------+ | +--  ---------------+ |  |
   |  	↑クラスA	       | 	↑クラスC      |  |
   |  			       | 		       |  |
   |                           | +---64Kbps for misc-+ |  |
   |                           |   [HTTPS]   [HTTP]  | |  |
   |			       | | [FTP] [RSYNC]     | |  |
   |			       | |         [HTTP]    | |  |
   |			       | +-------------------+ |  |
   |  			       | 	↑クラスD      |  |
   |  			       | 		       |  |
   |			       +-----------------------+  |
   |			             ↑クラスB		  |
   +------------------------------------------------------+
	↑ルートクラス

           図: CBQによる帯域資源管理のイメージ
	   クラスCとクラスDは枠に穴が空いていて互いに貸し借りできる。

----------------------------------------------------------------------

  図では、以下の4つのクラスが定義されている。

  【ルートクラス】  ----  全ての親となるクラス
     |
     +--【クラスA】  --- 64Kbpsに制限されたキューを持つクラスで
     |		     	 SMTPがそこに分類される
     +--【クラスB】  --- 448Kbpsに制限されたキューを持つクラスで
	     |		 SMTP以外がそこに分類される
	     +--【クラスC】  --- 384Kbpsに制限されたキューを持つ、
	     |		     	 クラスBの子クラスでSSHがそこに分類される
	     +--【クラスD】  --- 64Kbpsに制限されたキューを持つクラスBの子
	     		     	 クラスでSSH以外がそこに分類される

  デフォルトでは各クラスに割り当てられた帯域幅を超過することができないが、
  CBQではそれぞれのクラスに対して「borrow」オプションを指定することで、親
  クラスから余っている帯域を「借り」ることが可能となる。もちろん、他の子
  クラスが回線を使用している場合は「借り」ができないことも十分にありうる。

  このように、指定したサービスの帯域を制限しつつ、回線負荷が低い場合にな
  るべく多くの帯域割り当てを可能にすることができるのがCBQである。CBQはルー
  タ専用機などでも広く採用されている。Part2で解説する設定例ではCBQに触れ
  ないが、他の多くのトラフィック制御方式でもCBQのもつ親子関係に類似した
  アプローチを取っているのでCBQの考え方を理解しておくと良いだろう。

	-	-	-	-	-	-	-	-

以上いくつか方式を挙げたが、実際にトラフィック制御を行なう場合には、いく
つかを階層的に組み合わせて利用することが多い。


■
■現在利用できるトラフィック制御の実装
■


前節で挙げたのは数多くある制御方式のほんの一部といってよい。利用したいOS 
で使えるネットワーク制御ツールによって、どのようなトラフィック制御方式を
実装しているかは異なっている。いずれの場合でも実装している方式をうまく組
み合わせることで目的とするQoS管理を行なうわけだ。以下に代表的なトラフィッ
ク制御機構とそれぞれで利用できるものを挙げる。

●IPFW (FreeBSD)

カーネルオプション

options         DUMMYNET

を組み込むか、カーネルモジュール dummynet.ko をロードすることでDUMMYNETに
よる帯域制御が利用可能になる【註 り】。

---[註 り]------------------------------------------------------------
options         IPFIREWALL
も必要だが、/etc/rc.conf でfirewall_enable=YESしていれば、自動的に
カーネルモジュール ipfw.ko がロードされるので。ipfwによるファイアウォー
ル機能を普段利用している場合はとくに意識しなくても自動的に組み込まれてい
るだろう。
----------------------------------------------------------------------

ipfw+dummynet【註 ぬ】では、Traffic Shapingと、WF2Q+による帯域制限が利用
できる。
---[註 ぬ]------------------------------------------------------------
FreeBSD 5の場合はipfw2
----------------------------------------------------------------------

●PF (OpenBSD, NetBSD, FreeBSD5)

PF では、パケットキューイングの統合的な実装であるALTQと一体化して、パケッ
トフィルタリングだけでなくトラフィック制御も可能になっている【註 る】。
PFは比較的新しいパケットフィルタツールで元はOpenBSDだけのものであったが、
FreeBSDとNetBSDの最新版に取り込まれたことを受け、今後利用の幅が広がって行
くことが予想される。
---[註 る]------------------------------------------------------------
http://www.openbsd.org/faq/pf/ja/
http://www.openbsd.org/faq/pf/ja/queueing.html
----------------------------------------------------------------------
PF経由で呼ばれるALTQでは制御方式として PRIQ, CBQ, HFSC (Hierarchical
Fair Service Curve) が利用できる。ALTQを単体利用する場合はさらに
RED(Random Early Drop), RIO(RED with IN/OUT) などが利用できる。これらの
詳細については
http://www.csl.sony.co.jp/person/kjc/kjc/software.html#ALTQ
を参照して欲しい。

●iproute2 (Linux)

現在のLinuxカーネルが持っているIP接続に関する制御を行なうフレームワーク
「iproute2」でもトラフィック制御の機能が利用できる。トラフィック制御関連
のの設定を行なうコマンドラインインタフェースとしてtcコマンドが用意されて
いる、

iproute2で利用できる制御方式にはCBQ, RED, TBF(Token Bucket Filter),
SFQ(Stochastic Fairness Queueing), HTB(Hierarchical TBF), その他…のよう
に一般的なものから独自に実装されたアルゴリズムまで多数存在する。残念なが
ら全ての制御方式について言及した文書を探せなかったが、使用頻度の高いもの
についての解説が
http://www.lartc.org/ (英語)
http://www.linux.or.jp/JF/JFdocs/Adv-Routing-HOWTO/ (日本語)
にあるので参考にして頂きたい。


■
■パケットフィルタとの効果的な組み合わせを
■

WANに接続している機器ではパケットフィルタを利用して未然に不正アクセスを防
ぐというのはもはや常識だろう。ただ、パケットフィルタの場合は特定のホスト
からのアクセスを禁止するか許可するかの二値しか取り得ない。その中間的な選
択肢として「○○へのアクセスが多くて重くて仕方ないが、全面禁止してしまう
のは忍びない……ちょっと遅くしようか」といったことも可能にできるのがトラ
フィック制御の良い点でもある。積極的にサービスを公開しつつ、DoSや突発的な
アクセス過多に対する耐性も考慮したサーバ環境を構築して行きたい。

Part2では具体的な制御を行なう例を見て行こう。

---[註 わ]------------------------------------------------------------
----------------------------------------------------------------------
---[註 か]------------------------------------------------------------
----------------------------------------------------------------------


yuuji@example.org
Fingerprint16 = FF F9 FF CC E0 FE 5C F7 19 97 28 24 EC 5D 39 BA
HIROSE Yuuji - ASTROLOGY / BIKE / EPO / GUEST BOOK / YaTeX [Tweet]