Apache mod_dosdetector で同一IPからのアクセス過多を防いでみる


Apache mod_dosdetectorを使うと、DoS攻撃を検出できます。DoS攻撃を検出した場合、特定の環境変数に値をセットします。
mod_dosdetector自体はリクエストに影響を及ぼしません。

どんな感じなのか試してみました。

前提

  • Debian GNU/Linux 8 (jessie)
  • Apache/2.4.33

環境構築

https://github.com/stanaka/mod_dosdetector をインストールします。

$ apt-get update && apt-get install -y git vim make gcc
$ ln -s /usr/local/apache2/bin/apxs /usr/sbin/apxs
$ git clone https://github.com/stanaka/mod_dosdetector
$ cd mod_dosdetector && make install

Apacheの設定ファイルに下記を追記します。

http.conf
LoadModule dosdetector_module modules/mod_dosdetector.so
LoadModule rewrite_module modules/mod_rewrite.so

DoSDetection on
DoSPeriod 60
DoSThreshold 5
DoSBanPeriod 60

RewriteEngine On
RewriteCond %{ENV:SuspectDoS} =1
RewriteRule .*  - [R=503,L]
ErrorDocument 503 "Hasta la vista, baby."

mod_dosdetectorは、DoSPeriod秒間に(おそらく同一IPアドレスから)DoSThreshold回のリクエストがあった場合、特定の環境変数に1を設定します。
この場合だと、60秒間に5回のアクセスがあった場合にDoSと判断します。

mod_rewriteを使って、セットされた環境変数に応じて挙動を変えることで、DoS攻撃への対策を設定することができます。この場合は503を返すようにしています。

RewriteCondをちゃんと書けば、静的アセットファイルへのアクセスはDoS検知の対象から外したり、正規のクローラからのアクセスは除外したりすることができると思います。

Dockerでの検証環境構築

上述の設定を検証するための環境をDockerで構築します。Apacheの公式イメージを使います。

Dockerfile
FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/

# Installing mod_dosdetector
RUN apt-get update && apt-get install -y git vim make gcc
RUN ln -s /usr/local/apache2/bin/apxs /usr/sbin/apxs

RUN git clone https://github.com/stanaka/mod_dosdetector
RUN cd mod_dosdetector && make install

COPY ./conf/dos-detecting-httpd.conf /usr/local/apache2/conf/httpd.conf
$ docker build --tag my-apache-mitigating-dos --file ./Dockerfile .
$ docker run --name my-apache-mitigating-dos --publish 8081:80 my-apache-mitigating-dos

通常のApacheを8080、DoS DetectorがインストールされたContainerを8081ポートに立てておくと、検証しやすいと思います。

実際に使ったDockerfileやhttp.confはGitHubに上げてあります。
https://github.com/s2terminal/apache_mitigating_dos

検証

Apache Benchで検証してみます。
ab - Apache HTTP server benchmarking tool - Apache HTTP Server Version 2.4

$ ab -n 1000 -c 1000 http://localhost:8080/

デフォルトの場合

Complete requests:      1000
Failed requests:        0

mod_dosdetectorを入れている場合

Complete requests:      1000
Failed requests:        996

ちゃんと5アクセスめ以降がBanされているのが分かります。

なお、これぐらいの設定であれば、手でブラウザリフレッシュを繰り返しても再現することが出来ます。

DoS攻撃と認識された時、ちゃんとmod_rewriteで設定されたコンテンツが返って来ています。

参考