WordPressの不正ログインと不正中継メール送信をfail2banでbanしてみた

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を設定する

## 検知したいログ

```access.log
# 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 "-" "-"
```

```ssl_access.log
# 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アドレスに値します。

```wplogin.local
[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]セクションの定義を行います。

```/etc/fail2ban/jail.d/01-default-jail.conf

[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`下に作成されているフィルター定義です。

```/etc/fail2ban/jail.d/02-enable-jail.conf

[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`を対象とすることができます。
<dl> 今回は、以下のactionを定義しています。
<dt> firewallcmd-multiport
<dd> firewallで対象のIPアドレスをbantimeの間、REJECT(デフォルト)します。 DROPにする場合には、`blocktype=DROP` を付与します。 例） firewallcmd-multiport[name=sshd, port="ssh", protocol=tcp, blocktype=DROP]
<dt> sendmail-whois-ipjailmatches
<dd> banされたIPアドレスの情報をwhoisの結果を付けて指定したアドレスにメールで送ってくれます。
</dl>


# 稼働確認

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
```