投稿日 2009年11月18日 水曜日 カテゴリ Apache 投稿者 sugimotoComments Off 

sugimotoです。

Apache のDoS対策として mod_dosdetector を使ったのでメモです。

1. mod_dosdetector の設定

インストールの方法などは「dos対策のmod_dosdetectorで特定のContentTypeは、対象外にする方法」というBlogがあったので参考にしました。

設定の書き方もいろいろなサイトに載っていましたが、静的ファイルをアクセス回数の対象外にする方法が正しくないところが多いようです。

静的ファイルの除外は DoSIgnoreContentType ディレクティブで設定しますが、

<IfModule dosdetector_module>
    ... 省略 ...
    DoSIgnoreContentType .(js|png|jpe?g|gif|css|ico)
</IfModule>

のような設定をしてテストしたところ、設定追加前と同じ回数でDoS判定されてしまいました。

このディレクティブは名前の通り Content-Type を設定するのが正しいので、次のように静的ファイルの Content-Type を設定すると正しく認識されました。

<IfModule dosdetector_module>
    ... 省略 ...
    DoSIgnoreContentType ^(image/|application/|text/javascript|text/css)
</IfModule>

2. 利用可能なディレクティブ

利用可能なすべてのディレクティブは以下の通りです。

DoSDetection
DoS判定をする/しないのフラグ(On/Off)
DoSThreshold
判定の閾値 – 注意レベル(回)
DoSHardThreshold
判定の閾値 – 警告レベル(回)
DoSPeriod
DoS判定をする基準時間(秒)
DoSBanPeriod
DoS認定したクライアントを再度開放するまでの時間(秒)
DoSShmemName
クライアントを保存するために保持するシェアードメモリの名前
DoSTableSize
クライアントを保存するためのテーブルのサイズ
DoSIgnoreContentType
アクセス回数としてカウントしないContent-Typeの指定

3. DoS認定されたクライアントの処理を追加する

Apache の設定ファイルに以下の設定を追加して、DoS認定(警告レベル)となったクライアントを「403 (FORBIDDEN)」にします

    RewriteEngine On
    RewriteCond %{ENV:SuspectHardDoS} .+
    RewriteCond %{REMOTE_ADDR} !^192\.168\.1\. # ローカルネットワークからのアクセスは無視
    RewriteCond %{REMOTE_ADDR} !^xxx\.xxx\.xxx\.xxx$ # テストユーザーからのアクセスは無視
    RewriteCond %{HTTP_USER_AGENT} !Googlebot
    RewriteCond %{HTTP_USER_AGENT} !Yahoo
    RewriteRule .* – [F,L]

なお、以下の場合はDoS判定しないように設定しています

  1. 192.168.1.* : ローカルネットワークからのアクセスは監視サーバーなどの自動アクセスがあるため除外
  2. xxx.xxx.xxx.xxx : 自社オフィスなどのIPアドレスからのアクセスはテストなどで頻繁にアクセスすることがあるため、除外しました
  3. Googlebot : Googleはインデックスされないと困るので。。。除外
  4. Yahoo : Yahooもインデックスされないと困るので。。。

4. DoS対策のテスト

設定のテストは Apache Bench を使うと簡単に実行できます。

> ab -n 1000 -c 3 -k http://xxxx.ciklone.com/xxxx
  • -n 1000 : 1000アクセスする負荷テストを実行
  • -c 3 : 同時アクセス数を 3 に設定

5. その他の負荷対策モジュール

最後にその他の負荷対策モジュールについても書いておきます。

ソフトウェアエンジニアのためのバグトラッキングシステム : Ciklone

ソフトウェアエンジニアのためのバグトラッキングシステム

ソフトウェアエンジニアのためのバグトラッキングシステム

投稿日 2009年8月17日 月曜日 カテゴリ Apache, ソフトウェア開発, テスト 投稿者 syojiComments Off 

Webアプリケーションやクライアントサーバ型のシステム開発の中で性能要件を満たすために負荷試験やロード試験といわれる工程がある。

重要な工程として考えているが、スケジュールの厳しいプロジェクトなどでは後回しにされることがあった。 特に、開発が遅れている場合、要件を満たすための開発が重視されることは理解しているが、負荷試験を実施することは同じくらい大切な工程である。試験で起こることは当然、本番環境でも起こり、あとで痛い目をみないためにも必須の工程である。

負荷試験を設計する上での考え方をまとめてみたいと思う。 以下のサイトが参考になる。

負荷試験とは

構築するシステムがどの程度の負荷に耐えられるかを測定し、システムの信頼性と耐用範囲を明確にする。ウェブアプリケーションの場合、同時アクセスユーザ数をどれだけ処理出来るか、閾値を越えた場合のシステムの振る舞いを検証する試験である。

負荷試験で使われる試験環境は本番環境と同一であることが望ましい。しかし、実際には機器調達が難しいことが多い(例えば、想定している分だけのクライアントマシンを用意する等)。機器が準備できない場合、サーバに負荷を発生させるツール等を使用し、高負荷、過負荷を与え、システムの振舞いについて検証する。

負荷試験の計画(設計)に必要なこと 負荷試験を計画するときに最低限、考えなければいけないことを説明したい。

前提条件

試験を実施するときの試験環境について、サーバの役割、台数、クライアント数、負荷をかける時間等の環境について条件を明確化しておく必要がある。

監視ポイント

例えば、Webアプリケーションの場合、クライアントがアクセスしトップページが表示されるまでの時間。など要件を満たすために必要な監視ポイントを明確にしておく必要がある。サーバサイドではDBに対する大量のI/O(書込、読み出し等)がそれにあたると思われる。

目的と対象範囲

負荷試験でクリアしなければいけない要件、ユーザ数などの試験の目的と対象範囲/ハード情報(各サーバのOS情報/CPU/DISK IO/MEMORY/NETWORK)、過負荷時の測定範囲を明確にする。

性能要件(目標値)

想定されるクライアント数から性能要件を予測し、定義する。レスポンス時間等の試験項目から測定可能な数値を予測する。 例えば年に1度のみ過負荷が発生するといった事象に合わせてシステムを組んだ場合、性能要件は十分であるが、コスト面で満足するものにはならない場合がある。そのため、要件にあった目標値を設定することは重要である。

想定シナリオ

構築するシステムの利用シーンを考えたシナリオを作成する。試験実施はそのシナリオに沿って行われるべきである。 例えば、メールクライアントの場合、社員が出社する時間(09:00頃)が大量のアクセスが発生する、など。その利用シーンをシナリオに組み込む。

実施方法

市販のツールを利用する、自作ツールを利用する、など目標値を達成するためには過負荷状態を作らなければいけない。疑似的に過負荷状態を作り出す必要がある。Webアプリケーションに限定されるが無料ですばらしいツールが多く提供されている。

試験結果

負荷試験計画時の「目的と対象範囲」を達成したかどうか、 実測値が予測値より悪い場合や、目標値ギリギリの場合、チューニングを実施することになる。 問題点の原因については、計測データなどを使って

  • トランザクション数/クライアント数が増加しているとき、スループットの増加傾向が変化した時点
  • レスポンスタイムが急速に遅くなった点

分析するポイントとして、システムの測定値が急激に変化したとき、関連するモジュールがボトルネックと考えられる。 チューニングについては、そのようなボトルネックと予測されるモジュールから優先的に検証する必要がある。

以上のような点について、負荷試験の計画フェーズで考えておけば良いのではないかと考える。 負荷試験が実施されるのはシステムが構築され、結合試験も終わった以降になる。一番忙しいフェーズであるが 負荷試験の重要性を説明し、しっかりと計画をして実施していきたいと思う。

投稿日 2008年10月15日 水曜日 カテゴリ pound, proxy 投稿者 sugimotoコメント(0) » 

とあるプロジェクトで、オープンソースのプロキシサーバ「pound」を使いました。

その中で、気になったことなどをメモしておきます。

設定は簡単

特にSSLの設定は非常に楽です。 設定ファイルの書き方も明快でわかりやすいのでメンテナンス上も良いです。

バックエンドのWebサーバーはクライアントIPアドレスが変わる

バックエンドではクライアントIPアドレスがプロキシサーバーのアドレスとなるため、バックエンドのウェブサーバー(今回はapache)でログのフォーマットを修正する必要がありました。 X-Forwarded-For にクライアントIPアドレスは渡されるため、Webサーバーではこの値をログするように変更しました。

ログの出力方法によってパフォーマンスに影響がある

Poundのログはdefaultでsyslogに出力することができます。ただ、この設定をするとパフォーマンスが目に見えて悪くなりました。 LogFacilityを – に設定するとログは標準出力なります。 1. ログ出力なし 2. 標準出力 3. syslogに出力 上記の3つの設定では3番の方法で極端にパフォーマンスの低下が見られました。

そのため、今回はPoundのログは標準出力にしました。

クライアントIPアドレスでのフィルタはできない

プロキシサーバーを使う前は、特定のIPアドレスに対してapacheでDenyの設定をしていましたが、この方法は使えなくなりました。 – iptables で設定 – アプリケーションで設定

と考えられましたが、今回はアプリケーションに実装する予定です。

設定ファイルのリロードはできない

設定ファイルを書き換えた場合、反映するためにはreload ではなく、 restartが必要となります。(reloadは無い) 今回のシステムでは瞬間的な停止は許容範囲のため、そのまま運用しています。

導入までの手間は非常に少なかったのですが、細かい設定ができないのでした。

投稿日 2008年3月4日 火曜日 カテゴリ couchdb, lighttpd 投稿者 sugimotoComments Off 

はじめまして、sugimotoです。

このBlogの初めての記事になります。 何を書こうか迷ったのですが、今回は最近使っているCouchDBをlighttpdをproxy serverとして設定したときの手順のメモを書きます。 Apache をproxyにした場合の設定はCouchDBのインストール方法にあります。

自分の環境はDebianだったので、Debianでの設定となります。

1. lighttpdのインストール

インストールチュートリアルにある通り、yum, apt-getのようなパッケージマネージャでインストールできます。

日本語のチュートリアルも検索するとたくさんあり、参考になります。

インストールが終わったら、http://localhost/ でlighttpdのトップページが見えるか確認します。

2. CouchDBのインストール

こちらも、チュートリアルにあるとおり apt-get できます。 インストールすると、全てのファイルが /usr/local/ 以下にできてしまうので、log を /var/log/ に移したいときは設定を変更します。

CouchDB用のlog directoryを作成

> sudo mkdir /var/log/couchdb
> chown couchdb /var/log/couchdb

couch_httpd.conf を変更

ErrorLog /var/log/couchdb/http_error.log  # 作成したdirectoryに変更
TransferLog /var/log/couchdb/http_access.log # 作成したdirectoryに変更

couch.ini を変更

LogFile=/var/log/couchdb/couch.log    ; 作成したdirectoryに変更

CouchDBがインストールできたら、トップページ画面 http://localhost:5984/ にアクセスしてインストールを確認します。

{"couchdb": "Welcome", "version": "0.7.2"}

とJSON形式のwelcomeメッセージとversionが表示されました。

3. データベースの作成

今回設定するデータベースを作成します。

ToDoリストを作ろうと思ったので、管理画面 http://localhost:5984/_utils/ から todo というデータベースを作りました。

4. lighttpd.conf の設定

http://localhost/todo/ でCouchDBにアクセスするため、lighttpd.conf でproxyの設定をします。 xxx.xxx.xxx.xxx はサーバのIPアドレスです

$HTTP["url"] =~ "^/todo/" {
    proxy.server = ( "" => (( 
        "host" => "xxx.xxx.xxx.xxx", 
        "port" => 5984 )))
}

5. 確認

最後に http://localhost/todo/ を表示して、設定の確認。

{"db_name": "todo", "doc_count":0, "update_seq":0}

こちらもJSON形式でデータが表示されました。

参考リンク: