CentOS7にFail2ban導入②フィルタ作成方法

Fail2banのフィルター概要
フィルターを作成するにあたり、まず初めに確認が必要なのが、監視対象となるサービスが出力しているログ情報である。Fail2banはログ情報から文字列をパターンマッチして検出対象とする。

一般的なログファイルの保存場所

・messages / secure / maillog / cron / spooler
設定ファイル:/etc/rsyslog.conf
ログ出力先:/var/log/*

・apache
設定ファイル:/etc/httpd/conf/httpd.conf
ログ出力先:/var/log/httpd/*access_log
ログ出力先:/var/log/httpd/*error_log

「/etc/fail2ban/filter.d」には、デフォルトのフィルターが用意されているが、いざ使ってみるとフィルタが機能しない事がままある。その理由として、フィルターのパターンと出力されたログのパターンが一致していない場合だ

当環境のapache-ddosフィルタは以下のように定義している

[Definition]
failregex = ^<HOST> -.*"(GET|POST).*
ignoreregex =

failregex    — 指定ログファイル中に出力されている文字列で、検出対象にしたい文字列を正規表現で記述
ignoreregex —  指定ログファイル中に出力されている文字列で、検出対象にしたくない文字列を正規表現で記述

Apacheアクセスログ(例)
118.126.101.81 – – [29/Oct/2019:06:52:04 +0900] “POST /9678.php HTTP/1.1” 404 206 “-” “Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.91 Safari/537.36”

例のアクセスログを上記フィルタにかけた場合の照合部分は以下3つの条件となる。
青文字部:<HOST>  — クライアントIPアドレス
緑文字部:

赤文字部:“(GET|POST)

これらの文字列が全て照合した場合、「jail.conf」「jail.local」のignoreipで除外対象となっていなければ、findtime内にmaxentryされた数を上回ってログに出力された場合、クライアントIPアドレスをbantimeの間、Firewalldによって接続不可(BAN)となる。

検証環境を整える:
fail2ban.local
loglevel の設定値を「INFO」に設定する。
jail.local
検証端末のIPアドレスが、「ignoreip」に含まれている場合は、BANの挙動確認が必要なため削除する。

Fail2banのフィルター作成
①フィルター定義をする

②フィルターでパターンマッチ出来るか確認する
確認コマンド:fail2ban-regex <ログファイルのパス> <フィルター定義のパス>
失敗例)

# fail2ban-regex /var/log/httpd/ssl_access_log /etc/fail2ban/filter.d/apache-ddos.local
Running tests
=============
Use   failregex filter file : apache-ddos, basedir: /etc/fail2ban
Use      datepattern : Default Detectors
Use         log file : /var/log/httpd/ssl_access_log  
Use         encoding : UTF-8

Results
=======
Failregex: 0 total
Ignoreregex: 0 total
Date template hits:
Lines: 380624 lines, 0 ignored, 0 matched, 380624 missed  ← 全てmissedになっている
[processed in 117.32 sec]

Missed line(s): too many to print.  Use --print-all-missed to print all 380624 lines

成功例)

# fail2ban-regex /var/log/httpd/ssl_access_log /etc/fail2ban/filter.d/apache-ddos.local

Running tests
=============
Use   failregex filter file : apache-ddos, basedir: /etc/fail2ban
Use         log file : /var/log/httpd/ssl_access_log 
Use         encoding : UTF-8

Results
=======
Failregex: 387213 total
|-  #) [# of hits] regular expression
|   1) [387213] ^<HOST> -.*"(GET|POST).*
`-
Ignoreregex: 0 total
Date template hits:
|- [# of hits] date format
|  [392682] Day(?P<_sep>[-/])MON(?P=_sep)ExYear[ :]?24hour:Minute:Second(?:\.Microseconds)?(?: Zone offset)?
`-
Lines: 392682 lines, 0 ignored, 387213 matched, 5469 missed ← 387213パターンマッチしている
[processed in 158.00 sec]

Missed line(s): too many to print.  Use --print-all-missed to print all 5469 lines

③パターンマッチに成功したら、設定を反映してフィルターをロードできるか確認する

# systemctl restart fail2ban
# less +F -S /var/log/fail2ban.log
2020-02-25 15:43:27,257 fail2ban.jail           [25697]: INFO    Jail 'recidive' started
2020-02-25 15:43:27,259 fail2ban.jail           [25697]: INFO    Jail 'apache-ddos' started
ここでエラーが出ていないか確認

④実際にフィルターが正しく動作するかテストする
DDoSのフィルターであれば、対象サイトに対して「F5」キーを連打して確認可能

2020-02-25 15:48:10,398 fail2ban.filter         [26051]: INFO    [apache-ddos] Found 192.168.0.10 - 2020-02-25 15:48:10
2020-02-25 15:48:10,400 fail2ban.filter         [26051]: INFO    [apache-ddos] Found 192.168.0.10 - 2020-02-25 15:48:10
2020-02-25 15:48:10,401 fail2ban.filter         [26051]: INFO    [apache-ddos] Found 192.168.0.10 - 2020-02-25 15:48:10
2020-02-25 15:48:10,570 fail2ban.filter         [26051]: INFO    [apache-ddos] Found 192.168.0.10 - 2020-02-25 15:48:10
2020-02-25 15:48:10,620 fail2ban.actions        [26051]: NOTICE  [apache-ddos] Ban 192.168.100.5
※BANしたログが「NOTICE」として挙がっている

BANしたIPアドレスを確認する方法

# ipset --list
Name: f2b-apache-ddos
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536 timeout 3600
Size in memory: 312
References: 1
Number of entries: 2
Members:
66.249.82.90 timeout 3144   ← 3144秒の間、BANする状態
66.249.82.92 timeout 3144

テスト方法は定義したいフィルターの内容によって様々なので、作成しながら設定確認を繰り返す

⑤BANしたIPアドレスを解除する。「1」という値が返されれば解除完了
# fail2ban-client set <フィルター名> unbanip <解除したいIPアドレス>

# fail2ban-client set apache-ddos unbanip 192.168.100.10
1

「fail2ban.local」「jail.local」の設定値を元に戻す

フィルタを作成するにあたり、一番苦労するのはパターンマッチの正規表現であると思う。ただし、フィルターしたい項目によっては、ログとのパターンマッチ整合率よりも、同じIPアドレスからのアクセス数をカウントする方が大事であったり、特定のキーワードを含む文字列を確実にマッチさせる事が大事な場合など、フィルターによって様々なので注意したい。