はじめての SSH 鍵認証講座 ― ed25519/known_hosts/ssh-agent を使いこなす

毎回パスワードを打ち込み、サーバー名やIPを探してはため息…そんな“接続の負担”を、学習で根本から軽くしていくのが本講座です。

ここでは ed25519 での鍵作成から、公開鍵の配備、~/.ssh/config の設計、known_hosts の仕組み、そして ssh-agent を使ったパスフレーズの安全運用までを、はじめての方でも迷わず進められる順番で学びます。

学び方はシンプルです。まずは 5分のクイックスタート で「無パス接続」を体験し、続いて“なぜ動くのか”を噛み砕いて理解します。そのうえで、複数環境や踏み台サーバー(ProxyJump)にも耐える 実務向けConfigテンプレート を整え、つまずきやすい Permission denied (publickey) の原因切り分けまで押さえます。専門用語はその場で説明し、コピペで試せるサンプルを豊富に用意します。

この講座を終えると、毎日の接続は「ssh srv」のように短く、権限や鍵の置き場所も迷わず、複数の鍵・複数の環境を 安全かつ一貫したルール で扱えるようになります。セキュリティを犠牲にせず、作業スピードを上げる。そのための最小で確かな知識と手順を、一緒に身につけていきましょう。

学習ゴールと前提環境

到達目標(無パス接続・安全運用・多環境対応)

この講座のゴールは、毎回パスワードを入力しなくても安全に接続できる「無パス接続(公開鍵認証)」を自分で構築し、仕事でよくある“サーバーが複数ある・踏み台を経由する・鍵が増えていく”という状況でも迷わず運用できる状態になることです。具体的には、ed25519形式の秘密鍵と公開鍵を作成し、サーバーに配備して動作させ、~/.ssh/configで接続名を短くまとめ、known_hostsの意味を理解して初回警告に慌てず対応できるようにします。さらに、ssh-agentを使ってパスフレーズを守りながら快適に使えるところまで一気に進めます。

想定OS(Linux/macOS/WSL)と必要ツール

前提として、クライアント側にOpenSSHが入っていることを想定します。LinuxディストリビューションやmacOSでは最初から利用できることが多く、WindowsではWSL(Linux)か、Windows版OpenSSHクライアントを使うのが一般的です。サーバー側もOpenSSHを想定しますが、設定ファイルの細かい違いがあっても、公開鍵認証の基本は同じです。もし社内のセキュリティポリシーで制約がある場合は、パスワード認証の無効化など“サーバー側の変更”を行う前に、必ず運用ルールを確認してください。

いま困っている典型シナリオの整理

おそらくあなたは、長いコマンドを毎回打って、Permission denied (publickey)に悩まされ、踏み台経由の複雑なコマンドにため息をついた経験があるはずです。この講座では、まず“たった数行”で無パス接続を体験し、そのあとで「なにが起きたのか」をやさしくほどいていきます。原因の切り分けも、専門的なログの読み方を必要最小限に絞り、手を動かしながら自然に身につく流れにしています。

クイックスタート:5分で無パス接続を体験

最短手順(鍵作成→配備→初回接続)

まずは動かしてみましょう。以下の3ステップで「無パス接続」を体験します。実行はクライアントPC上です。

1つ目は鍵の作成です。コメント部分は自分が識別しやすい文字列にしてください。保存先はデフォルトの~/.sshで問題ありません。

ssh-keygen -t ed25519 -C "you@example.com" -f ~/.ssh/id_ed25519

パスフレーズを求められます。ここは空にせず、覚えられる強度のパスフレーズを設定してください。のちほどssh-agentで便利に扱えるようにします。

2つ目は公開鍵のサーバー配備です。user@serverは実際のユーザー名とホスト名(またはIP)に置き換えてください。22番以外のポートなら-p 2222のように付けます。

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

3つ目は接続の確認です。ここでは明示的に秘密鍵を指定して接続してみます。

ssh -i ~/.ssh/id_ed25519 user@server

パスワード入力なしでログインできれば成功です。初回接続時にホスト鍵の確認が出たら、指紋を確認のうえでyesと応答します。もしssh-copy-idが使えない環境の場合は、次の章で“手動配備”の方法を説明します。

動作確認と失敗時の最小チェック

もしPermission denied (publickey)が表示されたら、まずは権限とファイルの場所を確かめます。クライアント側では.sshディレクトリが700、秘密鍵が600であることが大切です。

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519

サーバー側では、ホーム配下の.sshが700、authorized_keysが600になっているか確認します。自分で直せる権限がない場合は管理者に相談してください。原因が見つからないときは、詳しいログを一度だけ眺めます。

ssh -vvv -i ~/.ssh/id_ed25519 user@server

長い出力に圧倒されるかもしれませんが、まずは「どの鍵を試しているか」「公開鍵が拒否されたか」の2点だけ追えば十分です。深追いは後の“つまずき解決”で一緒に練習しましょう。

体験から学ぶ全体像(何が起きたか)

ここまでで、クライアントが秘密鍵、サーバーが公開鍵のコピーを使って本人確認をしていること、初回接続でサーバーの“顔(ホスト鍵)”をknown_hostsに登録して安全性を確かめていることを、手と目で感じられたはずです。無理に暗記する必要はありません。次の章で、作業をもう少し丁寧に整えて、毎日使う基礎づくりをしていきます。

鍵の作成と配備:ed25519 を基本に

ssh-keygen の実践(コメント・保存先・パスフレーズ)

鍵の作成は先ほど一度行いましたが、オプションの意味を知っておくと安心です。-t ed25519は鍵の方式を指定しており、現行では軽快で安全性の高い選択肢です。-Cは鍵にメモを付けるだけで、実運用に影響はありません。-fで保存先を指定しない場合は、既定の~/.ssh/id_ed25519が使われます。すでに同名の鍵があるなら、上書きしないよう別名にしましょう。

ssh-keygen -t ed25519 -C "laptop personal key" -f ~/.ssh/id_ed25519

パスフレーズは“秘密鍵を盗まれた時の最後の砦”です。覚えにくい場合は、後でssh-agentに登録して都度入力を省けます。ここで設定しておくのが安全です。

サーバーへの公開鍵配備(ssh-copy-id/手動配置)

ssh-copy-idが使える環境であれば、先ほどのコマンドのとおりで十分です。内部では、サーバー側の~/.ssh/authorized_keysに公開鍵の1行を追記してくれています。もしこのコマンドがない場合は、公開鍵の中身を手で貼り付ければ同じ結果が得られます。

# クライアントで公開鍵の中身を表示
cat ~/.ssh/id_ed25519.pub

表示された1行をコピーし、サーバーにパスワードでログインしてから次のように貼り付けます。

# サーバー上で
mkdir -p ~/.ssh
chmod 700 ~/.ssh
printf '%s\n' 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...' >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

ここでのポイントは“1行であること”と“余計な空白や改行を入れないこと”です。ファイルの末尾に追記する形なら、複数の公開鍵を共存させることもできます。混乱を避けるため、コメント(-Cで付けた文字列)に誰の鍵かを分かるようにしておきましょう。

権限の正解(~/.ssh・authorized_keys のパーミッション)

公開鍵認証は、ファイルの権限が“緩すぎる”だけで拒否されます。クライアント側は.sshが700、秘密鍵が600、公開鍵は644でも構いません。サーバー側は.sshが700、authorized_keysが600です。もしホームディレクトリ自体の権限が緩く(グループや他人に書き込み可能)なっていると、そこでも弾かれます。気になるときは一度だけ厳しめに整えてしまいましょう。

# クライアント
chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519
# サーバー
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys

クラウドイメージや特定ディストリビューションでは、SELinuxやAppArmorの都合でホーム配下に特別なコンテキストが必要なことがあります。もし権限が正しいのに弾かれるときは、無理に設定を変えず、/var/log/securejournalctl -u sshのログを確認するか、管理者に相談してください。

ここまで整えると、ssh -i ~/.ssh/id_ed25519 user@serverで安定してログインできるはずです。次は、毎日の接続を楽にするためのknown_hosts~/.ssh/configの設計に進みます。

known_hosts を理解する:なぜ聞かれるのか

初めてサーバーに接続すると、「このホストを信頼しますか?」という確認が出ます。これはサーバーの“顔”にあたるホスト鍵の指紋を、あなたのPCの~/.ssh/known_hostsに保存してよいかどうかを尋ねています。ここでyesと答えると、以後は同じ“顔”かどうかを毎回照合し、もしサーバーがすり替わっていれば警告してくれます。つまり、パスワードの入力有無に関係なく、なりすまし攻撃を防ぐ重要な仕組みです。

表示されるメッセージは次のようなものです。細部は環境で異なりますが、指紋(fingerprint)を確認してから進みます。

The authenticity of host '203.0.113.10 (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:abcDEF...123.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

社内やクラウドで構築したサーバーなら、管理者から事前に指紋を共有してもらうのが理想です。自分で確認できる場合は、サーバー側で次のようにホスト鍵の指紋を出せます(権限が必要です)。

# サーバー側での例(ed25519)
ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub

既に信頼済みのサーバーで、IPの使い回しやDNS変更があったときにホストキー不一致の警告が出ることがあります。誤って上書きせず、一度登録を削除してから再登録すると安全です。

# 旧情報の削除(ホスト名やIPに置き換え)
ssh-keygen -R example.com
# 初回接続で自動登録(指紋を再確認)
ssh -o StrictHostKeyChecking=accept-new user@example.com

StrictHostKeyCheckingは“確認の厳しさ”を調整する設定です。既知の鍵は厳密に照合しつつ、新規ホストは初回だけ自動登録したい、という現実的な運用にはaccept-newが向いています。後ほど~/.ssh/configの共通設定で使い方を示します。

~/.ssh/config の基本設計

毎回長いssh user@host -i ~/.ssh/id_ed25519 -p 2222を打つのは、ミスの温床です。接続に“名前”を付け、鍵やユーザー、ポートをひとまとめにしておくと、作業はぐっと軽くなります。まずは最小構成から始めて、動くことを確かめましょう。

# ~/.ssh/config (パーミッションは600を推奨)
Host srv
  HostName 203.0.113.10
  User deploy
  Port 22
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

保存したら、単にssh srvと打つだけで接続できます。IdentitiesOnly yesは「ここで指定した鍵だけを使って認証する」という意味で、手元に鍵が増えたときの“総当たり”を防ぎ、無関係な鍵で拒否される事故を避けます。Host srvの部分はあなたが覚えやすい短い別名にして構いません。

複数のサーバーを扱うときは、エントリを並べていきます。コメントを付けて、目的が分かるようにしておくと後で助かります。

Host db
  HostName db.internal.example.com
  User postgres
  IdentityFile ~/.ssh/id_ed25519_db
  IdentitiesOnly yes
  Port 2222  # カスタムポートの例

Host web
  HostName 198.51.100.20
  User ubuntu
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

全ての接続に共通する“お作法”は、ワイルドカードのHost *で一度にまとめると管理が楽です。たとえばホスト鍵の初回登録を緩やかにしたい、鍵をエージェントに自動登録したい、といった方針をここへ集約します。macOSではキーチェーン連携の1行を添えると、再起動後もパスフレーズの入力がほぼ不要になります。

# すべての接続に共通する既定値
Host *
  ServerAliveInterval 30
  ServerAliveCountMax 3
  StrictHostKeyChecking accept-new
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ed25519

# macOSのみ:キーチェーン連携(無関係なら省略可)
Host *
  UseKeychain yes

設定後は、設定ファイル自体の権限も確認しておきましょう。chmod 600 ~/.ssh/configとしておくと無用な警告を避けられます。ここまでできたら、あなたの毎日の接続はすでに短く、間違いにくい形に整っています。次は、踏み台サーバーを経由する複雑な経路や、環境が増えても疲れないための設計に踏み込みます。

踏み台・多環境対応の実践

業務では、社外から直接入れない内向きサーバーに、踏み台(bastion)を経由して入る場面がよくあります。ここでも毎回長いコマンドを書かずに、~/.ssh/configで経路も鍵もまとめてしまいましょう。踏み台はひとつの“中継点”として名前を与え、実サーバー側はその踏み台を通る前提で定義します。

# 踏み台(インターネットから到達できる)
Host bastion
  HostName bastion.example.com
  User ops
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

# 業務アプリ群(踏み台経由で内向きへ)
Host app-*
  User deploy
  ProxyJump bastion
  IdentityFile ~/.ssh/id_ed25519_deploy
  IdentitiesOnly yes

ProxyJumpは“踏み台を経由せよ”という合図です。これを入れておけば、ssh app-01のように短い名前でも自動で踏み台を通ってくれます。サーバーが増えてきたら、Host app-*のようにワイルドカードでまとめると、共通のポリシーを崩さずに増設できます。もしプロジェクトごとに設定を分けたいときは、Includeでファイルを分割すると見通しがよくなります。

# ~/.ssh/config の先頭などに共通設定
Host *
  StrictHostKeyChecking accept-new
  AddKeysToAgent yes

# conf.d配下の *.conf を読み込む
Include ~/.ssh/conf.d/*.conf

分割したファイルには、環境名が伝わるような名前を付けると親切です。たとえば ~/.ssh/conf.d/prod.conf に本番系、staging.conf に検証系、という具合です。チームで共有する場合は、鍵のパスやユーザー名を各自の環境に合うように変数化したくなりますが、まずは“迷わず動くこと”を優先し、役割ごとに鍵を分けるほうが安全で扱いやすいことが多いです。

ssh-agent とパスフレーズ運用

秘密鍵には必ずパスフレーズを付けておきたい一方で、毎回の入力は負担になります。ここで活躍するのが ssh-agent です。エージェントは“いったん解錠した鍵を、しばらく安全に預かっておく小さな番人”のような存在で、登録後はパスフレーズの再入力なしに接続できます。

まずは手元の鍵をエージェントへ登録してみます。デスクトップ環境では多くの場合、ログイン時にエージェントが自動で立ち上がっています。

# 鍵の登録(初回のみパスフレーズ入力)
ssh-add ~/.ssh/id_ed25519

# 登録状況の確認
ssh-add -l

macOSでは、キーチェーンへの保存を有効にすると再起動後も快適です。既に例に挙げた UseKeychain yesAddKeysToAgent yes~/.ssh/config に入れておけば、初回登録以降はほぼ“存在を意識しない”運用になります。Linuxでも GNOME Keyring や KDE Wallet と連携するディストリビューションが増えており、デスクトップログイン時に自動で鍵が解錠されることがあります。

注意したいのは ForwardAgent です。これは“踏み台にもエージェントの鍵を渡して、さらに奥のサーバーで使えるようにする”仕組みですが、踏み台が信頼できない環境だとリスクが上がります。基本方針としては ProxyJump で経路を組み、ForwardAgent は使わないのが無難です。どうしても必要な場面では、接続先を限定した上で一時的に使い、作業後に ssh-add -D で登録鍵を空にするなど、扱いを明確に区切ると安全です。

つまずき解決:Permission denied をほどく

公開鍵認証で最も多いエラーは、やはり Permission denied (publickey) です。焦らず順番にほどいていきましょう。まずはクライアント側で、どの鍵を試しているのか、そしてサーバーからどう見えているのかを確認します。

# まずは冗長モードで観察
ssh -vvv -i ~/.ssh/id_ed25519 user@server

冗長出力では、Offering public key: ...Authentications that can continue: publickey のような行が見つかります。ここで提供している鍵が意図したものか、~/.ssh/configIdentityFile と一致しているかを確かめます。鍵が違っていたり、IdentitiesOnly yes を入れていないために無関係な鍵を総当たりしているようなら、設定を見直します。

サーバー側に入れる場合は、認証ログが強い味方です。systemd 系であれば次のように直近の失敗原因を追えます。

# サーバーでのログ確認例
sudo journalctl -u ssh -n 100 --no-pager
# あるいはディストリビューションによって /var/log/secure /var/log/auth.log

ここで “bad ownership or modes for directory” のような文言が出ていれば、ホームディレクトリや .sshauthorized_keys の権限が緩すぎる可能性があります。ホームの親ディレクトリまで含めて、書き込み権限が第三者に開かれていないかを見直します。SELinux が有効な環境では、権限が正しくてもコンテキスト不整合で拒否されることがあります。その場合は次のコマンドで .ssh 配下のコンテキストを整えます。

# SELinuxのラベルを再付与
sudo restorecon -Rv /home/ユーザー名/.ssh

設定ファイルの見直しも有効です。/etc/ssh/sshd_config において PubkeyAuthentication yes が有効か、AuthorizedKeysFile の場所がデフォルトから変わっていないか、PasswordAuthentication を意図せず無効化していないかを点検します。変更したら忘れずにリロードします。

# 設定を編集したら再読み込み
sudo systemctl reload sshd

古いサーバーでは ed25519 が未対応のこともあります。その場合は一時的に RSA の新しめの長さで作り直し、接続を回復させてから計画的に更新する方法もあります。

# 互換性目的のRSA鍵(必要な場合のみ)
ssh-keygen -t rsa -b 4096 -C "compat" -f ~/.ssh/id_rsa

最後に、意外と多いのが“別ユーザーに入ろうとしている”ケースです。ubuntuec2-user のようなクラウド初期ユーザーを忘れていないか、また authorized_keys を置いた場所がそのユーザーのホームと一致しているかを落ち着いて確認してみてください。

最後に:学びの定着と次の一歩

無パス接続が安定して動くようになったら、運用を“続けられる形”に整えます。

鍵は役割単位で分け、どの鍵がどのサーバーで使われているかを簡単に棚卸しできるよう、~/.ssh/config にコメントを増やしておくと良いでしょう。退職や委託終了などのイベントに備えて、authorized_keys から特定の鍵を安全に外す手順を、実作業とは別にドキュメント化しておくと、いざというときの混乱が減ります。

セキュリティの底上げとして、公開鍵の登録を“どこからでも”にしない工夫も効果的です。authorized_keys の1行に、許可する接続元を制限する from="203.0.113.0/24" の指定を加えると、不正な場所からの試行を早い段階で落とせます。用途に応じて、command="..."no-pty などのオプションで権限を絞り込む設計も覚えておくと、メンテナンス用ユーザーや自動化の安全性が上がります。

次の発展としては、ハードウェアセキュリティキーを使う FIDO2 系の鍵があります。ssh-keygen -t ed25519-sk のように “-sk” を付けて生成するタイプで、物理デバイスによる所持要件が加わるため、秘密鍵の流出に対する耐性が高まります。Windows クライアントを本格的に使う場合は、WSL で Linux と同じ体験を得る方法と、Windows 版 OpenSSH クライアントをそのまま使う方法の二本立てで、チーム内の手順を合わせておくと学習コストを抑えられます。

最後に、今日つくった ~/.ssh/config は“あなたの接続の言語”です。読みやすい別名、役割が伝わるコメント、共通設定のまとめ方を少しずつ磨くほど、未来のあなたは楽になります。うまくいかないときは、ssh -vvv とサーバーのログに戻り、今回学んだ順番で静かにほどいていきましょう。できるだけ短い手数で、長く安全に。これが公開鍵認証を“自分の道具”にするための、いちばんの秘けつです。

参考・参照リンク

学びを“実務”へつなぐ最短ルート

独学で積み上げた「わかった」を、仕事で使える「できる」へ。
学習ハブの内容を踏まえて、実務に直結する学習設計・添削・質問環境を整えたい人は、下記のページで具体的な進め方を確認してください。

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする