こんにちは、UOZUです!
インターネットへ公開したLinuxサーバーのSSHログを見ると、心当たりのないユーザー名でログインを試みられていることがあります。ユーザー名やパスワードを繰り返し試す、総当たり攻撃や辞書攻撃です。
実際にさくらのVPSの起動後、/var/log/secure では相当数のSSHアタックが来ていることが分かります。
# less /var/log/secure
--
Sep 13 00:54:55 uozu-vps sshd-session[141777]: Received disconnect from 203.0.113.34 port 34000:11: Bye Bye [preauth]
Sep 13 00:54:55 uozu-vps sshd-session[141777]: Disconnected from invalid user adminuser 203.0.113.34 port 34000 [preauth]
Sep 13 00:55:05 uozu-vps sshd-session[141779]: Invalid user student from 198.51.100.154 port 34192
Sep 13 00:55:05 uozu-vps sshd-session[141779]: Received disconnect from 198.51.100.154 port 34192:11: Bye Bye [preauth]
Sep 13 00:55:05 uozu-vps sshd-session[141779]: Disconnected from invalid user student 198.51.100.154 port 34192 [preauth]
Sep 13 00:55:10 uozu-vps sshd-session[141781]: Received disconnect from 192.0.2.28 port 45024:11: Bye Bye [preauth]
Sep 13 00:55:10 uozu-vps sshd-session[141781]: Disconnected from authenticating user root 192.0.2.28 port 45024 [preauth]
さくらのクラウドを利用している方は、Fail2banという名前を見かけたことがあるかもしれません。例えば、さくらのクラウドのAlmaLinux 10.0パブリックアーカイブでは、Fail2banが有効化され、SSHのログイン試行に5回失敗すると接続を拒否する設定が案内されています。公式リリースノート
今回はさくらのVPSのAlmaLinux 10を対象に、導入状況の確認からFail2banの設定、動作確認、誤って遮断した場合の解除方法まで紹介します。
Fail2banとは?
Fail2banは、認証失敗などのログを監視し、条件に一致した接続元IPアドレスを一定時間遮断するソフトウェアです。
例えば「10分以内に5回の失敗を検知したIPアドレスを1時間遮断する」といった設定ができます。
実際の通信遮断は、Fail2banがOSのファイアウォール機構にルールを追加して行います。今回はnftablesを使う構成にします。
| 機能 | 主な役割 |
|---|---|
| さくらのVPSのパケットフィルター | VPSの外側で、あらかじめ設定した通信条件に基づいて制御する |
| firewalldなどOSのファイアウォール管理機能 | OS内で許可するポートや接続元などを管理する |
| Fail2ban | ログから不審な試行を検知し、OS側に遮断ルールを追加・解除する |
今回の設定で、Fail2banがさくらのVPSのコントロールパネルにあるパケットフィルターを書き換えることはありません。
今回の前提
- さくらのVPSでAlmaLinux 10を使用する
- sudoを実行できる管理ユーザーで作業する
- SSHはTCP 22番ポートを使用する
さくらのVPSのAlmaLinux 10では、標準ユーザーはalmaです。設定は提供時期などで変わるため、利用中のサーバーと標準OSセットアップ情報を確認してください。
※本記事は設定例です。実機での動作を保証するものではありません。
1. SSH以外の復旧手段を確保する
Fail2banは、管理者がログインに繰り返し失敗した場合も遮断する可能性があります。
作業前にコントロールパネルのコンソールを開き、OSへログインしてsudoを実行できることを確認しましょう。コンソール画面が開くだけでは、復旧手段の確認として不十分です。
また、現在のSSH接続は残したまま、別のターミナルから接続を確認します。ただし、既存接続が必ず維持されるとは限らないため、コンソールも準備しておきます。
2. Fail2banをインストールする
EPELリポジトリを利用してFail2banをインストールします。
ここではFail2ban本体とsystemd journal用の連携パッケージを導入します。
# dnf install epel-release
# dnf install fail2ban-server fail2ban-systemd
# fail2ban-client --version
Fail2Ban v1.1.0
なお、Fail2banからnftコマンドでルールを操作するために、nftables.serviceを新しく起動する必要はありません。既存のfirewalldやnftablesルールは削除せず、そのまま維持します。
3. SSHの監視設定を作成する
初期設定のjail.confを直接編集せず、専用の.localファイルを作成します。
# vi /etc/fail2ban/jail.d/sshd.local
# cat /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
filter = sshd
backend = systemd
port = 22
banaction = nftables-multiport
findtime = 10m
maxretry = 5
bantime = 1h
ignoreip = 127.0.0.1/8 ::1 203.0.113.222 198.51.100.98
| 設定 | 内容 |
|---|---|
| enabled | sshd jailを有効化する |
| filter | SSH向けの検知フィルターを使う |
| backend | systemd journalからログを読む |
| port | 遮断対象のSSHポート |
| banaction | nftablesで対象ポートへの通信を遮断する |
| findtime | 失敗回数を数える期間 |
| maxretry | 遮断の基準となる失敗回数 |
| bantime | 遮断を継続する時間 |
| ignoreip | 遮断対象から除外するIPアドレス |
この例では「10分以内に5回の失敗を検知した接続元を、1時間遮断する」設定です。数えるのはフィルターに一致した失敗であり、SSHコマンドを実行した回数と必ず一致するわけではありません。
backend = systemdでは、ログファイルのパスを指定するlogpathは使用しません。設定項目と.localによるカスタマイズ方法は、Fail2banの公式設定ファイルでも説明されています。
SSHのポートを変更している場合は、portも実際の番号に合わせます。ここを変更してもsshdの待ち受けポート自体は変わりません。
管理元IPアドレスの扱い
管理用の固定グローバルIPアドレスがある場合は、ignoreipへ追加できます。
ただし、除外したIPアドレスからの試行は遮断されません。共有回線の広い範囲を除外したり、動的に変わるIPを放置したりしないよう注意しましょう。NAT環境では、サーバーから見える接続元のグローバルIPアドレスを指定します。
4. 設定を確認して起動する
設定テストを行い、自動起動も有効にして起動させます。
# fail2ban-client -t
OK: configuration test is successful
# systemctl enable --now fail2ban
Created symlink '/etc/systemd/system/multi-user.target.wants/fail2ban.service' →'/usr/lib/systemd/system/fail2ban.service'.
次のコマンドで確認します。
# systemctl status fail2ban
# fail2ban-client get sshd findtime
600
# fail2ban-client get sshd maxretry
5
# fail2ban-client get sshd bantime
3600
# fail2ban-client get sshd actions
nftables-multiport
設定値だけでなく、意図した遮断アクションが使われているかも確認してください。
5. 検知と遮断を確認する
Fail2banのログとnfablesの状態を確認
Fail2banのログで検知や遮断の記録があることを確認しましょう。
# tail /var/log/fail2ban.log
--
2026-09-13 18:53:53,557 fail2ban.filter [147851]: INFO [sshd] Found 203.0.113.34 - 2026-09-13 18:51:25
2026-09-13 18:53:53,557 fail2ban.filter [147851]: INFO [sshd] Found 198.51.100.211 - 2026-09-13 18:51:28
2026-09-13 18:53:53,557 fail2ban.filter [147851]: INFO [sshd] Found 192.0.2.17 - 2026-09-13 18:52:15
2026-09-13 18:53:53,558 fail2ban.filtersystemd [147851]: INFO [sshd] Jail is in operation now (process new journal entries)
2026-09-13 18:53:53,746 fail2ban.actions [147851]: NOTICE [sshd] Ban 192.0.2.17
2026-09-13 18:53:56,792 fail2ban.filter [147851]: INFO [sshd] Found 203.0.113.34 - 2026-09-13 18:53:56
2026-09-13 18:53:57,007 fail2ban.actions [147851]: NOTICE [sshd] Ban 203.0.113.34
nftablesでもreject対象のIPとして遮断されていることも確認できますね。
# nft list ruleset
--
table inet f2b-table {
set addr-set-sshd {
type ipv4_addr
elements = { 203.0.113.34, 192.0.2.17 }
}
chain f2b-chain {
type filter hook input priority filter - 1; policy accept;
tcp dport 22 ip saddr @addr-set-sshd reject with icmp port-unreachable
}
}
管理用回線とは別の接続元で試す
検証は、自分が管理するVPSだけを対象に、管理用回線と異なる接続元IPアドレスから行います。別の端末でも同じルーターを経由していれば、同じグローバルIPアドレスになる場合があります。
- テスト元IPがignoreipに含まれないことを確認します。
- パケットフィルターなどでテスト通信が事前に拒否されていないことを確認します。
- テスト元から少数回の認証失敗を発生させます。
- SSHのログとFail2banの失敗カウントを確認します。
- 条件に達した後、テスト元IPがBAN一覧へ入ることを確認します。
- その接続元から新規SSH接続ができなくなることを確認します。
[root@uozu-attack ~]# ssh 203.0.113.189 -l test
test@203.0.113.189: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
[root@uozu-attack ~]# ssh 203.0.113.189 -l test
test@203.0.113.189: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
...
[root@uozu-attack ~]# ssh 203.0.113.189 -l test
ssh: connect to host 203.0.113.189 port 22: Connection refused
# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 5
| |- Total failed: 172
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session
`- Actions
|- Currently banned: 1
|- Total banned: 11
`- Banned IP list: 198.51.100.137
# nft list ruleset
table inet f2b-table {
set addr-set-sshd {
type ipv4_addr
elements = { 198.51.100.137 }
}
chain f2b-chain {
type filter hook input priority filter - 1; policy accept;
tcp dport 22 ip saddr @addr-set-sshd reject with icmp port-unreachable
}
}
検証のために本番サーバーのパスワード認証を有効化する必要はありません。公開鍵認証の失敗が数えられるかは、ログ内容とフィルター設定に依存するため、ログを見ながら確認します。
BAN一覧と、nftablesに追加されたルールの両方を確認します。Fail2banが起動しているだけでは、遮断成功の確認にはなりません。
IPv6でもSSHを公開している場合は、IPv6の検知・遮断も別途確認してください。また、OS再起動やファイアウォール設定の再読み込み後にも、ルールと動作を再確認しておくと安心です。
6. 誤って遮断したIPアドレスを解除する
本来遮断から除外すべきIPを誤って遮断してしまっている際は、以下のコマンドで遮断を解除できます。
# fail2ban-client set sshd unbanip 198.51.100.25
1
復旧のためにファイアウォール全体を停止したり、nftablesの全ルールを消したりする必要はありません。
Fail2banだけで十分?
Fail2banは有効な補助対策ですが、SSHへの攻撃を完全に防ぐものではありません。
多数のIPアドレスを使う攻撃や、しきい値に達しない低頻度の試行は遮断できない場合があります。また、最初の試行で正しい認証情報が使われれば、この失敗回数ベースの対策では防げません。
基本対策も組み合わせましょう。
- SSH公開鍵認証を利用する
- 公開鍵での接続確認後に、不要なパスワード認証を無効化する
- 管理用IPやVPN経由にSSH接続元を限定する
- 不要なroot直接ログインを禁止する
- OSや関連パッケージを更新する
- 認証ログとFail2banの稼働状態を定期的に確認する
固定の管理元だけで運用できる場合は、まず接続元を制限する構成を検討しましょう。
さいごに
さくらのクラウドには、Fail2banがあらかじめ有効になっているパブリックアーカイブがありますが、さくらのVPSでは、利用するOSや構築状況に応じて導入・設定状況を確認することが大切です。
今回は、AlmaLinux 10でFail2banを導入し、SSHの認証失敗を検知して接続元を一時遮断する設定を紹介しました。
導入して終わりにせず、「ログを読めているか」「実際に遮断されるか」「誤遮断を解除できるか」まで確認しておきましょう。
最後までお読みいただき、ありがとうございます!