サーバ管理 - Apache:多重セッション防止
(ダウンロード支援ソフトはじき
作業メモ。
はじめに
なぜダウンロード支援ソフトをはじく必要があるのかを説明しておく。ダウンロード支援ソフトは1つのファイルに多重セッションを張ることで転送パフォーマンスを稼いでいるが(これを投網と呼ぶ)、 サーバには同時接続上限(MaxConnection)が設定されており、低速回線の訪問者に投網をやられるとなかなかコネクションが開放されず、結果的に混雑が解消されなくなってしまう。他の訪問者のみならず鯖管理側としても実に不愉快な状況であるので、なんとかせねばならない。
なお、サーバはApache2系が前提(うちがそうだから)。
セッションとコネクションの違いはOSIでいうところのどの階層にあたるか、ということ。セッションは文字通りセッション層、コネクションはトランスポート層での概念/機能である(前者がアプリケーションレベルの接続、後者がネットワークレベルでの接続と考えてもよい)。問題になってくるのはひとつのコネクション上に複数のセッションを張るのではなく、セッションごとにコネクションを確立しようとするからである(セッションよりもコネクションのほうがリソースの制約は厳しい)。なお投網はむしろ複数のファイルに対して同時にセッションを張ることをそう呼ぶケースが多い。特にP2Pなんかで。
ケーススタディ1:Cookieを利用する
───ある技術者の備忘録を参考にしてみる。
氏も指摘しているように、User-Agent偽装など簡単であるから、環境変数ではじく方法はそれほど効果があるようには思えない。またRefererを見る方法は、ノートンのセキュリティソフトを使っている訪問者を弾いてしまう可能性
(内部串のせいか?)があるらしい。そこで氏が提案しているのはCookieを使う方法。要点は直接ダウンロードの制限である。
まずHTMLファイルにクッキーを仕込む。
<meta http-equiv="Set-Cookie" content="access=true">
続いて制限対象のディレクトリに対してアクセス設定を行う。
<FilesMatch ".(jpg|jpeg|wmv|avi|mp3|mp4|scr|exe|lzh|zip)$">
SetEnvIf Cookie "^access=" accessed
Order deny,allow
Deny from all
Allow from env=accessed
</FilesMatch>
これによりクッキーを仕込んだページを経由していないアクセスは拒否される、という仕組み。この方法のメリットは仕込みが容易であること、.htaccessが許可されていればレンタルサーバなどでも可能であること。
ただ、サイトの構成によってはクッキーを仕込むページが膨大な量となる可能性があり、サイト設計の見直しが必要になるかもしれない。
ケーススタディ2:同時接続IPの制限を行う
異常な連続IPの接続を拒否してしまう方法。これが最も理想的であるが、サーバにモジュールを組み込むかPHPなどで専用にプログラムを起こす必要があるため実装難易度は多少高め。またモジュールによってはApacheのバージョンに対応していないものもある。
有名どころとしてはmod_bwshare及びmod_limitipconnがある。
mod_limitipconn
多重セッション張られて困ってる人に最適な、同一IPからの最大接続数の制限を行うモジュール。いろんな条件で指定できる。記述はconfだけでなく.htaccessでも可能。
組み込みにはDSOを使うのがよいだろう。
ソースの入手とコンパイル
CentOSの場合、標準ではapxsが入ってないのであらかじめyumでhttpd-develを追加しておく。mod_limitipconn本体はDavid Jaoさん宅(リンク先はApache1.3系向けなので注意)にある。
# wget http://dominia.org/djao/limit/mod_limitipconn-0.22.tar.gz # gunzip -c mod_limitipconn-0.22.tar.gz | xvf - # cd mod_limitipconn-0.22 # make install
インストールできない場合axpsとapachectlのパスがおかしいのだろう。Makefileを環境に応じて適当に修正してからビルドする。
APXS=/usr/sbin/apxs APACHECTL=/usr/sbin/apachectl
組み込みが終わったらhttpd.confでモジュールを有効にする。またExtendedStatusがOnになっている必要があるのでこれもチェック。
# vi /etc/httpd/conf/httpd/conf LoadModule limitipconn_module /usr/lib/httpd/modules/mod_limitipconn.so ExtendedStatus On
パッケージで導入
デビッドさんはCentOS向けRPMパッケージも用意しているので、これを使ったほうが楽だろう。
# wget http://dominia.org/djao/limit/mod_limitipconn-0.23-1.el5.i386.rpm # rpm -ivh mod_limitipconn-0.23-1.el5.i386.rpm
/etc/httpd/conf.d/limitipconn.conf が追加されたコンフィグレーションファイル、あとの設定はソースからビルドと同じ。
設定
細かい条件はIfModuleで指定する。まずドキュメントルート以下、MIMEタイプがtextを除くすべてのファイルに対して同時接続数を4に制限。
<IfModule mod_limitipconn.c> <Location /> MaxConnPerIP 4 NoIPLimit text/* </Location> </IfModule>
以下、ファイルタイプzip、mpg/mpeg、wmv、mp3に対して最大接続数を2に制限。
<IfModule mod_limitipconn.c> <FilesMatch "\.(zip|mp?g|wmv|mp3)$"> MaxConnPerIP 2 </FilesMatch> </IfModule>
Flashで使ってるFLVやMP4を制限してしまうと利便性が落ちそうなので今回は含めないことにした。そのかわり、この手のファイルをあぷろだにうpする場合はZIPで固めてからにする。
実際に機能しているかどうかはServer-Statusなどで確認してみる。なお上限を超えたリクエストに対してはステータスコード503 Service Temporarily Unavailableを返すので、好みでカスタムエラーでも表示してやるとよい。503以外のステータスを返すにはソースをいじる必要があるので(mod_limitipconn.cのreturn HTTP_SERVICE_UNAVAILABLを変える)、そういう人はapxs経由で入れるとかSRPMから起こすとか工夫しる。
…俺の設定がおかしいのか、mod_uploaderに対してはどうもうまく機能しない。ただmod_uploaderにはもともと同時接続数を制御する機能がある(デフォルトで3かな)のでそっちを使えばよさそう。つかあぷろだ以外では多重セッションで困ってるわけではないので、別にmod_limitipconn入れる必要はなかったというか。まー何事も経験よ。
H'Imagine氏の記事を読む感じでは、ごく短時間の多重アクセスには対処しきれない場合があるようなので経過観測はしたほうがよさげ。
mod_bw
帯域制御を行うモジュール。オレの考えとしては接続数を制限したら必要ない。むしろとっとと落として待ち行列の渋滞を解消してもらったほうがよい。これが必要となる代表的なケースは、月額見放題の動画配信とかやってるサービスだろう。