UbuntuのVPSで、SSHログインをパスワード認証から公開鍵認証に変更しました。さらに、SSHに接続できるIPアドレスを限定しました。
この記事では、作業手順と接続確認のポイントをまとめます。
前提
以下の環境を想定しています。
- 接続元:Mac
- VPS:Ubuntu 20.04 / 22.04
- SSHポート:22
- ファイアウォール:UFWがすでに有効で、受信の既定ポリシーがdenyまたはreject
- ログインユーザー:sudoを実行できるユーザー、またはroot
記事中の値は例です。自分の環境に置き換えてください。
| 項目 | 記事中の例 |
|---|---|
| VPSのIPアドレス | 203.0.113.10 |
| 接続元のグローバルIP | 198.51.100.20 |
| ログインユーザー | example |
| 秘密鍵のファイル名 | id_ed25519_example_vps |
IPアドレスには、説明用に予約されたアドレスを使っています。そのままでは接続できません。
作業の順番
締め出されないように、次の順番で進めます。
- 現在の設定を確認する
- MacでSSH鍵を作成する
- VPSに公開鍵を登録する
- 公開鍵だけで新規ログインできることを確認する
- パスワード認証を無効化する
- 接続元IPを制限する
- 最後にもう一度、新規ログインを確認する
作業中のSSH接続は、最後の接続確認が終わるまで閉じません。
また、VPS事業者の管理画面からコンソールを使えることを、事前に確認しておきます。
1. VPSの現在の設定を確認する
ここからのコマンドは、SSH接続したVPS上で実行します。
OSとユーザーを確認
cat /etc/os-release
id
登録されているユーザーも確認します。
getent passwd | awk -F: \
'{printf "%-20s UID=%-6s HOME=%-30s SHELL=%s\n", $1, $3, $6, $7}'
この一覧には、ログイン用ユーザーだけでなく、サービス用ユーザーも含まれます。シェルが/bin/bashなどでも、SSH接続できるかどうかはSSH設定などに依存します。
現在の接続元とSSHポートを確認
printf '%s\n' "$SSH_CONNECTION"
次の順番で表示されます。
接続元IP 接続元ポート VPSのIP SSHポート
SSHの実効設定を確認
sudo /usr/sbin/sshd -T | grep -E \
'^(port|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin|authorizedkeysfile|allowusers|allowgroups|denyusers|denygroups|authenticationmethods) '
設定ファイルも確認します。
sudo grep -nE \
'^[[:space:]]*(Include|Match|PasswordAuthentication|KbdInteractiveAuthentication|ChallengeResponseAuthentication|PubkeyAuthentication|PermitRootLogin|AuthenticationMethods|AllowUsers|AllowGroups)' \
/etc/ssh/sshd_config
sudo grep -RnE '^[[:space:]]*[^#[:space:]]' \
/etc/ssh/sshd_config.d/
今回の環境では、公開鍵認証とパスワード認証の両方が有効でした。また、環境によっては50-cloud-init.confにもパスワード認証の設定がありました。
Matchによる条件別設定がある場合は、その内容も確認してから変更します。対象ユーザーと接続元について確認するには、次のように-Cを指定します。値は実際の接続条件に置き換え、Match Hostを使っている場合はhostも指定してください。
sudo /usr/sbin/sshd -T \
-C user=example,addr=198.51.100.20,laddr=203.0.113.10,lport=22
設定変更後も同じ条件で確認し、パスワード系認証が無効になっていることを確認します。
ファイアウォールを確認
sudo ufw status verbose
今回の環境ではUFWが有効で、SSHは全IPから許可されていました。
SSHのルール名には、次の2パターンがありました。
22/tcp ALLOW IN Anywhere
または、
22/tcp (OpenSSH) ALLOW IN Anywhere
後で削除するときに使うコマンドが異なるため、確認しておきます。
2. MacでSSH鍵を作成する
ここからは、Macの新しいターミナルで実行します。
ssh-keygen -t ed25519 \
-f ~/.ssh/id_ed25519_example_vps \
-C "example-vps"
鍵を保護するため、パスフレーズを設定します。
次の2ファイルが作成されます。
| ファイル | 用途 |
|---|---|
~/.ssh/id_ed25519_example_vps |
秘密鍵。Macに保管する |
~/.ssh/id_ed25519_example_vps.pub |
公開鍵。VPSに登録する |
秘密鍵はVPSに送ったり、他人に共有したりしません。
同じ名前のファイルがすでに存在する場合は、上書きせず、別のファイル名にします。
3. VPSに公開鍵を登録する
Mac側で実行します。
cat ~/.ssh/id_ed25519_example_vps.pub | ssh example@203.0.113.10 \
'umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys; chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys'
この段階では、VPSのログインパスワードを入力します。
公開鍵はauthorized_keysに追記します。既存の鍵を消さないよう、>ではなく>>を使っています。
rootで接続している環境では、example@をroot@に置き換えます。
4. 公開鍵だけで新規ログインする
Macの別ターミナルで実行します。
ssh -S none \
-o IdentitiesOnly=yes \
-o PreferredAuthentications=publickey \
-o PasswordAuthentication=no \
-o KbdInteractiveAuthentication=no \
-i ~/.ssh/id_ed25519_example_vps \
example@203.0.113.10
このコマンドでは、既存のSSH接続を使い回さず、公開鍵認証での接続を確認します。SSH設定に別のIdentityFileがある場合はそれも候補になるため、鍵を厳密に確認したいときは-vを付けて認証ログも確認します。
次の表示は、秘密鍵のパスフレーズを求めています。VPSのログインパスワードとは別です。
Enter passphrase for key ...
ログイン後、ユーザーと管理者権限を確認します。
whoami
sudo -v
sudoでユーザーパスワードを求められるのは正常です。SSHのパスワード認証を無効化しても、sudo用のパスワードはそのまま使えます。
rootの場合は、whoamiでrootと表示されることを確認します。
5. SSHのパスワード認証を無効化する
ここからはVPS側で実行します。
今回の環境では、/etc/ssh/sshd_configの冒頭付近に次の設定がありました。
Include /etc/ssh/sshd_config.d/*.conf
そこで、専用の設定ファイルを追加しました。同名ファイルがすでにある場合は、先に内容を確認して保存しておきます。
sudo tee /etc/ssh/sshd_config.d/00-local-auth.conf > /dev/null <<'EOF'
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
各設定の意味は次のとおりです。
| 設定 | 意味 |
|---|---|
PubkeyAuthentication yes |
公開鍵認証を有効にする |
PasswordAuthentication no |
パスワード認証を無効にする |
KbdInteractiveAuthentication no |
キーボード対話型認証を無効にする |
PermitRootLogin prohibit-password |
rootのパスワード系認証を禁止する |
rootの公開鍵ログインは許可したままです。rootのSSHログイン自体を禁止する設定ではありません。すでにPermitRootLogin noでrootログインを禁止している環境では、その設定を維持し、上のPermitRootLogin prohibit-password行は追加しません。
OpenSSHの多くの設定項目は、先に読み込まれた値が使われます。今回の構成では、00-local-auth.confを50-cloud-init.confより先に読み込ませます。
環境によって読み込み順や条件別設定が異なるため、ファイルを書くだけで終わらず、実効設定も確認します。
構文チェックと反映
sudo /usr/sbin/sshd -t && sudo systemctl reload ssh
構文チェックに成功した場合だけ、SSH設定を再読み込みします。エラーが出た場合は、その内容を修正してから進めます。
実効設定を確認
sudo /usr/sbin/sshd -T | grep -E \
'^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin) '
今回の環境では、次のように表示されました。
permitrootlogin without-password
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
without-passwordは、ここではprohibit-passwordと同じ意味です。
この変更は、条件別設定がなければ他のSSHユーザーにも適用されます。自動処理や他の利用者がいる場合も、鍵で接続できることを確認します。
Macからもう一度、新規ログイン
ssh -S none \
-o IdentitiesOnly=yes \
-o PreferredAuthentications=publickey \
-i ~/.ssh/id_ed25519_example_vps \
example@203.0.113.10
ログインできたことを確認してから、IP制限に進みます。
6. SSHの接続元IPを制限する
今回の環境ではUFWがすでに有効で、許可ルールのない外部からの接続を拒否する設定でした。
UFWが無効な環境では、Webサイトなどに必要な許可ルールを確認せずに有効化しないでください。
現在の接続元IPを確認
VPS側で実行します。
CLIENT_IP="${SSH_CONNECTION%% *}"
printf '許可するIP: %s\n' "$CLIENT_IP"
出力例:
許可するIP: 198.51.100.20
空欄の場合は作業を止め、SSH接続したシェルで確認し直します。管理コンソール上ではSSH_CONNECTIONは通常設定されません。
これはVPSから見た接続元IPです。VPNや踏み台経由の場合は、その出口のIPになることがあります。
接続元IPを先に許可
sudo ufw allow from "$CLIENT_IP" to any port 22 proto tcp
全IP向けのSSH許可を削除
最初に確認したルール名に合わせて、以下のどちらかを実行します。
22/tcpとして登録されている場合:
sudo ufw delete allow 22/tcp
OpenSSHとして登録されている場合:
sudo ufw delete allow OpenSSH
両方のルールがある場合は、両方を削除します。
最終状態を確認
sudo ufw status verbose
SSHについて、次のように特定IPだけが許可されていることを確認します。
22/tcp ALLOW IN 198.51.100.20
次の全IP向けSSHルールが残っていないことも確認します。
AnywhereAnywhere (v6)
SSHを含むポート範囲や、全ポートを許可するルールがあれば、それも確認します。IPv4だけを許可する場合は、IPv6経由のSSH接続はできなくなります。
Webサイト用の80・443番ポートは変更しません。
7. 最後に新規ログインを確認する
Macの別ターミナルから接続します。
ssh -S none \
-o IdentitiesOnly=yes \
-o PreferredAuthentications=publickey \
-i ~/.ssh/id_ed25519_example_vps \
example@203.0.113.10
既存の接続が使えることと、新規接続できることは別です。 必ず新しい接続で確認します。
IP制限後もログインできれば、作業完了です。元のSSH接続を閉じて構いません。
exit
接続できなくなった場合
まだ開いているSSH接続、またはVPS管理画面のコンソールから、許可IPを確認・修正します。
どうしても一時的にSSHのIP制限を解除する必要がある場合は、次を実行します。
sudo ufw allow 22/tcp
これは全IPからSSHに接続できる状態へ戻す復旧用コマンドです。正常に接続できた場合は実行しません。
公開鍵認証の設定は維持されますが、IP制限は解除されるため、問題を解決したら全IP許可を再び削除します。
接続元IPが変わった場合
固定IPではない回線では、グローバルIPが変わることがあります。その場合は、VPS管理画面のコンソールなどから新しいIPを許可します。
sudo ufw allow from 新しい接続元IP to any port 22 proto tcp
新しいIPから接続できることを確認した後、古いIPの許可を削除します。
sudo ufw delete allow from 古い接続元IP to any port 22 proto tcp
IP制限を使う場合は、管理コンソールへのアクセス方法も把握しておくことが大切です。
作業後の状態
今回の変更で、次の状態になりました。
- SSHログインは公開鍵認証を使用
- SSHのパスワード認証は無効
- SSHへの接続元は指定したグローバルIPのみ
- Webサイト用のHTTP・HTTPSは引き続き公開
各段階で別ターミナルから接続を確認することで、締め出しを避けながら設定を変更できました。

コメント
新しいコメントの受付は停止しています。