ApacheをDoS攻撃から守る方法
DoS攻撃(サービス不能攻撃)は、その名の通り、「サービスを利用できない状態にする攻撃」です。ここでは、Apache HTTP Server(Apache,httpd) を DoS攻撃 から守る方法について説明します。
読み方
- Apache HTTP Server
- あぱっち えいち てぃーてぃーぴー さーば
- DoS攻撃
- どすこうげき, でぃーおーえす こうげき
目次
概要
DoS攻撃 を受けると、サービスが利用できない状態になります。 ここでは、サービスを停止しないために、どのような対策をすべきなのか、というのを紹介します。しかしながら、おそらく、完璧な方法はありません。
サービスが止まって何が悪いのか?
DoS攻撃 を受けると、サービスが利用できない状態になります。
サービスが利用できない、とは、「サービスを利用したいお客様がサービスを利用できない」という状態のことです。 たとえば、ショッピングサイトを運営していて、DoS攻撃を受けたとき、ショッピングサイトでお買い物ができない状態がおきる、ということです。 つまり、「お買い物ができない」ということは、お店の売上が上がらず、止まったままになる、ということになります。 もし、ウェブの事業だけが収益源の場合、お金を稼ぐことができなくなってしまう、ということです。
オンラインゲームのサイトが「悪い人たち」に目をつけられて、「サービスを止められたくなかったら、お金を払え」とゆすられたという話があります。オンラインゲームサイトは、ゲームサイトに接続ができなくなってしまうと、運営が成り立たなくなってしまいます。
DoS攻撃を受けて、サービスが停止すると、利益を上げることが困難になります。だから、攻撃に対して、耐性を上げておく必要があるということになります。
DoS攻撃
サービスが DoS 状態になってしまう攻撃パターンがいくつかあります。
- 脆弱性をついた攻撃
- 大量のコネクション
- Slow HTTP 攻撃
- Slow HTTP リクエスト (ヘッダ、POST 等)
- Slow HTTP Read 攻撃
脆弱性を利用した攻撃については、脆弱性をしっかり修正すれば良いため、ここでは、割愛します。セキュリティアップデートをするようにして下さい。
どう防ぐのか?
基本的には、リソースのマネジメントを厳しくやる、ということになります。ユーザには、最低限のリソース・機能しか提供しない、というのを目指すことが対策になります。 リソースが枯渇する問題を解決するために、枯渇する要因になる要素を取り除かなければなりません。
- HTTPメソッドを限定する
- 転送量を限定する
- 接続数を限定する
- 接続時間を限定する
制限をすれば良い、と書きましたが、必ずしも、すべてのエントリーポイントで制限を厳しくできるかというとそうではないかもしれません。 たとえば、ショッピングサイトの決済の画面を厳しくしてしまうと、決済の処理の画面遷移がうまくできなくなる、といったようなことも起きるかもしれません。
HTTPメソッドを限定する
いらないメソッドを許す必要はありません。 もし、GET メソッドしか使う必要がないなら、POSTのリクエストを受け付ける必要はありません。 POSTのリクエストであるかどうかは、HTTPリクエストの一番最初の段階でわかるため、POSTのリクエストを処理するつもりがないなら、その時点で、接続を終了させることができます。POSTリクエストをうけないなら、POSTリクエストを最後まで受け取る必要がありません。
URLごと(エントリーポイントごと)に、サポートしなければならないHTTPメソッドが決めることができます。
転送量を限定する
ヘッダやメッセージボディをリーズナブルな長さに限定します。 URLごとに、適切なサイズがあるはずです。
接続数を限定する
Apache に大量にコネクションをはられてしまうと、ほかのクライアントが Apache に接続できなくなってしまいます。 そのため、クライアントごとに同時に接続する数を限定すべきです。
簡単な方法としては、IPアドレスベースで、接続数を限定する方法です。 ただし、この方法は、NATやプロキシを利用した接続の制限で問題になりやすい方法です。企業や学校などには、巨大なNATやプロキシが存在します。つまり、単純にIPアドレスだけで接続を制限するのは難しいです。 一方で、接続元がNATであるかどうかは、判断が困難であるため、単位時間あたりの接続数をある程度、多めに許可するしかありません。
接続時間を限定する
接続時間をできるだけ短くすることが、DoS対策の1つの方法です。 つまり、接続に対して、タイムアウトを設定します。
たとえば、どういった時間があるか、という例を以下に挙げます。
- リクエストが到着するまでの時間
- レスポンスを受け取り終わるまでの時間
リクエストを全部受け取るまでにかかる時間や、レスポンスを受け取り終わる時間は、クライアントの能力だけではなく、クライアントとサーバの間にあるネットワークにも大きく影響を受けます。 たとえば、
- 混雑しているネットワーク
- 遅いネットワーク
- ネットワークが遠い
があります。
あまり厳しくしすぎると、正規のスローなコネクションをドロップさせてしまうことになります。
混雑しているネットワークというのは、お昼時や帰宅ラッシュなどの時間帯では、スマホでニュースを見ると、なかなか表示されない、ということがあるかと思います。 学校や企業の無線LANや携帯キャリアのネットワークが混雑する時間帯が存在します。
遅いネットワークというのは、モバイルデータ通信が上げられます。日本は、それなりに、スマホの通信が速い国と言われていますが、それでも、我々は遅いと感じているでしょう。
サーバとクライアントの距離が遠ければ、それだけ、通信には時間がかかります。
対策
OS/システムコールの機能
Unix の場合は、 OS の機能として、Accept Filter/Accept Dataが利用できるケースがあります。FreeBSD の場合は、Accept Filter が利用できます。FreeBSD の Accept Filter (accept http) では、GETのHTTPリクエストのデータが届くまで、accept システムコールが Apache (httpd) のプログラムに返らないようになります。HTTPリクエストが到達してから accept が返るため、Apache は一回の read システムコールの呼び出しで、リクエストを読みだすことができ、OSとプロセスのスイッチングを減らすことができます。また、リクエスト待ちになってしまう apache のプロセスを減らすことができます。ただし、HTTPのみに限定され、HTTPS の場合は、通信が暗号化されているため、カーネル がHTTPリクエスト全体をバッファリングする、といった処理ができません。通信が暗号化されているため、何のリクエストなのか判断ができないためです。
Linuxの場合は、FreeBSD とは異なり、Accept Filter は、accept がデータの到達を保証するだけになり、HTTPリクエスト全体が到達することは保証できません。
プロセス数を増やす
これは、力技で、付け焼き刃的なものでしかありません。良い方法ではありません。
Apache のプロセス数を増やすことで、たくさんのクライアントを同時にさばくことができます。 しかし、メモリを多く消費し、ネットワークが詰まりやすくなります。また、同時に処理するクライアントが増えれば、それだけCPUも消費するため、結果的に、スループットが落ちる、といったことも考えられます。データベースへの同時問い合わせが増えれば、データベースがボトルネックになってしまうことも考えられます。
どれだけクライアントを増やしても良いのかは、アプリケーションやデータベースの作りによります。 適切なプロセス数をベンチマークで、はじき出す必要があります。
reqtimeout_module
FreeBSD の場合、設定ファイルのディレクトリの extra/httpd-default.conf に設定の例があります。
<IfModule reqtimeout_module> RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500 </IfModule>
上記は、以下の意味になります。
- ヘッダの最初のバイトは、20秒以内、それ以降は、500byte/secで40秒まで待つ
- ボディは20秒以内
上記の設定は、かなり緩やかな設定と言わざる得ません。 DoS対策という目的であれば、もっと短く設定すべきです。
mod_security
- 接続数を制限
- ボディサイズを制限
mod_qos
テスト
テストツール
関連項目
ツイート