Apache2でmod_limitipconnを使う方法

初出:2004/11/11
更新:2005/01/07

1.紹介と仕組み

 ダウンロードツールを使って、多重ダウンロードや分割ダウンロードが行なわれることは非常に迷惑なことだ。サーバー管理者は、ネットワーク帯域の圧迫やハードディスクへの負荷増大に悩まされることになる。
 そこで、この対策のために有用なものが「mod_limitipconn」だ。

 mod_limitipconnは、Apache用のモジュールとして動き、1つのIPアドレスが接続できる最大値を制限することが出来る。例えば最大値を2とすれば、1つのIPアドレスから同時に並行してダウンロードできる数は最大2つとなる。
 最大数以内ならば、mod_limitipconnは通信をスルーしてサーバー側に渡す。つまり通常と何ら変わりない処理となる。一方、最大数を超えた場合、mod_limitipconnは、HTTPステータスコード「503 Server Temporary Unavailable」を返すようサーバーに指示する。この結果、データは送信されずにダウンロードは失敗する。

 肝心の効果のほどだが、それなりにディスクアクセスの量は減るようだ。実のところ、完璧に多重アクセスを防いでくれるわけではない。アクセスログを見ると明らかに多重アクセスにもかかわらず、素通りして200/206を返しているパターンがところどころに見受けられる。そのパターンは1秒間に数回のアクセスを行うものだ。どうやらあまりにも速い多重アクセスだと防ぎきることが出来ず、素通りさせてしまうようである。
 mod_limitipconnは、多重か否かの判定を、現在接続中のIPアドレス一覧をApacheから取得し、その数を調べることで行っているが、おそらく取得するまでの時間に若干のタイムラグがあるのだろう。
 つまり「効果てきめん」とまでは言えないが、導入するとしないとでは負荷にそれなりに違いが見受けられるので、やってみる価値はあると思う。

2.インストールと設定

 では早速インストールをしてみよう。想定するソフトウェア環境は以下の通り。

OSRedHat Linux9
HTTPサーバーApache2.x

 OSについては筆者が動作確認したものを載せた。おそらくApacheが動くのならば、他のLinux系・BSD系でも問題ないだろう。
 Apacheのバージョンについては、2.xを使用する。1.xは取り上げない。

<Apacheの設定確認>

 まずは、Apacheの設定を確認してインストール可能な状態か調べる。
 mod_limitipconnを使用するためには、
  1. DSOが組み込まれていること
  2. mod_statusが組み込まれていること
が必要条件となる。
 これらの条件を調べるには、
# apachectl -l
として、「mod_so.c」と「mod_status.c」が表示されればOKである。
 mod_so.cが表示されない場合は、「--enable-so」オプションを付けてconfigureしたApacheを再インストールすることになる。
# ./configure --enable-so
# make install

<インストール>

#作業はrootになって行う。
  1. mod_limitipconn.c - Apache 2.0 port」から、「tar.gz package」をダウンロードする。
    # wget http://dominia.org/djao/limit/mod_limitipconn-0.22.tar.gz
  2. 展開する。
    # tar zxvf mod_limitipconn-0.22.tar.gz
  3. ディレクトリを移動する。
    # cd mod_limitipconn-0.22
  4. メイクしてインストールする
    # make install
 以上でインストールは終了。

<設定>

#設定は全てhttpd.confで行う。
  1. httpd.confを開く
  2. mod_limitipconnが組み込まれているか確認する
    「LoadModule」の行が書き込まれていればOK。もし「AddModule」の行があった場合は、コメントアウトしておく。
    # Example:
    # LoadModule foo_module modules/mod_foo.so
    LoadModule limitipconn_module modules/mod_limitipconn.so
    #AddModule mod_limitipconn.c
  3. mod_statusの機能を有効にする
    # ExtendedStatus controls whether Apache will generate "full" status
    # information (ExtendedStatus On) or just basic information (ExtendedStatus
    # Off) when the "server-status" handler is called. The default is Off.
    #
    ExtendedStatus On
  4. mod_limitipconnの設定を行う
    <Directory "/">
    #いろいろ
    </Directory>

    # mod_limitipconn Setting
    <IfModule mod_limitipconn.c>
      <Location /bin/data>
        MaxConnPerIP 2
      </Location>
    </IfModule>
    IfModuleディレクティブ内に設定を記述する。ディレクティブの記述場所はどこでもよいのだが、精神衛生上「<Directory "/">」ディレクティブの下に置いた。
    この設定では、例えば「http://www.example.com/bin/data/」というURLにアクセスしてきた場合、「/bin/data」内にあるファイルに対して、最大数2個までにダウンロードを制限できることになる。ファイルの種類は問わない。
  5. Apacheを起動する
  6. 正しく動作するかテストする。
    Apacheには「ApacheBench」というベンチマークソフトが付属しているので、それを使って行う。
    # ab -n 10 -c 10 http://localhost/bin/data/test.jpg
    これを実行すると、test.jpgに対して10個の同時リクエストを行う。
  7. ログを確認する。
    tailコマンドで、access_logの最後から30行を表示する。
    # tail -n30 access_log
    10個中8個が503で2個が200になっていれば成功。

3.設定の詳細

 「<IfModule mod_limitipconn.c>」ディレクティブでは、以下の設定をすることができる。

 ※NoIPLimit/OnlyIPLimitを指定せず、MaxConnPerIPのみ設定した場合は、ファイルの種類を問わずすべて拒否することになる。

4.拒否するときに404を返す改造方法

 通常の仕様では、拒否するときに503を返す。503は「サーバーが一時的に利用できない」という意味であり、ファイル自体は存在する(かもしれない)。そのため、一部のダウンロードソフトは503が返ってきたとしても動作を終了しようとせず、延々とリトライを繰り返すのだ。
 これをやめさせるには、「ファイルはない、あきらめろ」と返答する必要がある。そのためには、HTTPステータスコード「404 Not Found」を返すのが効果的である。

 残念ながらhttp.confの設定では行うことが出来ないため、ソースコードを直接いじって改造する必要がある。だが安心してよい。修正個所はたったの1つだけだ。設定ファイルをいじる感覚で誰にでも出来る。

<改造手順>

  1. 「mod_limitipconn-0.22.tar.gz」を展開する。おそらく以前に展開済みだろうからそれを使ってもよい。
  2. 「mod_limitipconn-0.22」ディレクトリへ移動する。
  3. lsすると「mod_limitipconn.c」というファイルがあるはずだ。
    #ls
    mod_limitipconn.c
  4. それをエディタで開いて、「HTTP_SERVICE_UNAVAILABLE」という単語で検索する(viならばスラッシュで検索モードに入る「/HTTP_SERVICE_UNAVAILABLE」)。
  5. 以下のようなコードが見つかるはずだ。
          /* return 503 */
          return HTTP_SERVICE_UNAVAILABLE;
        } else {
    return OK;
        }
  6. この個所を以下のように変える。
          /* return 503 */
          //return HTTP_SERVICE_UNAVAILABLE;
          /* return 404 */
          return HTTP_NOT_FOUND;
        } else {
    return OK;
        }
    単に「HTTP_SERVICE_UNAVAILABLE」を「HTTP_NOT_FOUND」に変えるだけだ。これで404を返すようになる。
    ※注意:「HTTP_NOT_FOUND」のうしろに必ずセミコロン(;)を付けるのを忘れずに。
    なお、別のステータスコードを返したい場合は、定義表を参照されたい。
  7. 修正したら、makeしてモジュールを作成する。
  8. 出来たモジュールは「.libs」ディレクトリにあるので、それをApacheモジュールの入っているディレクトリへコピーする。
    ※Apacheはあらかじめ停止しておくこと。
    #cp .libs/mod_limitipconn.so /usr/local/apache2/modules
    モジュールへのパスは環境に合わせて適宜変更されたい。

  9. Apacheを起動し、abでテストしてみる。404が返ってきたら成功。

Copyright © 2004 H'Imagine.
All rights reserved.