SSH とは — 仕組み・公開鍵認証・主要コマンド のサムネイル

SSH とは — 仕組み・公開鍵認証・主要コマンド

⏱ 約 8 分 view 167 like 0 LOG_DATE:2026-05-09
目次 / TOC

SSH (Secure Shell) は、ネットワーク越しに別のコンピュータへ安全にアクセスし、リモート操作とファイル転送を行うためのプロトコル。Telnet / rlogin など平文プロトコルが抱えていた盗聴・改ざん・なりすましを一掃した。本稿では接続の 3 ステップ、公開鍵認証、ファイル転送、ポートフォワーディング、最低限おさえたい設定までを実用ベースで整理する。

01

SSH の立ち位置 #

SSH は TCP 22 番ポートで動き、RFC 4253 で標準化されている。サーバ運用・GitHub への push・CI/CD のデプロイなど現代の開発に不可欠なインフラの一つ。OpenSSH (OpenBSD 由来の OSS 実装) がほぼあらゆる Linux / macOS / Windows 10 以降に同梱され、事実上の標準となっている。

▸ なぜ Telnet ではダメだったか

Telnet はユーザ名 / パスワード / コマンド出力すべてを平文でネットワークに流す。同セグメントで tcpdump を回せば認証情報が丸見えだった。SSH は暗号化 + ホスト認証 + ユーザ認証を 1 つのプロトコルに統合し、この問題を完全に解いた。

02

接続の 3 ステップ #

SSH の接続シーケンスは次の順で進む。この骨格を掴めば仕組みの理解は終わったも同然。

1. ホスト認証
クライアントが「相手は本物のサーバか?」を検証。サーバがホスト鍵で署名し、フィンガープリントを ~/.ssh/known_hosts に保存。
2. ユーザ認証
サーバが「相手は本物のユーザか?」を検証。パスワード or 公開鍵で本人確認。
3. 暗号化通信
Diffie-Hellman で双方が独立に生成した共通鍵を確立。以降のデータは ChaCha20-Poly1305AES-GCM で暗号化。

自分で動かして確かめる — TCP 接続から鍵交換・ホスト認証・ユーザ認証を経て暗号化シェルが確立するまでを 1 ステップずつ追える。

ホスト認証 — TOFU モデル #

初回接続時、クライアントには未知のホスト鍵フィンガープリントが提示される。これを known_hosts に保存し、2 回目以降は一致を検証する。これを TOFU (Trust On First Use) モデルと呼ぶ。

初回接続時に出るホスト鍵警告
The authenticity of host 'example.com' can't be established. ED25519 key fingerprint is SHA256:abcd1234... Are you sure you want to continue connecting (yes/no/[fingerprint])?
▸ 初回だけは MITM の窓が開く

TOFU の盲点は「最初の 1 回」。厳密な運用ではサーバ管理者が事前にフィンガープリントを別経路(社内 Wiki / 認証アプリ)で公開しておき、初回接続でその値と一致するかを目視確認する。

ユーザ認証 — 2 方式 #

方式 仕組み 推奨度
パスワード認証 ユーザ名 + パスワードを暗号化チャネル上で送信 △ ブルートフォースの的
公開鍵認証 クライアントが秘密鍵で署名、サーバが公開鍵で検証 ◎ 本番運用の定石

本番ではパスワード認証を無効化し、公開鍵認証だけを許可するのが標準的な構え。

03

公開鍵認証の仕組み #

公開鍵認証では、対 (ペア) の鍵をクライアント側で作る。

  • 秘密鍵 — 自分の手元から絶対に出さない
  • 公開鍵 — サーバへ事前にコピーしておく
鍵ペアの作成 (Ed25519 推奨)
$ ssh-keygen -t ed25519 -C "your@email" Generating public/private ed25519 key pair. Enter file in which to save the key (/home/user/.ssh/id_ed25519): Enter passphrase (empty for no passphrase): Your identification has been saved in /home/user/.ssh/id_ed25519 Your public key has been saved in /home/user/.ssh/id_ed25519.pub # 秘密鍵: ~/.ssh/id_ed25519 (絶対に外に出さない) # 公開鍵: ~/.ssh/id_ed25519.pub (サーバへコピー)
▸ なぜ Ed25519 か

鍵長が短く、強度が高く、生成・検証も速い。互換性で困らない限り今ならまず Ed25519 を選んでよい。古い OpenSSH (7.0 未満) でしか接続できない場合のみ RSA-4096 にフォールバック。

サーバへ公開鍵を登録 #

ssh-copy-id で authorized_keys に追記
$ ssh-copy-id user@example.com /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub" Number of key(s) added: 1 # サーバ側の ~/.ssh/authorized_keys に追記される (パーミッション 600 も自動セット)

チャレンジ・レスポンスの流れ #

1. 公開鍵を提示
クライアントが「この公開鍵で入りたい」と申告。
2. 乱数チャレンジ
サーバが乱数を生成して送る。
3. 秘密鍵で署名
クライアントが秘密鍵で乱数に署名して返す。
4. 公開鍵で検証
サーバが authorized_keys の公開鍵で署名を検証。一致すれば認証成功。
▸ 秘密鍵はネットワークを流れない

署名計算はクライアント側のみで実行される。秘密鍵本体は線の上を一度も走らない。これがパスワード認証より圧倒的に強い理由。さらに毎回のチャレンジが乱数なのでリプレイ攻撃にも耐性がある。

04

基本コマンド #

接続バリエーション
# 標準接続 $ ssh user@example.com # ポート指定 $ ssh -p 2222 user@example.com # 鍵ファイル指定 $ ssh -i ~/.ssh/special_key user@host # 単発コマンド実行 (シェルを起こさない) $ ssh user@host 'uptime' # 詳細ログ (トラブル切り分け時) $ ssh -vvv user@host
鍵管理コマンド
# 新規鍵作成 $ ssh-keygen -t ed25519 # パスフレーズ変更 $ ssh-keygen -p -f ~/.ssh/id_ed25519 # 公開鍵のフィンガープリント確認 $ ssh-keygen -l -f ~/.ssh/id_ed25519.pub # 鍵更新時に known_hosts から旧鍵を削除 $ ssh-keygen -R example.com
▸ ssh-agent でパスフレーズ再入力を省く

秘密鍵にパスフレーズを付けると毎回の打ち込みが面倒。ssh-agent を起動し ssh-add ~/.ssh/id_ed25519 で 1 度だけ復号しておけば、セッション中は再入力不要。パスフレーズなしの鍵は使わないのが鉄則。

05

ファイル転送 #

SSH の暗号化チャネル上で動くファイル転送方式は 3 つ。用途で使い分ける。

scp / sftp / rsync over SSH
# scp — 単発コピー (シンプル、小規模向け) $ scp local.txt user@host:/path/ $ scp -r local-dir/ user@host:/path/ # sftp — 対話的なファイル操作 (ls / cd / get / put) $ sftp user@host sftp> get remote.txt sftp> put local.txt # rsync over SSH — 差分転送 (大量ファイル / バックアップに最適) $ rsync -avz -e ssh src/ user@host:/dst/
06

ポートフォワーディング #

SSH 接続の暗号化チャネルに別のアプリの通信を相乗りさせる機能。3 パターンある。

パターン フラグ 用途の典型例
ローカルフォワード -L 手元から踏み台越しのリモート DB に直接接続
リモートフォワード -R 手元のアプリを一時的に外部サーバへ公開 (ngrok 代替)
ダイナミック -D SOCKS プロキシ。ブラウザを SSH 経由で出口接続
踏み台越しに PostgreSQL へ直結
# bastion に接続しつつ、ローカル 5432 を bastion の見える 5432 に転送 $ ssh -L 5432:localhost:5432 user@bastion.example.com # 別ターミナルで localhost に対して psql を叩くだけ $ psql -h localhost psql (16.0) postgres=#

多段踏み台 — ProxyJump #

-J で踏み台をチェーン
# 1 段 — bastion 経由で internal へ $ ssh -J user@bastion user@internal-server # 多段 — b1 → b2 → target $ ssh -J user@b1,user@b2 user@target # 古い ProxyCommand 記法 (今は -J で済むので非推奨)
07

最低限おさえたいサーバ設定 #

/etc/ssh/sshd_config で次の 3 行は必ず効かせる。

sshd_config の最低ライン
# /etc/ssh/sshd_config PermitRootLogin no # root 直接ログイン禁止 PasswordAuthentication no # パスワード認証無効 (公開鍵のみ) PubkeyAuthentication yes # 公開鍵認証を有効化 # 反映前に必ず構文チェック $ sudo sshd -t $ sudo systemctl reload sshd
▸ 自分を締め出さないための手順

設定変更後は今のセッションを閉じない。別ターミナルで再接続テストして、新セッションが確立したのを確認してから古いセッションを切る。PasswordAuthentication no を入れたつもりで打ち間違え、再ログイン不能になった事故は無数にある。

08

~/.ssh/config の便利設定 #

接続先ごとに別名を切ると ssh internal と打つだけで済む。チームでも個人でも、ある程度サーバが増えたら必須。

~/.ssh/config の典型
# 踏み台 Host bastion HostName bastion.example.com User admin Port 2222 IdentityFile ~/.ssh/id_ed25519_admin # 内部サーバ (ProxyJump で踏み台経由) Host internal HostName 10.0.0.5 User deploy IdentityFile ~/.ssh/id_ed25519_deploy ProxyJump bastion # 以後は ssh internal だけで内部サーバに入れる
09

参考 #

𝕏 ポスト B! はてブ