hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

fail2banの使い方



1 fail2banとは?

fail2banは、サーバを不正アクセスから保護するためのツールです。具体的には、ログファイルの内容を監視し、認証に何度も失敗しているログや連続アクセスしているログを検出すると、ファイアーウォールの設定を変更して、不正アクセス元からの接続を禁止します。たとえば、SSHのログインが失敗すると、/var/log/secureに以下のようなログが記録されます。fail2banは、このログを監視して、何度もSSHログインに失敗している接続元からのアクセスを禁止します。

[root@server ~]# tail -f /var/log/secure
-snip-
May 23 21:04:21 primary unix_chkpwd[1247]: password check failed for user (root)
May 23 21:04:21 primary sshd[1245]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.122.213  user=root
May 23 21:04:23 primary sshd[1245]: Failed password for root from 192.168.122.213 port 58084 ssh2

2 検証環境

2.1 ネットワーク構成

サーバとクライアントの2台構成です。図中のeth0はNICの名前です。

                         192.168.122.0/24
client(eth0) ----------------------------------------(eth0) server
           .213                                       .16

2.2 版数

サーバのCentOS版数は以下のとおりです。

[root@server ~]# cat /etc/redhat-release
AlmaLinux release 9.1 (Lime Lynx)

サーバのカーネル版数は以下のとおりです。

[root@server ~]# uname -r
5.14.0-162.6.1.el9_1.x86_64

3 インストール方法

3.1 fail2banのインストール

fail2banパッケージはepelリポジトリにあるので、まず、epel-releaseパッケージをインストールします。

[root@server ~]# dnf -y install epel-release

次に、fail2banパッケージをインストールします。

[root@server ~]# dnf -y install fail2ban

インストールしたfail2banの版数を確認します。fail2banのメジャーバージョンが1になりました。

[root@server ~]# fail2ban-server --version
Fail2Ban v1.0.2
[root@server ~]# fail2ban-client --version
Fail2Ban v1.0.2
[root@server ~]# fail2ban-regex --version
fail2ban-regex 1.0.2
[root@server ~]# fail2ban-python --version
Python 3.9.14

3.2 Apacheのインストール

検証目的のため、サーバにhttpdパッケージをインストールします。

[root@server ~]# dnf -y install httpd

httpdサービスを起動します。

[root@server ~]# systemctl start httpd

4 機能概要

4.1 fail2ban-server/fail2ban-client概要

コマンド 概要
fail2ban-server システムに常駐して,ログファイルの監視や攻撃を受けた際の処理を行う
fail2ban-client fail2ban-serverの起動・停止や各種設定をおこなう

4.2 設定ファイル

設定ファイル名 概要
/etc/fail2ban/fail2ban.conf ログの格納場所やログレベルを指定する
/etc/fail2ban/filter.d/*.conf 正規表現を使ってアクセス違反を定義する
/etc/fail2ban/action.d/*.conf アクセス違反が発生したときの動作を定義する
/etc/fail2ban/jail.conf どの程度(時間、回数)アクセスがあったらブロックするかを定義する。 ただし、このファイルは編集しない(後述)

5 サーバの起動、停止方法

fail2ban-clientコマンドを使って、fail2banの起動、停止ができます。なお、systemctlコマンドでも、fail2banの起動、停止ができます。

[root@server ~]# fail2ban-client start
Server ready

fail2banを起動すると、以下のプロセスが生成されます。なお、PIDが全て同じなので、3つのプロセスはアドレス空間を共有するスレッドとなります。

  • fail2ban-server:親プロセス
  • f2b/observer:fail2ban-serverが生成するプロセス

なお、psコマンドの使い方は、psコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# ps -LC fail2ban-server -o comm,pid,ppid,args
COMMAND             PID    PPID COMMAND
fail2ban-server    3194       1 /usr/bin/python3 -s /usr/bin/fail2ban-server --async -b -s /var/run/fail2ban/f
f2b/observer       3194       1 /usr/bin/python3 -s /usr/bin/fail2ban-server --async -b -s /var/run/fail2ban/f
f2b/observer       3194       1 /usr/bin/python3 -s /usr/bin/fail2ban-server --async -b -s /var/run/fail2ban/f

fail2banの状態は、statusオプションを使用して確認します。Number of jailが0であるため、現在アクセス禁止にされているアクセス元が存在しないことがわかります。

[root@server ~]# fail2ban-client status
Status
|- Number of jail:      0
`- Jail list:

fail2banを停止します。

[root@server ~]# fail2ban-client stop
Shutdown successful

fail2banの状態を確認します。fail2banを停止したので、"Is fail2ban running?"と聞かれます。

[root@server ~]# fail2ban-client status
2023-05-23 21:57:06,494 fail2ban                [3203]: ERROR   Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?

6 設定ファイルのカスタマイズ方法

jail.confのmanを確認すると、以下の説明があります。設定のカスタマイズはjail.confではなく、jail.localを新規作成して、そこに記述するようです。

[root@server ~]# man jail.conf
-snip-
       *.conf files are distributed by Fail2Ban.  It is recommended that *.conf files should remain unchanged to ease
       upgrades.  If needed, customizations should be provided in *.local files.  For example, if you would  like  to
       enable the [ssh-iptables-ipset] jail specified in jail.conf, create jail.local containing

       jail.local
              [ssh-iptables-ipset]

              enabled = true

       In .local files specify only the settings you would like to change and the rest of the configuration will then
       come from the corresponding .conf file which is parsed first.

7 実験1(sshアクセスの禁止)

30秒間で2回、sshログインに失敗すると、サーバに60秒間アクセス禁止にする、という設定をしてみます。アクセス禁止とは、ファイアーウォールでsshパケットをREJECTする、という意味です。

7.1 設定内容

jail.localを新たに作成します。設定内容は次のとおりです。

  • bantime:対象ホストへのアクセス禁止の時間です。
  • findtime :監視時間を表します。
  • maxretry :リトライ回数を表します。findtimeで指定した時間、maxretry回続けば対象ホストへのアクセス遮断します。
[root@server ~]# vi /etc/fail2ban/jail.local
[root@server ~]# cat /etc/fail2ban/jail.local
[sshd]
enabled = true
bantime  = 60
findtime  = 30
maxretry = 2

fail2banサーバを起動します。

[root@server ~]# fail2ban-client start
Server ready

fail2banの状態を確認します。まだアクセス禁止(Banned IP list)になっているIPアドレスはありません。

[root@server ~]# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:

7.2 動作確認

クライアントからサーバにsshログインを実行します。このとき、意図的に間違ったパスワードを入力します。

[root@client ~]# ssh 192.168.122.16
root@192.168.122.16's password:
Permission denied, please try again.
root@192.168.122.16's password:
Permission denied, please try again.
root@192.168.122.16's password:
root@192.168.122.16: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

さらにサーバにsshログインを実行してみます。fail2banがnetfilterのルールを変更して、22番ポートへのアクセスを禁止にしたため、TCPコネクション確立が拒否されていることがわかります。"Connection refused"については、ECONNREFUSEDとECONNRESETについて - hana_shinのLinux技術ブログを参照してください。

[root@client ~]# ssh 192.168.122.16
ssh: connect to host 192.168.122.16 port 22: Connection refused

fail2banの状態を確認してみます。192.168.122.213からのアクセスが禁止されたことがわかります。

[root@server ~]# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 1
|  |- Total failed:     3
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 1
   |- Total banned:     1
   `- Banned IP list:   192.168.122.213

netfilterのアクセス定義を確認してみます。22番ポートのアクセス禁止にするルールが設定されていることがわかります。

[root@server ~]# nft list ruleset|grep -A2 filter_IN_public_deny
                jump filter_IN_public_deny
                jump filter_IN_public_allow
                jump filter_IN_public_post
--
        chain filter_IN_public_deny {
                ip saddr 192.168.122.213 tcp dport 22 ct state { new, untracked } reject with icmp port-unreachable
        }

192.168.122.213からのアクセス禁止を解除します。

[root@server ~]# fail2ban-client set sshd unbanip 192.168.122.213
0

fail2banの状態を確認してみます。192.168.122.213からのアクセス禁止が解除されたことがわかります。

[root@server ~]#  fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     3
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 0
   |- Total banned:     1
   `- Banned IP list:

8 実験2(HTTPアクセスの禁止)

HTTP GETやHTTP HEADを連続して送信するアクセス元をアクセス禁止にしてみます。

8.1 事前準備(fail2banの設定)

設定ファイルを作成します。設定内容は以下のとおりです。

  • 監視ポート番号(port):80,443
  • フィルタ(filter):http-get-dos.conf
  • 監視するファイル(logpath):/var/log/httpd/access_log
  • アクセス禁止時間(bantime):600秒
  • 監視時間(findtime):10秒
  • リトライ回数(maxRetry):2回
[root@server ~]# vi /etc/fail2ban/jail.local
[root@server ~]# cat /etc/fail2ban/jail.local
[http-get-dos]
enabled = true
port = http,https
filter = http-get-dos
logpath   = /var/log/httpd/access_log
bantime = 600
findtime = 10
maxRetry = 2

フィルタを作成します。フィルタの内容は次のとおりです。/var/log/httpd/access_logに次の正規表現に合致するログが出力されたら、接続元からのアクセス拒否します。

  • HOST:行頭がホスト名、またはIPアドレス(IPv4,IPv6)
  • GET|HEAD:HTTPメソッドがGETまたHEAD
[root@server ~]# vi /etc/fail2ban/filter.d/http-get-dos.conf
[root@server ~]# cat /etc/fail2ban/filter.d/http-get-dos.conf
[Definition]
failregex = ^<HOST> -.*"(GET|HEAD).*
ignoreregex =

fail2banを起動します。

[root@server ~]# fail2ban-client restart
Shutdown successful
Server ready

fail2banの状態を確認します。

[root@server ~]# fail2ban-client status
Status
|- Number of jail:      1
`- Jail list:   http-get-dos

fail2banの状態を確認します。クライアントからのアクセス拒否が解除されたことがわかります。

[root@server ~]# fail2ban-client status http-get-dos
Status for the jail: http-get-dos
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- File list:        /var/log/httpd/access_log
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:

8.2 事前準備(httpdの設定)

httpdの設定ファイルを作成します。

[root@server ~]# vi /var/www/html/index.html
[root@server ~]# cat /var/www/html/index.html
Hello

httpdサービスを起動します。

[root@server ~]# systemctl restart httpd

httpdがListenしているポート番号を確認します。httpdTCPの80番ポートでListenしていることがわかります。なお、lsofコマンドの使い方は、lsofコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# lsof -c httpd -a -i -a -nP
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd   1489   root    4u  IPv6  21849      0t0  TCP *:80 (LISTEN)
httpd   1492 apache    4u  IPv6  21849      0t0  TCP *:80 (LISTEN)
httpd   1493 apache    4u  IPv6  21849      0t0  TCP *:80 (LISTEN)
httpd   1494 apache    4u  IPv6  21849      0t0  TCP *:80 (LISTEN)

httpdがListenしている80番ポートへのアクセスを解放します。なお、firewall-cmdコマンドの使い方は、trace-cmdコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# firewall-cmd --add-port=80/tcp
success

開放したポート番号を確認します。80番ポートへのアクセスが解放されていることがわかります。

[root@server ~]# firewall-cmd --list-ports
80/tcp

8.3 動作確認

ここでは、curlコマンドを使って、GETメソッドをサーバに送信してみます。なお、HEADメソッドは、curlの-Iオプションを使って送信できます。どちらのメソッドを使っても、アクセスが禁止されることが確認できます。

サーバにhttpアクセスします。

[root@client ~]# date;curl http://192.168.122.16
2023年  5月 24日 水曜日 20:27:15 JST
Hello

サーバにhttpアクセスします(リトライ1回目)。

[root@client ~]# date;curl http://192.168.122.16
2023年  5月 24日 水曜日 20:27:17 JST
Hello

サーバにhttpアクセスします(リトライ2回目)。

[root@client ~]# date;curl http://192.168.122.16
2023年  5月 24日 水曜日 20:27:18 JST
Hello

サーバにhttpアクセスします。10秒間で2回目のリトライをしたので、3回目のアクセスが拒否されました。

[root@client ~]# date;curl http://192.168.122.16
2023年  5月 24日 水曜日 20:27:19 JST
curl: (7) Failed to connect to 192.168.122.16 port 80: 接続を拒否されました

fail2banの状態を確認します。クライアントからのアクセスが拒否されていることがわかります。

[root@server ~]# fail2ban-client status http-get-dos
Status for the jail: http-get-dos
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     2
|  `- File list:        /var/log/httpd/access_log
`- Actions
   |- Currently banned: 1
   |- Total banned:     1
   `- Banned IP list:   192.168.122.213

クライアントからのアクセス拒否を解除します。

[root@server ~]# fail2ban-client set http-get-dos unbanip 192.168.122.213
1

fail2banの状態を確認します。

[root@server ~]# fail2ban-client status http-get-dos
Status for the jail: http-get-dos
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     2
|  `- File list:        /var/log/httpd/access_log
`- Actions
   |- Currently banned: 0
   |- Total banned:     1
   `- Banned IP list:

Z 参考情報

私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ


https://www.linode.com/docs/guides/using-fail2ban-to-secure-your-server-a-tutorial/