mod_evasive (mod_dosevasive)
mod_evasive は Jonathan Zdziarski によって mod_dosevasive として開発され、2002年10月に 1.0.0 がリリースされた。 1
2005年10月の 1.10.1 のリリースで「発音を簡単にするためと皆の舌の寿命を保つため」2に mod_evasive に名称を変更したのを最後に更新されていない。 1
最終リリース日は2005年10月8日であるものの、 EPEL 7 リポジトリにパッケージが2015年6月16日付けでビルドされていたり、セキュリティ監査ツール Lynis に DoS 攻撃対策としてインストールするようサジェストされるなど、依然として知名度が高い。
同様の Apache モジュールとして、元はてな CTO の田中慎司氏による mod_dosdetector や黒沢剛氏による doshelper、David Jao による mod_limitipconn などがある。
evasive
evasive とはあまりなじみのない単語だが、発音は [ɪvéɪsɪv] で「回避的な」という意味。
インストール
yum install epel-release
yum install mod_evasive
systemctl restart httpd
オリジナルの mod_evasive 1.10.1 は Apache 2.2 までしか対応していないが、 EPEL リポジトリのパッケージでは Apache 2.4 に対応されている。
確認
LoadModule evasive20_module modules/mod_evasive24.so
/usr/lib64/httpd 配下の modules/mod_evasive24.so が evasive20_module
としてロードされる。
httpd -M | grep evasive
evasive20_module (shared)
Apache の -M
オプションでモジュールがロードできているか確認できる。 3
設定
設定ファイルは /etc/httpd/conf.d/mod_evasive.conf になる。
デフォルト値
設定項目 | デフォルト値 | 内容 |
---|---|---|
DOSHashTableSize | 3097 | ハッシュテーブルサイズ |
DOSPageCount | 2 | 最大ページヒット数/間隔 |
DOSSiteCount | 50 | 最大サイトヒット数/間隔 |
DOSPageInterval | 1 | page interval |
DOSSiteInterval | 1 | site interval |
DOSBlockingPeriod | 10 | ブロック時間(秒) |
DOSEmailNotify | 通知先メールアドレス | |
DOSSystemCommand | 連動実行コマンド | |
DOSLogDir | /tmp | ログ保存ディレクトリ |
DOSWhitelist | ホワイトリスト(IPアドレス) |
デフォルト値は mod_evasive.c で定義されている。
設定項目
DOSHashTableSize
ハッシュテーブルサイズは各子供のハッシュテーブルのトップレベルノードの数を定義する。
この数を増やすと、レコードに到達するために必要な反復回数を減らすことで高速なパフォーマンスが得られるが、テーブルスペースとしてより多くのメモリを消費する。
ビジー状態の Web サーバを使用している場合は、この値を大きくする必要がある。
指定した値は、自動的に素数リストの次の素数まで階層化される (使用される素数のリストについては mod_evasive.c を参照)。
DOSPageCount
DOSPageInterval
ごとの同じページ(またはURI)に対するリクエスト数の閾値。
その間隔の閾値を超えると、そのクライアントのIPアドレスはブロックリストに追加される。
DOSSiteCount
DOSSiteInterval
ごとに、同じリスナー上の同じクライアントによる、任意のオブジェクトに対するリクエストの合計数の閾値。
その間隔の閾値を超えると、そのクライアントのIPアドレスがブロックリストに追加される。
DOSPageInterval
そのページでの閾値を設定する間隔。デフォルトは1秒。
DOSSiteInterval
そのサイトでの閾値を設定する間隔。デフォルトは1秒。
DOSBlockingPeriod
ブロック期間 (blocking period) とは、クライアントがブロックリストに追加された場合にブロックされる時間(秒)のこと。
この間、クライアントからのそれ以降のリクエストはすべて 403 (Forbidden) となり、タイマーはリセットされる (例: さらに10秒)。
タイマーは後続のリクエストごとにリセットされるので、長いブロック期間を設ける必要はない。DoS 攻撃の場合、このタイマーはリセットされ続ける。
DOSEmailNotify
この値を設定すると、IPアドレスがブラックリストに登録されるたびに、指定したアドレスにメールが送信されるようになる。
/tmp
を利用したロック機構により、連続したメールの送信を防ぐことができる。
注意: mailx の /bin/mail
が必要。
DOSEmailNotify root
メールの件名の変更
DOSEmailNotify "-s \"mod_evasive: Added IP address to the blacklist on ${HOSTNAME}\" root"
デフォルトのメールの件名は「HTTP BLACKLIST <IPアドレス>」で固定だが、 DOSEmailNotify
は "/bin/mail -t %s"
に代入されるためバッドノウハウとして mailx の -s
オプションを追加することで件名を任意のものに変更することができる。ただし、本文にも出力されてしまう。
ちなみにハードコーディングされている -t
オプションは余計なメールヘッダーの破棄を指示するもので To:
の意味ではない。 4
DOSSystemCommand
この値を設定すると、IPアドレスがブラックリストに登録されるたびに、指定されたシステムコマンドが実行される。これは、IPフィルターや他のツールのシステムコールを可能にするために設計されている。
/tmp
を用いたロック機構により、連続したシステムコールを防ぐことができる。
ブラックリストに登録されたIPアドレスを表すには %s
を使用する。
DOSSystemCommand "su - someuser -c '/sbin/... %s ...'"
独自のメールアラートを送信する
DOSEmailNotify
ではメールの本文をコントロールできないが、例えば以下のように指定することで IP アドレスに関する情報を付加して自前でメールを送ることができる。この場合 DOSEmailNotify
を指定する必要はない。
DOSSystemCommand "export IP=%s API=http://ip-api.com/line/${IP} ; /bin/echo -e \"mod_evasive HTTP Blacklisted ${IP}\n\n$(/bin/curl -s ${API})\" | /bin/mail -s \"mod_evasive: Added IP address ${IP} ($(/bin/curl -s ${API}?fields=country)) to the blacklist on ${HOSTNAME}\" root"
DOSLogDir
デフォルトでは /tmp
がロック機構に使用されるが、システムがシェルユーザーに開かれている場合、いくつかのセキュリティ上の問題が発生する。
http://security.lss.hr/index.php?page=details&ID=LSS-2005-01-01
非特権シェルユーザーがいる場合、Apache が実行されているユーザーにのみ書き込み可能なディレクトリを作成し、httpd.conf で設定する。
DOSLogDir "/var/lock/mod_evasive"
保存先として設定ファイルのコメントで例示されている /var/lock
は、 FHS 3.0 でロックファイルの保存先として規定されている。
mkdir --parents --verbose /var/lock/mod_evasive
chown --changes apache:apache /var/lock/mod_evasive
DOSWhitelist
ホワイトリストを使用して特定の範囲の IP に対してモジュールを無効にすることができる。
必要であれば最後の3オクテットまでワイルドカードを使用することができる。
複数の DOSWhitelist
を設定に使用することができる。
動作テスト
mod_evasive の有効性をテストするための小さなスクリプト test.pl が付属している。
perl /usr/share/doc/mod_evasive-1.10.1/test.pl
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
ログ
/var/log/messages
grep 'mod_evasive' /var/log/messages*
/var/log/messages:Jan 1 00:00:00 localhost yum[2705]: Installed: mod_evasive-1.10.1-22.el7.x86_64
/var/log/messages:Jan 1 00:00:00 localhost mod_evasive[12385]: Blacklisting address 192.0.2.1: possible DoS attack.
/var/log/messages:Jan 1 00:00:00 localhost mod_evasive[14201]: Blacklisting address 192.0.2.1: possible DoS attack.
/var/log/messages:Jan 1 00:00:00 localhost mod_evasive[14222]: Blacklisting address 192.0.2.1: possible DoS attack.
/var/log/messages:Jan 1 00:00:00 localhost mod_evasive[14303]: Blacklisting address 192.0.2.1: possible DoS attack.
/var/log/messages:Jan 1 00:00:00 localhost mod_evasive[14325]: Blacklisting address 192.0.2.1: possible DoS attack.
/var/log/messages:Jan 1 00:00:00 localhost mod_evasive[14360]: Blacklisting address 192.0.2.1: possible DoS attack.
/var/log/messages にブロックしたIPアドレスのログが出力される。
Fail2ban
Fail2ban をインストールしている場合、mod_evasive のログでフィルターを作成できる。
# Fail2Ban apache-mod_evasive filter
#
[Definition]
failregex = Blacklisting address <HOST>: possible DoS attack.
ignoreregex =
[apache-mod_evasive]
enabled = true
port = http,https
logpath = %(syslog_local0)s
maxretry = 1
fail2ban-regex /var/log/messages /etc/fail2ban/filter.d/apache-mod_evasive.conf --print-all-matched
fail2ban-client status apache-mod_evasive
syslog_local0
は /etc/fail2ban/paths-common.conf で /var/log/messages
と定義されている。
https://briansnelson.com/Howto_install_mod_evasive_with_fail2ban
-
Version 1.0.0 [20021015] jonz: Initial Release
- mod_evasive/CHANGELOG at master · jzdziarski/mod_evasive ↩ ↩2 -
For the sake of pronunciation's simplicity and to preserve the life of your tongue, mod_dosevasive is now known simply as mod_evasive
- http://www.nuclearelephant.com/projects/dosevasive/ ↩ -
-M Dump a list of loaded Static and Shared Modules.
- httpd(8) ↩ -
-t The message to be sent is expected to contain a message header with
- mailx(1) ↩To:
,Cc:
, orBcc:
fields giving its recipients. Recipients specified on the command line are ignored.