仮想サーバへの度重なる攻撃をfail2banで自動ブロックする

# 目的

インターネットに晒されたサーバを運用している方ならご存じのとおり、特にSSHポートは常に攻撃されていることに気づきます。証明書認証やソースIPを絞ることで実質的な被害はありませんが、ログに常に攻撃の痕跡があるのは精神衛生上よくはないです。

> There were 17477 failed login attempts since the last successful login.

特にIBM Cloud VPCの仮想サーバはクラシックインフラストラクチャーの仮想サーバとは違い、標準でSSL-VPN接続がないため、踏み台としてパブリックからSSHを許可するケースは多いでしょうし、作業場所のパブリックIPアドレスが固定ではないため、ソースIPで絞れないケースもあると思います。

そこで、fail2banというツールを使って、攻撃元を自動ブロックしてみます。

# 手順

## 前提

* OSはRed Hat Enterprise Linux 8を使用

## EPELリポジトリの有効化

fail2banはEPELにありますのでリポジトリを有効化します。

```
# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
```

## fail2banのインストール

fail2banをインストールします。また、今回はバックエンドとしてjournalを使用するため、fail2ban-systemdもインストールします。

```
# dnf install fail2ban fail2ban-systemd
```

## 設定

fail2banの設定ファイルは/etc/fail2ban/以下にあります。個別の設定は/etc/fail2ban/jail.localや/etc/fail2ban/jail.d/で行うのが習わしです。今回はjail.localを使用します。

```/etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 10.244.0.0/24　# ローカルのIPは無視

[sshd]
enabled = true
bantime = 30m  # 30分間ブロック
maxretry = 3   # 3回の攻撃検知でブロック

[recidive]     # 再犯者を長期ブロック
enabled = true
port = ssh     # 長期ブロックしたいポート（複数ある場合は,区切りで指定可）
maxretry = 2   # 2回の攻撃検知で長期ブロック
```

個別カスタマイズではない部分はjail.confの値が使われます。

```/etc/fail2ban/jail.conf
[DEFAULT]
findtime = 10m  # 10分以内に攻撃検知

[recidive]
bantime  = 1w   # 1週間ブロック
findtime = 1d   # 1日以内に攻撃検知
```

結果として次のようなルールになります。

* sshで10分以内に3回攻撃検知（ログイン失敗）したら30分間ブロック
* それを1日に2回検知したら1週間長期ブロック

## firewalldの起動

fail2banはfirewalldを使用します。IBM Cloud VPCの仮想サーバはfirewalldが有効になっていないので開始します。

```
# systemctl enable firewalld
# systemctl start fiwarelld
# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: cockpit dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```

## fail2banの起動

```
# systemctl enable fail2ban
# systemctl start fail2ban
```

## 確認

起動すると早速ブロック（BAN）が開始されています。

```
# tail -f /var/log/fail2ban.log
2020-10-11 12:12:22,788 fail2ban.filter         [7414]: INFO    [sshd] Found 222.186.42.57 - 2020-10-11 12:12:17
2020-10-11 12:12:22,789 fail2ban.filter         [7414]: INFO    [sshd] Found 222.186.42.57 - 2020-10-11 12:12:21
2020-10-11 12:12:23,077 fail2ban.actions        [7414]: NOTICE  [sshd] Ban 35.192.99.43
2020-10-11 12:12:23,826 fail2ban.actions        [7414]: NOTICE  [sshd] Ban 122.168.195.223
2020-10-11 12:12:24,385 fail2ban.actions        [7414]: NOTICE  [sshd] Ban 222.186.30.112
2020-10-11 12:12:25,016 fail2ban.actions        [7414]: NOTICE  [sshd] Ban 222.186.42.57
2020-10-11 12:12:28,601 fail2ban.filter         [7414]: INFO    [sshd] Found 222.186.42.57 - 2020-10-11 12:12:28
2020-10-11 12:12:32,856 fail2ban.filter         [7414]: INFO    [sshd] Found 222.186.42.57 - 2020-10-11 12:12:32
2020-10-11 12:12:36,614 fail2ban.filter         [7414]: INFO    [sshd] Found 222.186.42.57 - 2020-10-11 12:12:36
2020-10-11 12:12:36,966 fail2ban.actions        [7414]: NOTICE  [sshd] 222.186.42.57 already banned
```

コマンドラインで現在の状況が確認できます。

```
# fail2ban-client status
Status
|- Number of jail:      2
`- Jail list:   recidive, sshd

# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 1
|  |- Total failed:     30
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 5
   |- Total banned:     5
   `- Banned IP list:   35.192.99.43 122.168.195.223 222.186.30.112 222.186.42.57 198.12.249.249

# fail2ban-client status recidive
Status for the jail: recidive
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- Journal matches:  _SYSTEMD_UNIT=fail2ban.service PRIORITY=5
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:
```

実体はfirewalldのrich ruleを使ってブロックをしています。

```
# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: cockpit dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
        rule family="ipv4" source address="35.192.99.43" port port="ssh" protocol="tcp" reject type="icmp-port-unreachable"
        rule family="ipv4" source address="122.168.195.223" port port="ssh" protocol="tcp" reject type="icmp-port-unreachable"
        rule family="ipv4" source address="222.186.30.112" port port="ssh" protocol="tcp" reject type="icmp-port-unreachable"
        rule family="ipv4" source address="222.186.42.57" port port="ssh" protocol="tcp" reject type="icmp-port-unreachable"
        rule family="ipv4" source address="198.12.249.249" port port="ssh" protocol="tcp" reject type="icmp-port-unreachable"
        rule family="ipv4" source address="218.92.0.249" port port="ssh" protocol="tcp" reject type="icmp-port-unreachable"
```

これを仕込むと、/var/log/secureのログイン失敗ログがあからさまに減りますので気持ちいいです。fail2banはかなり細かい設定やルールが他にもありますので、ガイドを参考にカスタマイズしてみてください。