サーバーを管理する仕事をしていると、物理的にそのサーバーの前に座っている機会はほとんどありません。データセンターに設置されたサーバーに、自宅や会社のPCから「まるでその場にいるかのように」コマンドを打って操作する──その仕組みを支えているのがSSH(Secure Shell)です。
SSHは1995年にフィンランドのコンピュータ科学者Tatu Ylönenによって設計・公開されました。きっかけは、Ylönenが勤務していた大学のネットワークで発生したパスワードスニッフィング攻撃(通信を盗聴してパスワードを収集する攻撃)でした。当時広く使われていたtelnetやrloginはすべての通信を平文で送受信していたため、ネットワーク上を流れるパスワードを容易に盗み取ることができたのです。この経験を基に「通信を暗号化した安全なリモートシェル」としてSSHは誕生しました。
現在世界中で使われているのはSSH-2(SSHプロトコルバージョン2)です。SSH-1には脆弱性が発見されており、現代の実装ではSSH-1は使用しないことが原則です。Linuxサーバーに標準搭載されるOpenSSHはSSH-2のみをデフォルトでサポートしています。
📌 この記事でわかること
・SSHの仕組みと「なぜ安全なのか」の技術的な根拠
・WindowsおよびMacからのSSH接続方法(複数手段を比較)
・公開鍵認証の設定手順(最も安全な認証方式)
・SSHのポートフォワーディング・多段SSH・SCPなど実践的な活用技術
・サーバー側で行うべきSSHのセキュリティ強化設定
・SSH接続時のよくあるトラブルと解決策
SSHが「安全」である理由──暗号化の仕組みを理解する
SSHが安全とされる理由は大きく3つあります。①通信の暗号化、②サーバーの本人確認(ホスト認証)、③クライアントの本人確認(ユーザー認証)です。この3つが組み合わさって初めて「安全な通信路」が確立されます。
①通信の暗号化
SSH接続が確立されると、それ以降のすべての通信(コマンド入力、コマンドの結果、転送するファイルのデータなど)は共通鍵暗号方式(AES、ChaCha20など)で暗号化されます。共通鍵の交換にはDiffie-Hellman鍵交換やECDH(楕円曲線Diffie-Hellman)などのアルゴリズムが使われており、たとえ通信を傍受されても内容を解読することはできません。
②ホスト認証(サーバーの本人確認)
SSHに初めて接続する際、クライアントはサーバーからホスト公開鍵を受け取ります。そのフィンガープリント(公開鍵のハッシュ値)を手動で確認することで、「本当に接続したいサーバーに接続しているか」を検証できます。一度確認・保存したホスト鍵は次回以降自動的に照合されるため、中間者攻撃(MITM攻撃)を検知できます。
③ユーザー認証
SSHはユーザー認証に複数の方式をサポートしています。代表的なものがパスワード認証と公開鍵認証です。後述しますが、公開鍵認証の使用が強く推奨されます。
telnetとSSHの比較
| 項目 | telnet / rlogin | SSH |
|---|---|---|
| 通信の暗号化 | なし(平文) | あり(AES・ChaCha20など) |
| ホスト認証 | なし | あり(ホスト鍵) |
| パスワードの安全性 | 盗聴で即座に漏洩 | 暗号化されて送信 |
| 中間者攻撃への耐性 | なし | あり(ホスト鍵照合) |
| デフォルトポート | 23番 | 22番 |
| 現在の利用推奨 | ❌ 使用禁止 | ✅ 標準的に使用 |
⚠️ telnetは現在でも稼働しているサーバーがある
古いネットワーク機器(一部のルーター・スイッチなど)ではtelnetしか対応していないものがあります。そのような機器を管理する際は、必ず同じネットワーク上の第三者が存在しない閉じた環境(管理用VLAN・物理的に隔離されたネットワーク)で作業するか、機器のファームウェアアップデートによるSSH対応を検討してください。
SSH接続の基本的な使い方
Windowsからの接続
Windows 10(バージョン1809以降)およびWindows 11にはOpenSSHクライアントが標準搭載されています。PowerShellまたはコマンドプロンプトから直接 ssh コマンドを使用できます。
# 基本的な接続構文
ssh ユーザー名@ホスト名またはIPアドレス
# 例:IPアドレス 192.168.1.100 に ubuntu ユーザーで接続
ssh ubuntu@192.168.1.100
# ポート番号を指定して接続(デフォルト22以外のポートの場合)
ssh -p 2222 ubuntu@192.168.1.100
OpenSSHクライアントがインストールされているか確認するには、PowerShellで以下を実行します。
# OpenSSHクライアントのインストール確認
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH.Client*'
# インストールされていない場合
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
GUIを使いたい場合は、前回の記事で紹介したPuTTYが定番のSSHクライアントです。PuTTYは https://www.putty.org/ からダウンロードできます(必ず公式サイトから)。
Mac・Linuxからの接続
MacおよびLinuxにはOpenSSHクライアントが標準搭載されています。ターミナルを開いてそのまま ssh コマンドを使えます。
# Mac / Linux での基本的な接続
ssh ubuntu@192.168.1.100
# 秘密鍵を指定して接続
ssh -i ~/.ssh/id_ed25519 ubuntu@192.168.1.100
初回接続時のホスト鍵確認
初めてのサーバーに接続すると以下のようなメッセージが表示されます。
The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
ここで表示されるフィンガープリント(SHA256:〜の部分)を、サーバー上で事前に確認した値と必ず照合してください。サーバー側での確認コマンドは以下のとおりです。
# サーバー上でホスト鍵のフィンガープリントを確認する
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
値が一致していれば yes と入力します。フィンガープリントは ~/.ssh/known_hosts に保存され、以降の接続で自動照合されます。確認せずにyesを押す習慣をつけることは絶対に避けてください。
公開鍵認証の設定──最も安全な認証方式
SSH接続の認証方法として、現場では公開鍵認証(Public Key Authentication)が強く推奨されます。パスワード認証との違いを理解したうえで、設定手順を解説します。
パスワード認証の問題点
- ブルートフォース攻撃(自動化されたパスワード総当たり)の標的になりやすい
- 弱いパスワードや使い回しパスワードが設定されるリスクがある
- フィッシングや情報漏洩でパスワードが流出すると即座に不正アクセスされる
実際、インターネットに公開されたSSHサーバーには、24時間365日、世界中からパスワード総当たり攻撃が試みられています。ログ(/var/log/auth.log や /var/log/secure)を確認すると、その量に驚くはずです。
公開鍵認証の仕組み
公開鍵認証では秘密鍵(Private Key)と公開鍵(Public Key)の2つがペアで機能します。
- 秘密鍵:自分だけが持つ「印鑑」のようなもの。絶対に他人に渡してはいけない
- 公開鍵:サーバーに登録する「印鑑登録証」のようなもの。公開しても問題ない
接続時、サーバーはランダムなデータをクライアントに送り、クライアントは秘密鍵でそれに「署名」して返送します。サーバーは登録済みの公開鍵で署名を検証し、一致すれば本人確認完了です。パスワードはネットワーク上を一切流れません。
ステップ1:鍵ペアの生成
# 最も推奨される鍵タイプ:Ed25519(楕円曲線ベース、高速で安全)
ssh-keygen -t ed25519 -C "your_email@example.com"
# RSA を使う場合(互換性が必要な古いシステム向け)は 4096bit 以上で
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
コマンドを実行するといくつかの質問が出ます。
- 保存先:デフォルト(
~/.ssh/id_ed25519)でよければそのままEnterを押します - パスフレーズ:必ず設定してください。 パスフレーズは秘密鍵ファイルを暗号化します。秘密鍵が盗まれた際の最後の防衛線です
生成されるファイルは2つです。
~/.ssh/id_ed25519── 秘密鍵(厳重管理。絶対に人に渡さない・クラウドにアップしない)~/.ssh/id_ed25519.pub── 公開鍵(サーバーに登録する。公開しても安全)
ステップ2:公開鍵をサーバーに登録する
# ssh-copy-id コマンドを使う方法(最も簡単)
ssh-copy-id -i ~/.ssh/id_ed25519.pub ubuntu@192.168.1.100
# ssh-copy-id が使えない場合(Windowsなど)の手動登録
# 1. 公開鍵の内容を表示
cat ~/.ssh/id_ed25519.pub
# 2. サーバーにパスワードでログインして実行
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "(公開鍵の内容をここに貼り付ける)" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
ステップ3:公開鍵認証で接続できるか確認する
# 公開鍵認証で接続(パスフレーズを聞かれたら秘密鍵のパスフレーズを入力)
ssh -i ~/.ssh/id_ed25519 ubuntu@192.168.1.100
正常に接続できたら、サーバー側でパスワード認証を無効化することを強く推奨します(後述)。
ssh-agent でパスフレーズ入力を省略する
毎回パスフレーズを入力するのが手間な場合は、ssh-agent(鍵管理デーモン)に秘密鍵を一時的に預けることで入力を省略できます。
# ssh-agentを起動(Mac・Linuxは通常自動起動している)
eval "$(ssh-agent -s)"
# 秘密鍵をagentに追加(1回だけパスフレーズを入力する)
ssh-add ~/.ssh/id_ed25519
# 登録済みの鍵を確認
ssh-add -l
Macではキーチェーンと統合されており、ログイン後は自動的にagentに登録することも可能です。~/.ssh/config に AddKeysToAgent yes および UseKeychain yes(Mac)と記載します。
SSH Configファイルで接続を快適に管理する
接続するサーバーが増えてくると、毎回 ssh -i ~/.ssh/鍵ファイル -p 2222 ユーザー名@IPアドレス と長いコマンドを打つのは非効率です。~/.ssh/config ファイルに接続先の情報をまとめておくことで、短いコマンドで素早く接続できるようになります。
# ~/.ssh/config の書き方例
# 本番Webサーバー
Host web-prod
HostName 203.0.113.10
User ubuntu
Port 2222
IdentityFile ~/.ssh/id_ed25519_prod
ServerAliveInterval 60
# 開発サーバー
Host dev-server
HostName 192.168.1.100
User developer
Port 22
IdentityFile ~/.ssh/id_ed25519_dev
# 踏み台サーバー経由でアクセスする内部サーバー
Host internal-db
HostName 10.0.0.50
User admin
ProxyJump bastion-server
Host bastion-server
HostName 203.0.113.1
User ubuntu
IdentityFile ~/.ssh/id_ed25519_bastion
設定後は ssh web-prod のように短いエイリアスで接続できます。ServerAliveInterval 60 は60秒ごとに通信確認パケットを送信して、アイドル状態での接続切断を防ぐ設定です。長時間のオペレーション中に突然切断されることを防げます。
configファイルのパーミッションにも注意が必要です。
# configファイルのパーミッションを適切に設定
chmod 600 ~/.ssh/config
SSHの実践的な活用技術
①ポートフォワーディング(トンネリング)
SSHの強力な機能のひとつがポートフォワーディングです。暗号化されたSSHトンネルを通じて、本来は直接アクセスできないポートやサービスに安全にアクセスできます。
ローカルフォワーディング(-L オプション)は、ローカルPCのポートをSSH経由でリモートサーバーのポートに転送します。
# 使用例:リモートサーバーのMySQLデータベース(ポート3306)に
# ローカルの3307番ポート経由で接続する
# (MySQLポートはファイアウォールで外部からブロックされていることが多い)
ssh -L 3307:localhost:3306 ubuntu@192.168.1.100
# 接続後、別のターミナルでローカルのMySQLクライアントを使って接続
mysql -h 127.0.0.1 -P 3307 -u dbuser -p
リモートフォワーディング(-R オプション)は逆方向の転送で、リモートサーバーのポートをローカルPCに転送します。ファイアウォールの内側にあるローカルのサービスを外部に公開したいときなどに利用されます。
# リモートサーバーの8080番ポートへのアクセスを
# ローカルPC上で動作している3000番ポートのアプリに転送する
ssh -R 8080:localhost:3000 ubuntu@203.0.113.10
ダイナミックフォワーディング(-D オプション)はSOCKS5プロキシを作成し、すべての通信をSSHトンネル経由にします。
# ローカルの1080番ポートにSOCKSプロキシを立てる
ssh -D 1080 ubuntu@192.168.1.100
# ブラウザやアプリのプロキシ設定でSOCKS5 127.0.0.1:1080を指定して使用
②多段SSH(踏み台サーバー・ジャンプホスト)
セキュリティが強化された環境では、インターネットから直接内部サーバーにSSH接続できないよう、踏み台サーバー(Bastion Host / Jump Host)を経由する構成が一般的です。
# -J オプションで踏み台サーバー経由の接続(OpenSSH 7.3以降)
# bastion.example.comを経由してinternal.example.comに接続
ssh -J ubuntu@bastion.example.com admin@internal.example.com
# ~/.ssh/config を使えばさらに簡潔に(前述のProxyJump設定を参照)
ssh internal-db
③SCP / rsync によるファイル転送
SSHを使った安全なファイル転送にはSCP(Secure Copy Protocol)が手軽です。
# ローカル → リモートにファイルをコピー
scp /local/path/file.txt ubuntu@192.168.1.100:/remote/path/
# リモート → ローカルにファイルをコピー
scp ubuntu@192.168.1.100:/remote/path/file.txt /local/path/
# ディレクトリごとコピー(-r オプション)
scp -r /local/directory/ ubuntu@192.168.1.100:/remote/path/
# 秘密鍵を指定してコピー
scp -i ~/.ssh/id_ed25519 file.txt ubuntu@192.168.1.100:/home/ubuntu/
大量のファイルの同期や差分転送にはrsync over SSHが非常に効果的です。
# rsyncでSSH経由の差分同期(変更されたファイルのみ転送される)
rsync -avz -e "ssh -i ~/.ssh/id_ed25519" /local/directory/ ubuntu@192.168.1.100:/remote/path/
# --delete オプションで削除も同期(ミラーリング)
rsync -avz --delete -e ssh /local/directory/ ubuntu@192.168.1.100:/remote/path/
④コマンドのリモート実行
SSH接続して対話的なシェルを開かずに、特定のコマンドだけをリモートで実行することも可能です。スクリプトやcronジョブとの組み合わせで非常に便利です。
# リモートサーバーでコマンドを実行して結果を受け取る
ssh ubuntu@192.168.1.100 "df -h"
ssh ubuntu@192.168.1.100 "sudo systemctl status nginx"
# 複数のコマンドをまとめて実行
ssh ubuntu@192.168.1.100 "uptime && free -m && df -h"
# ヒアドキュメントで複数行のコマンドを送る
ssh ubuntu@192.168.1.100 << 'EOF'
cd /var/www/html
git pull origin main
sudo systemctl reload nginx
EOF
⑤X11フォワーディング(GUIアプリをリモートで使う)
Linuxサーバー上のGUIアプリケーションを、ローカルのディスプレイに表示して操作することも可能です。
# X11フォワーディングを有効にして接続(-X オプション)
ssh -X ubuntu@192.168.1.100
# 接続後、GUIアプリを起動するとローカルのディスプレイに表示される
firefox &
gedit /etc/nginx/nginx.conf &
サーバー側のSSHセキュリティ強化設定
SSHクライアントの使い方だけでなく、サーバー側の設定を適切に行うことが安全なSSH環境の構築には不可欠です。設定ファイルは/etc/ssh/sshd_configです。変更後は必ず sudo systemctl reload sshd(または sudo service ssh reload)で設定を反映させます。
⚠️ 設定変更前の重要な注意事項sshd_config を変更する際は、必ず既存のSSHセッションを維持したまま別のSSHセッションを開いて設定をテストしてください。設定を誤ってSSHが起動できなくなった場合、サーバーにアクセスできなくなります。AWSやVPSの場合は「コンソール接続」などの緊急アクセス手段を事前に確認しておきましょう。
推奨セキュリティ設定一覧
# /etc/ssh/sshd_config の推奨設定
# SSHプロトコルバージョン2のみ使用(デフォルトで2だが明示的に)
# Protocol 2 ← 古いバージョンのOpenSSHでのみ記述が必要
# ────────── 認証設定 ──────────
# rootユーザーへの直接ログインを禁止(最重要設定のひとつ)
PermitRootLogin no
# パスワード認証を無効化(公開鍵認証の設定完了後に有効にする)
PasswordAuthentication no
# 空のパスワードを禁止
PermitEmptyPasswords no
# チャレンジレスポンス認証を無効化(パスワード認証の抜け道になりうる)
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
# 公開鍵認証を明示的に有効化
PubkeyAuthentication yes
# ────────── アクセス制限 ──────────
# SSH接続を許可するユーザーを限定(特定のユーザーのみに制限)
AllowUsers ubuntu deploy-user
# または特定のグループのみ許可
# AllowGroups ssh-users
# ────────── 接続設定 ──────────
# ポート番号を変更する(22以外に。ただしファイアウォール設定も要変更)
# Port 2222 ← 実際のポート番号を指定
# アイドルタイムアウトの設定(300秒=5分間無操作で接続を切断)
ClientAliveInterval 300
ClientAliveCountMax 3
# ログイン試行のタイムアウト
LoginGraceTime 30
# 同時ログイン試行数を制限
MaxStartups 3:50:10
MaxAuthTries 3
# ────────── その他 ──────────
# X11フォワーディング(使わない場合は無効化)
X11Forwarding no
# ログレベルを上げて詳細なログを記録
LogLevel VERBOSE
ポート番号の変更について
SSHのデフォルトポート(22番)を変更することで、自動化された総当たり攻撃ツールの多くを回避できます。ただし、これはセキュリティの「難読化」であり、根本的な解決策ではありません。ポート変更はあくまで「ノイズを減らす」ための補助的な対策と理解したうえで実施してください。公開鍵認証の設定やファイアウォールの設定のほうが本質的に重要です。
fail2banで自動ブロック
fail2banは、ログを監視して一定回数以上のログイン失敗が検知されたIPアドレスを自動的にファイアウォールでブロックするツールです。SSHへのブルートフォース攻撃対策として非常に効果的です。
# Ubuntu / Debian へのインストール
sudo apt update && sudo apt install fail2ban
# fail2banの設定確認(/etc/fail2ban/jail.conf をコピーして編集)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# /etc/fail2ban/jail.local の [sshd] セクション設定例
# [sshd]
# enabled = true
# port = ssh
# maxretry = 5 ← 5回失敗でブロック
# bantime = 3600 ← 1時間ブロック(秒単位)
# findtime = 600 ← 10分以内に5回失敗でカウント
# fail2banの起動と自動起動設定
sudo systemctl enable --now fail2ban
# 現在のBAN状況を確認
sudo fail2ban-client status sshd
ファイアウォール(UFW)でSSHポートを制限する
# UFW(Uncomplicated Firewall)でSSH接続を特定IPからのみ許可する例
# まず現在のルールを確認
sudo ufw status verbose
# SSH(ポート22)を特定IPアドレスからのみ許可
sudo ufw allow from 203.0.113.50 to any port 22
# ポートを変更している場合
sudo ufw allow from 203.0.113.50 to any port 2222
# すべてのIPからのSSHを許可する場合(推奨しないが暫定的な設定として)
sudo ufw allow ssh
SSH接続のトラブルシューティング
「Permission denied (publickey)」が表示される
公開鍵認証に失敗しているエラーです。以下を順番に確認してください。
- サーバーの
~/.ssh/authorized_keysに正しい公開鍵が登録されているか確認(cat ~/.ssh/authorized_keys) ~/.ssh/ディレクトリのパーミッションが700、authorized_keysファイルが600になっているか確認- 接続コマンドで指定している秘密鍵ファイルのパスが正しいか確認
- 詳細ログで原因を確認:
ssh -vvv ubuntu@192.168.1.100(-vを増やすほど詳細)
# サーバー側のパーミッションを修正する
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
# SSHデーモンのログで詳細を確認(Ubuntu / Debian)
sudo journalctl -u ssh -n 50
# または
sudo tail -f /var/log/auth.log
「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」が表示される
保存済みのホスト鍵とサーバーのホスト鍵が一致しない警告です。絶対に無視してはいけません。
正当な原因(サーバーの再構築・OSの再インストール)だと確認できた場合のみ、古いホスト鍵を削除して再接続します。
# 特定のホストの古いホスト鍵を削除する
ssh-keygen -R 192.168.1.100
# または known_hosts ファイルを直接編集して該当行を削除
「Broken pipe」で接続が突然切れる
アイドル状態での接続タイムアウトが原因です。クライアント側の ~/.ssh/config に以下を追記することで防げます。
Host *
ServerAliveInterval 60
ServerAliveCountMax 5
多段SSH(ProxyJump)がうまくいかない
踏み台サーバー経由での接続に失敗する場合、踏み台サーバー上に秘密鍵が保存されているケースがありますが、それは誤った設定です。Agent Forwarding(ForwardAgent yes)を使うことで、ローカルのssh-agentが管理する鍵を踏み台経由で使うことができます。ただしAgent Forwardingは、踏み台サーバーが侵害された際に鍵が悪用されるリスクがあるため、信頼できるサーバーに対してのみ有効にしてください。現代のOpenSSHでは ProxyJump(-J オプション)が推奨されており、Agent Forwardingを使わずに多段接続できます。
まとめ──SSHは「使えて当然」の必須スキル
SSHはサーバー管理・クラウドインフラ運用・DevOps・セキュリティ監査のあらゆる場面で必要とされる、エンジニアの基礎スキルです。「とりあえず接続できる」レベルから、公開鍵認証・ポートフォワーディング・セキュリティ強化設定まで使いこなせるようになると、日常の作業効率が大きく変わります。
今回紹介したセキュリティ設定のポイントを改めてまとめると、以下の順番で対応することをお勧めします。
- 公開鍵認証を設定し、パスワード認証を無効化する(最優先)
- rootへの直接ログインを禁止する(
PermitRootLogin no) - fail2banを導入してブルートフォース攻撃を自動ブロックする
- ファイアウォールで接続元IPアドレスを制限する
- ポート番号を変更してスキャンノイズを減らす(補助的な対策)
- アイドルタイムアウトを設定して放置セッションを切断する
SSHの設定はサーバーの「玄関の鍵」そのものです。一度きちんと設定しておくことで、長期にわたる安全なサーバー運用の基盤になります。ぜひ本記事を参考に、自身の環境を見直してみてください。
📚 参考・公式リソース
・OpenSSH公式サイト:https://www.openssh.com/
・OpenSSH man page(sshd_config):https://man.openbsd.org/sshd_config
・fail2ban公式ドキュメント:https://www.fail2ban.org/wiki/index.php/Main_Page
・NIST SP 800-190(コンテナセキュリティガイド):https://csrc.nist.gov/


コメント