CentOS 7上のWordPressにfail2banをインストールして、access.log内の不正アクセスや、不正中継のアクセスをbanしてみました。
インストール
epelのリポジトリからインストールします。
バージョンは、0.9.6-3.el7です。
yum install -y fail2ban-all
fail2banの設定ファイル
設定ファイルは /etc/fail2ban/
下にあります。
この階層にある *.conf
は編集しないようにしましょう。 バージョンアップすると、新しいconfファイルに差し替えられるので、設定が消えて痛い目にあいます。
設定を変更する場合には、action.d
filter.d
jail.d
fail2ban.d
の各種ディレクトリ下に、対応するファイルをコピーもしくは新規に作成します。
尚、action.d
filter.d
下にも各種ファイルがあります。 これも差し替え対象ファイルなので、編集する場合にはコピーして編集しましょう。
# ls -l
合計 68
drwxr-xr-x 2 root root 4096 3月 2 09:28 action.d <----- banの実行ファイル群があるディレクトリ
-rw-r--r-- 1 root root 2328 12月 9 23:36 fail2ban.conf <----- fail2banの設定ファイル
drwxr-xr-x 2 root root 6 2月 16 03:37 fail2ban.d <----- fail2banの設定ファイル用ディレクトリ
drwxr-xr-x 3 root root 4096 3月 23 10:37 filter.d <----- ban対象のログ検知用ファイル群があるディレクトリ
-rw-r--r-- 1 root root 21284 2月 16 03:37 jail.conf <----- 監視設定ファイル
drwxr-xr-x 2 root root 59 3月 23 10:25 jail.d <----- 監視設定ファイル用ディレクトリ
-rw-r--r-- 1 root root 2375 12月 9 23:36 paths-common.conf <--以下、各ディストリビューション用のパス定義ファイル
-rw-r--r-- 1 root root 642 12月 9 23:36 paths-debian.conf
-rw-r--r-- 1 root root 1070 12月 9 23:36 paths-fedora.conf
-rw-r--r-- 1 root root 1174 12月 9 23:36 paths-freebsd.conf
-rw-r--r-- 1 root root 975 12月 9 23:36 paths-opensuse.conf
-rw-r--r-- 1 root root 290 12月 9 23:36 paths-osx.conf
fail2ban自体の設定ファイル(fail2ban.conf)は、特に変更しなくても動くので、ここでは特にしません。
WordPress用のfilterを設定する
検知したいログ
# wp-login.phpにアクセスしているログ
177 - 80.134.73.156 - - [23/Mar/2017:04:11:19 +0900] "POST /wp-login.php HTTP/1.1" 301 246 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
# 25番ポートで中継しようとアクセスしているログ(301エラーになっているけれども、しつこいのでban対象)
123 - 1.162.172.194 - - [23/Mar/2017:06:07:35 +0900] "CONNECT mx-tw.mail.gm0.yahoodns.net:25 HTTP/1.0" 301 234 "-" "-"
# wp-login.phpにアクセスしているログ
91.200.12.15 - - [23/Mar/2017:05:50:18 +0900] "POST /wp-login.php HTTP/1.1" 200 4796 "https://xxx.xxx.co.jp/wp-login.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; 125LA; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)"
検知用ファイル作成と設定
WordPress専用の検知設定ファイルは無いので、filter.d
下に新規に作成します。
拡張子は、.conf
.local
のいずれかにします。
vi /etc/fail2ban/filter.d/wplogin.local
failregexに、正規表現で検知したいログを記載します。 <HOST>
はIPアドレスに値します。
[Definition]
failregex = ^\d{1,5} - <HOST> -.*"POST /wp-login.php HTTP.*$
^<HOST> -.*"POST /wp-login.php HTTP.*$
^\d{1,5} - <HOST> -.*\"CONNECT [\w/.-]+:25 HTTP.*$
ignoreregex =
- failregex: 検知するログを正規表現で記載します。
- ignoreregex: 検知対象外のログを正規表現で記載します。
フィルタリングの確認
対象のログがあるファイルで検知できるか、fail2ban-regexコマンドで確認します。
# fail2ban-regex access.logのパス /etc/fail2ban/filter.d/wplogin.local --print-all-matched
実行すると、このようになります。 Matched line(s)のセクションに対象のログの行が出ていれば成功です。
# fail2ban-regex access.logのパス /etc/fail2ban/filter.d/wplogin.local --print-all-matched
Running tests
=============
Use failregex filter file : wplogin, basedir: /etc/fail2ban
Use log file : access.logのパス
Use encoding : UTF-8
Results
=======
Failregex: 39 total
|- #) [# of hits] regular expression
| 1) [6] ^\d{1,5} - <HOST> -.*"POST /wp-login.php HTTP.*$
| 2) [33] ^\d{1,5} - <HOST> -.*\"CONNECT [\w/.-]+:25 HTTP.*$
`-
Ignoreregex: 0 total
Date template hits:
|- [# of hits] date format
| [79] Day(?P<_sep>[-/])MON(?P=_sep)Year[ :]?24hour:Minute:Second(?:\.Microseconds)?(?: Zone offset)?
`-
Lines: 79 lines, 0 ignored, 39 matched, 40 missed
[processed in 0.01 sec]
|- Matched line(s):
| 171 - 1.162.172.194 - - [23/Mar/2017:03:36:38 +0900] "CONNECT mx-tw.mail.gm0.yahoodns.net:25 HTTP/1.0" 301 234 "-" "-"
| 204 - 62.197.243.18 - - [23/Mar/2017:03:43:27 +0900] "POST /wp-login.php HTTP/1.1" 301 246 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
| 150 - 1.162.172.194 - - [23/Mar/2017:03:55:25 +0900] "CONNECT mx-tw.mail.gm0.yahoodns.net:25 HTTP/1.0" 301 234 "-" "-"
| 177 - 80.134.73.156 - - [23/Mar/2017:04:11:19 +0900] "POST /wp-login.php HTTP/1.1" 301 246 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
| 93 - 1.162.172.194 - - [23/Mar/2017:04:14:10 +0900] "CONNECT mx-tw.mail.gm0.yahoodns.net:25 HTTP/1.0" 301 234 "-" "-"
| 163 - 62.123.1.89 - - [23/Mar/2017:04:31:08 +0900] "POST /wp-login.php HTTP/1.1" 301 246 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
[省略]
`-
Missed line(s): too many to print. Use --print-all-missed to print all 40 lines
監視設定
/etc/fail2ban/jail.confに個別の監視対象のベースとなる定義がされています。 監視対象はデフォルトでは無効となっているので、個別に有効にする必要があります。
個別の監視設定は、/etc/fail2ban/jail.d/
下に作成します。 インストール時はこのディレクトリは空です。 ここに、監視対象の設定ファイルを作成していきます。
今回は以下の2つの設定を作成しました。
01-default-jail.conf ・・・ デフォルト定義用のファイル
02-enable-jail.conf ・・・ 個別定義用のファイル
デフォルト定義用のファイル
[DEFAULT]セクションの定義を行います。
[DEFAULT]
ignoreip = 127.0.0.1/8 192.168.XXX.0/24 10.XXX.0.0/16
banaction = firewallcmd-ipset
bantime = 2592000
findtime = 6000
maxretry = 3
destemail = root@xxx.co.jp
sender = fail2ban@xxx.co.jp
mta = postfix
backend = systemd
- ignoreip: banの対象外とするIPアドレスを指定します。
- banaction: [DEFAULT]セクションでのみ定義可能なbanアクションです。 すべての監視対象にデフォルトで割り当てられるアクションになります。
- bantime: banしておく時間(秒)を定義します。
- findtime: ここで定義した時間内(秒)のログが検知対象期間となります。
- maxretry: ここで定義した回数に達すると、banが実行されます。
- destemail: banのアクションでメールを送信する場合の宛先です。
- sender: banのアクションでメールを送信する場合の送信者です。
- mta: banのアクションでメールを送信する場合のMTAを指定します。
- backend: 対象のログについての指定。
auto
,pyinotify
,gamin
,systemd
,polling
の5つから選択可能。systemd
を選択すると、systemdのjournalから情報を取得します。 autoはpyinotify
,gamin
,systemd
,polling
の順番に情報を取得しますが、たまにgaminで失敗するそうです。 任意のログファイルを指定するのであれば、polling
を指定しておけば問題ないと思います。
個別定義用のファイル
02-enable-jail.confでは、個々の監視を定義します。 []にfilter.d下にある定義ファイルの名前(拡張子ナシ)をセクション名とします。 以下は、先ほど新規に作成した[wplogin]の定義だけではなく、[sshd]の定義も行っています。 sshdはインストール時にfilter.d
下に作成されているフィルター定義です。
[sshd]
enabled = true
action = firewallcmd-multiport[name=sshd, port="ssh", protocol=tcp]
sendmail-whois-ipjailmatches[name=sshd, sender=fail2ban@xxx.co.jp, dest=root@xxx.co.jp]
[wplogin]
enabled = true
action = firewallcmd-multiport[name=wplogin, port="http,https,smtp", protocol=tcp]
sendmail-whois-ipjailmatches[name=wplogin, sender=fail2ban@xxx.co.jp, dest=root@xxx.co.jp]
port = http,https,smtp
logpath = /home/kusanagi/XXX/log/httpd/*access.log
/home/kusanagi/YYY/log/httpd/*access.log
/home/kusanagi/ZZZ/log/httpd/*access.log
maxretry = 5
backend = polling
- enabled: trueを指定すると、対象のセクションが有効になります。 セクション名と同一の
filter.d
下の検知ファイルで検知を行います。 - action: 個々のアクションを定義する場合には、actionを定義します。 改行することで複数定義可能です。
/etc/fail2ban/action.d
下に各種アクションがあります。 - port: ban対象のポートです。
- logpath: 検知対象のログファイルです。 改行することで複数定義可能です。 またワイルドカードも利用できるので、
*access.log
と指定すれば、access.log
とssl_access.log
を対象とすることができます。
- 今回は、以下のactionを定義しています。
- firewallcmd-multiport
- firewallで対象のIPアドレスをbantimeの間、REJECT(デフォルト)します。 DROPにする場合には、`blocktype=DROP` を付与します。 例) firewallcmd-multiport[name=sshd, port="ssh", protocol=tcp, blocktype=DROP]
- sendmail-whois-ipjailmatches
- banされたIPアドレスの情報をwhoisの結果を付けて指定したアドレスにメールで送ってくれます。
稼働確認
fail2banのサービスを再起動します。
systemctl restart fail2ban.service
起動できたら、状態を確認してみます。 定義した監視対象(セクション名)がJail listに出てきたら、その定義は有効となっています。
# fail2ban-client status
Status
|- Number of jail: 2
`- Jail list: sshd, wplogin
つづいて、各セクション毎の状態を確認します。
sshdの場合は、backendをsystemdのJournalから取ってきていることが分かります。
# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 2
| |- Total failed: 15
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 16
|- Total banned: 16
`- Banned IP list: 103.207.37.22 103.207.39.54 123.31.30.112 (長いので省略)
wploginの場合は、backendをpollingにしているので、logpathに指定しているファイルの一覧が表示されます。
# fail2ban-client status wplogin
Status for the jail: wplogin
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /home/kusanagi/XXX/log/httpd/ssl_access.log /home/kusanagi/XXX/log/httpd/access.log /home/kusanagi/YYY/log/httpd/ssl_access.log /home/kusanagi/YYY/log/httpd/access.log /home/kusanagi/ZZZ/log/httpd/ssl_access.log /home/kusanagi/ZZZ/log/httpd/access.log
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: 1.162.172.194
実際にbanされたら、iptalbesで確認すると、デフォルトactionの定義では REJECT --reject-with icmp-port-unreachable
されているのが確認できます。
# iptables -nvL
再読み込み
特定の監視設定のみ再読み込みを行いたい場合には、以下のようにすることもできます。
# fail2ban-client reload jail名
例)
# fail2ban-client reload sshd