- 1 fail2banとは?
- 2 検証環境
- 3 インストール方法
- 4 機能概要
- 5 サーバの起動、停止方法
- 6 設定ファイルのカスタマイズ方法
- 7 実験1(sshアクセスの禁止)
- 8 実験2(HTTPアクセスの禁止)
- Z 参考情報
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
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
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に次の正規表現に合致するログが出力されたら、接続元からのアクセス拒否します。
[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しているポート番号を確認します。httpdはTCPの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/