はじめに
AWSの無料枠などでEC2インスタンスを立ち上げ、インターネットに公開したその瞬間から、世界中の自動ボットによる「総当たり攻撃(ブルートフォースアタック)」が開始されます。
「まだ個人開発のテスト環境だから大丈夫」「重要なデータは入っていないから」と対策を怠っていると、思わぬリスクを背負うことになります。
本記事では、Amazon Linux 2023(AL2023) の作法に則ったSSHの要塞化と、しつこい攻撃者を自動で出入り禁止(BAN)にする「Fail2ban」の導入手順を、試行した際の記録になります。
【前提】
・パスワードログインでなく、キーペア(ログイン)を利用するインスタンスへの接続とする
・インスタンス起動時に、SSH接続するためのパブリックIPを有効化しておく
・EC2インスタンスでAmazon Linux 2023をインスタンス起動させておく
【今回の対策ゴール】
・入口を狭める: 関係のない場所からのアクセスや、狙われやすい設定を徹底的に遮断する。
・Fail2ban: しつこくアタックしてきたIPアドレスを自動的に検知し、サーバーの手前でシャットアウトする。
SSH要塞化
STEP1.インバウンドルールを厳格化する
【実施内容】
SSH接続するためのポートを既存ポートから変更ポートへとカスタマイズします。
既存ポート用:TCP / 22 / 自分のパブリックIP
変更ポート用:カスタムTCP / 10022 / 自分のパブリックIP
【手順】
1) EC2の管理画面を開き、対象のインスタンスを選択します。
2) 画面下の「セキュリティ」タブをクリックし、紐づいている「セキュリティグループ」のリンクをクリックします。
3) 画面右上の 「インバウンドルールを編集」 ボタンを押し、そこで 10022 番ポートの許可ルールを追加します。
STEP2.カスタム設定ファイルを作成する
【実施内容】
AL2023では、従来の /etc/ssh/sshd_config を直接編集するのではなく、
設定専用ディレクトリにカスタムファイルを新規作成するのが美しい設計(ベストプラクティス)です。
【手順】
既存のポートにキーペアを使用して、ssh接続します。
ssh -i /パス/your-key.pem ec2-user@XX.XX.XX.XX <-EC2のパブリックIP
接続後、以下のコマンドで一撃で設定ファイルを流し込みます。
sudo tee /etc/ssh/sshd_config.d/99-custom.conf << 'EOF'
Port 10022
PermitRootLogin no
PasswordAuthentication no
EOF
設定に構文エラーがないかチェックします。
sudo sshd -t
何もエラーが出なければ、SSHサービスを再起動して反映させます。
Ubuntuと違い、サービス名の末尾に d がつく点に注意。
sudo systemctl restart sshd
🚨 超重要・絶対に守ること:
今繋がっているEC2のターミナル(セッション)は絶対に閉じないでください!
そのままの状態で、手元のPCから新しく別のターミナルを立ち上げ、以下のコマンドで新しいポートからログインできるかテストします。
STEP3.動作検証
【実施内容】
新しいポートで接続できるか確認します。
【手順】
ssh -i /パス/your-key.pem -p 10022 ec2-user@XX.XX.XX.XX <-EC2のパブリックIP
無事にログインできたら、既存の22番ポートで繋いでいた古いターミナルを閉じて大丈夫です
Fail2banの実装
AL2023は初期状態では外部リポジトリ(EPELなど)を追加することなく、標準のパッケージマネージャー(dnf)から直接Fail2banをインストールできます。
STEP1.fail2banをインストール
【実施内容】
fail2banをインストールします。
【手順】
sudo dnf install fail2ban -y
STEP2.設定ファイルの作成(systemd-journald対応)
【実施内容】
AL2023には、従来の /var/log/secure のようなテキスト形式の認証ログファイルがデフォルトで存在しません。
ログはすべて systemd-journald という仕組みでメモリ管理されています。
そのため、Fail2ban側には「ファイルを見に行くのではなく、systemdから直接ログを読み取ってね」と指示を出す必要があります。
カスタム設定ファイル(jail.local)を作成して、以下の内容を記述します。
【手順】
sudo nano /etc/fail2ban/jail.local
以下を記述します。
Amazon Linux 2023用の jail.local の書き方例
[sshd]
enabled = true
port = 10022
filter = sshd
# 最重要:AL2023のログ仕様に合わせる設定
backend = systemd
maxretry = 3
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8
編集後、保存と終了を行います。
保存:Ctrl + O でEnter
終了:Ctrl + X
Amazon Linux 2023ではデフォルトで rsyslog が入っておらず、ログをファイルではなく systemd-journald(メモリ上のバイナリログ)で管理しています。
そのため、Fail2banにログを読ませる際は、logpath を指定するのではなく、backend = systemd を指定するのが今の正しい設定手順になります。
maxretry : BANするためのリトライ失敗回数
findtime:連続してログイン失敗とみなす時間
bantime:BANされた時の接続拒否時間。通常は1時間(1h)とかですが今回はテストで5分(5m)
STEP3.Fail2banの起動と自動起動設定
【実施内容】
fail2banを起動させます。
OS起動時の自動起動を有効にします。
【手順】
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
STEP4.動作検証
【実施内容】
本当に攻撃者が自動ブロックされるかテストします。
BANされると前述で実施した時間は接続できなくなります。
ご自身のPCがBANされないよう、前述の SSH要塞化 STEP1のセキュリティグループで一時的に「すべてのIP(0.0.0.0/0)」に10022ポートを開いて別端末でテストするか、スマホのテザリングなど別回線からテストしてください。
【手順】
テスト環境から、あえて間違った秘密鍵などを指定して3回アタックします。
ssh -p 10022 dummy-user@XX.XX.XX.XX <-EC2のパブリックIP
3回失敗すると、4回目からは接続が完全に拒否(Connection refused)されるようになります。
STEP5.EC2側で捕獲ステータスを確認する
【実施内容】
元の安全な接続を維持しているターミナルから、Fail2banの状況を覗いてみましょう。
【手順】
sudo 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: 1
|- Total banned: 1
`- Banned IP list: XX.XX.XX.XX <--ここにアタックしてきたIPが表示される!
もし実験で自分のメインIPを誤ってBANしてしまったら?
焦らずにサーバー側から以下のコマンドを実行すれば、即座にBANを解除できます。
sudo fail2ban-client set sshd unbanip <ブロックされたIPアドレス>
以前は、keypair使っていれば大丈夫だろうくらいに考えていましたが、
知れば知るほど、セキュリティに対する怖さを実感するこの頃です。
今度は、怪しい動きを検知したら通知する仕組みなども挑戦したいですね。