SSH 実践・入門ガイド アウトライン
SSH(Secure Shell)は、ネットワーク経由で離れたコンピュータへ安全にアクセスし、遠隔操作やデータ転送を行うための標準プロトコルです。
現代のインフラ運用、クラウド開発、日常のサーバ管理において、SSH の適切な理解と設定は必須の技術基盤となっています。
本書では、SSH の基礎知識から、Debian および Windows 環境における OpenSSH サーバの立ち上げ手順、クライアント側での安全な鍵生成と接続、ssh-agent に依存しない .ssh/config による明快な接続管理、ポート転送(トンネリング)、そして scp を用いたファイル転送までを体系的に解説します。
章構成
-
SSH の役割と歴史的背景、従来の平文通信との違い、公開鍵暗号方式による安全な認証の仕組み、ホスト認証とフィンガープリントの役割を学びます。
-
Debian GNU/Linux における OpenSSH サーバ(sshd)のインストール、サービスの起動・自動起動、設定ファイル(sshd_config)の編集、パスワード認証の無効化、ファイアウォール設定などのセキュリティ強化策を解説します。
-
Windows 10 / 11 および Windows Server における OpenSSH サーバ機能の導入、サービスの構成、ファイアウォール設定、管理者および一般ユーザーの公開鍵配置ルール(ACL設定)を解説します。
-
クライアント側での安全な鍵ペア生成(Ed25519 推奨)、サーバへの公開鍵登録、基本接続コマンド、初回接続時のホスト鍵検証、リモートコマンド実行手順を学びます。
-
ssh-agentを常駐させずに、~/.ssh/configファイルを用いてホスト情報、ポート番号、秘密鍵(IdentityFile)を明示的に紐付ける方法、複数サーバの切り替え、踏み台サーバ経由の接続設定を解説します。 -
ローカルポート転送(-L)、リモートポート転送(-R)、ダイナミックポート転送(-D / SOCKSプロキシ)の仕組みと具体的なユースケース、および
.ssh/configへの定義方法を解説します。 -
scpコマンドを用いたローカルとリモート間の安全なファイル・ディレクトリ転送手順、オプション指定、.ssh/configのエイリアスを活用した効率的な転送、SFTP プロトコルとの関係を解説します。
第1章 SSHの基本概念と仕組み
SSH とは何か
SSH(Secure Shell、セキュアシェル)は、ネットワークでつながった離れた場所にあるコンピュータ(サーバ)に安全に接続し、コマンド操作やファイル転送を行うためのプロトコル(通信規格)です。
インターネットや社内ネットワークなどの信頼できない経路を通じても、通信内容全体が暗号化されるため、第三者にデータを盗み見られたり改ざんされたりする危険を防ぐことができます。
現在、Unix/Linux や Windows、macOS などの多くの OS で、事実上の標準管理ツールとして広く利用されています。
平文通信の危険性と SSH の登場
SSH が登場する以前は、リモート接続に Telnet や rlogin、ファイル転送に FTP といったプロトコルが使用されていました。
しかし、これらの古いプロトコルは通信データを一切暗号化せず、そのままの平文(プレーンテキスト)で送信する仕様でした。
同一ネットワーク上に悪意を持つ第三者が存在した場合、パケット盗聴ツールを用いることで、送信されたパスワードや重要な業務データが容易に読み取られてしまう重大なセキュリティ上の脆弱性がありました。
SSH は、認証情報(ユーザー名やパスワード)だけでなく、送受信されるすべてのコマンドや出力データを強力に暗号化することで、安全なリモート通信を実現しました。
公開鍵暗号方式による認証の仕組み
SSH の安全性を支える中核技術が「公開鍵暗号方式」です。 公開鍵暗号方式では、数学的に対となる 2 つの鍵(キーペア)を生成して認証を行います。
-
公開鍵(Public Key):
誰に見られても安全な鍵です。南京錠(ロック)に例えられます。接続先となるサーバ側に事前に登録しておきます。
-
秘密鍵(Private Key):
作成者本人だけが厳重に保管しなければならない鍵です。南京錠を開ける本物の鍵に例えられます。外部に漏洩してはいけません。
認証の際、サーバは手持ちの「公開鍵」を使って暗号化された課題(チャレンジ)を作成してクライアントへ送信します。 クライアントは自分だけが持つ「秘密鍵」を使ってこの課題を復号(解決)して送り返すことで、パスワードをネットワーク上に一切流すことなく、正当な本人であることを証明します。
[クライアント (手元 PC)] [SSH サーバ]
│ │
│ 1. 接続要求 (ユーザー名) │
├────────────────────────────────────────────>│
│ │
│ 2. チャレンジ送信 (公開鍵で暗号化したデータ)│
│<────────────────────────────────────────────┤ (authorized_keys の公開鍵を使用)
│ │
│ 3. 秘密鍵で復号して署名を作成 │
│ │
│ 4. 署名(解答)を返送 │
├────────────────────────────────────────────>│
│ │ 5. 署名を検証し、
│ 6. 認証成功・通信開始 │ 本人と確認
│<────────────────────────────────────────────┤
ホスト認証と中間者攻撃の防御
公開鍵認証によってユーザーの身元が確認されますが、逆に「接続しようとしているサーバが、偽物の悪意あるサーバではないか」を確認する仕組みも必要です。これを ホスト認証 と呼びます。
サーバは固有の「ホスト鍵」を持っており、クライアントが初めて接続する際、サーバの公開鍵情報(フィンガープリント)が提示されます。
The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:7v6hX2k...
Are you sure you want to continue connecting (yes/no/[fingerprint])?
利用者が yes と答えると、そのサーバの情報がクライアント側の ~/.ssh/known_hosts というファイルに記録されます。
次回以降の接続では、保存されたホスト情報と自動的に照合されます。もし攻撃者が通信の途中に割り込み、偽のサーバへ誘導しようとする「中間者攻撃(Man-in-the-Middle 攻撃)」が発生した場合、ホスト鍵の不一致が検出され、警告画面が表示されて接続が即座に中断されます。
暗号鍵の暗号化(パスフレーズ)
秘密鍵は手元の PC にファイルとして保存されます。 万が一、PC の紛失やマルウェアへの感染によって秘密鍵ファイルが第三者の手に渡った場合に備え、秘密鍵自体に「パスフレーズ」を設定して保護することができます。
パスフレーズを設定すると、秘密鍵ファイルは強力な暗号で保護され、鍵を利用するたびにパスフレーズの入力が求められるようになります。
これにより、「秘密鍵ファイルを持っていること(所持情報)」と「パスフレーズを知っていること(記憶情報)」の二要素による強固なセキュリティが成立します。
第2章 OpenSSH サーバの環境構築(Debian)
パッケージのインストール
Debian GNU/Linux で SSH 接続を受け付けるには、OpenSSH のサーバデーモンである openssh-server パッケージをインストールします。
管理者権限(sudo または root)で以下のコマンドを実行します。
sudo apt update
sudo apt install -y openssh-server
インストールが完了すると、自動的にホスト鍵の生成と初期設定が行われます。
サービスの起動と自動起動設定
Debian ではインストール完了時に自動的にデーモンが起動しますが、念のため稼働状態と自動起動設定を確認します。
サービス名は ssh です(sshd でもシンボリックリンク経由で動作します)。
# 稼働状態の確認
sudo systemctl status ssh
# サービスの起動
sudo systemctl start ssh
# OS 起動時の自動起動の有効化
sudo systemctl enable ssh
ステータス表示で Active: active (running) と表示されていれば、正常に待機状態となっています。
設定ファイルの構成と編集
OpenSSH サーバの設定ファイルは /etc/ssh/sshd_config です。
最近の Debian では、設定の可読性やパッケージ更新時の競合を防ぐため、/etc/ssh/sshd_config.d/ ディレクトリ配下に個別の設定ファイル(例: local.conf)を配置する方式が推奨されています。
設定ファイルを編集する前に、必ず元の設定のバックアップを取得しておきます。
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
個別設定ファイルを作成して基本セキュリティ設定を記述します。
sudo nano /etc/ssh/sshd_config.d/99-security.conf
サーバのセキュリティ強化設定
外部からの不正アクセスや総当たり攻撃(ブルートフォース攻撃)を防ぐため、以下の項目を設定します。
# ポート番号(標準の 22 から任意のポートに変更する場合)
Port 22
# root ユーザーによる直接ログインを禁止
PermitRootLogin no
# 公開鍵認証の有効化
PubkeyAuthentication yes
# パスワード認証の無効化(公開鍵認証での接続確認後に適用)
PasswordAuthentication no
# 空のパスワードでのログインを禁止
PermitEmptyPasswords no
# 認証の最大試行回数
MaxAuthTries 3
▸ パスワード認証無効化の注意点
最初から PasswordAuthentication no を設定すると、公開鍵が正しく登録されていない場合にサーバへ二度とログインできなくなる恐れがあります。
必ず公開鍵でのログインが完全に成功したことを確認してから、パスワード認証を無効化してください。
設定の構文チェックとサービスの再読み込み
設定ファイルを書き換えたら、サービスを再起動する前に必ず構文チェック(テスト)を実行します。 構文エラーがあると SSH サービスが停止し、接続不能になる危険があります。
sudo sshd -t
エラーが表示されなければ、構文は正常です。設定を反映させます。
# 既存の接続を維持したまま設定を反映
sudo systemctl reload ssh
ポート番号などの変更がある場合は restart を実行します。
sudo systemctl restart ssh
▸ 安全確認の重要ルール
設定反映後、現在開いているターミナルは絶対に切断しないでください。 別の新しいターミナルウィンドウを開き、変更後の設定で正常に SSH ログインできることを確認してから、元の接続を閉じるようにします。
ファイアウォール設定(UFW)
ファイアウォール(UFW)を有効にしている場合は、SSH のポートを開放する必要があります。
標準ポート(22 番)を利用している場合の手順は以下の通りです。
# SSH ポートの許可
sudo ufw allow ssh
# またはポート番号を明示指定
sudo ufw allow 22/tcp
# ファイアウォールの状態確認
sudo ufw status
変更したポート番号(例: 2222 番)を使用している場合は、その番号を明示的に許可してください。
sudo ufw allow 2222/tcp
第3章 OpenSSH サーバの環境構築(Windows)
Windows における OpenSSH サーバの導入
Windows 10(バージョン 1809 以降)、Windows 11、および Windows Server では、OS 標準のオプション機能として OpenSSH サーバが提供されています。
管理者権限で起動した PowerShell を開き、以下のコマンドを実行してインストール状況を確認し、インストールします。
# OpenSSH サーバの利用可能状態を確認
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH.Server*'
# OpenSSH サーバ機能のインストール
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
「RestartNeeded: False」と表示されれば、再起動なしで直ちに利用可能です。
サービスの起動とスタートアップ設定
インストール直後の SSH サーバサービス(sshd)は停止状態であり、スタートアップの種類も手動になっています。
サービスを自動起動に設定し、直ちに起動します。
# スタートアップの種類を自動に変更
Set-Service -Name sshd -StartupType 'Automatic'
# サービスを開始
Start-Service sshd
# 稼働状態の確認
Get-Service -Name sshd
Status が Running になっていれば正常に起動しています。
ファイアウォール受信規則の確認
OpenSSH サーバをインストールすると、通常は自動的に Windows Defender ファイアウォールに受信規則が追加されます。 以下のコマンドで規則が有効になっているか確認します。
Get-NetFirewallRule -Name *ssh* | Select-Object Name, DisplayName, Description, Enabled
もし規則が存在しない場合や無効になっている場合は、手動でポート 22 の受信を許可します。
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' `
-DisplayName 'OpenSSH SSH Server (sshd)' `
-Enabled True `
-Direction Inbound `
-Protocol TCP `
-Action Allow `
-LocalPort 22
設定ファイルの構成
Windows 版 OpenSSH サーバの設定ファイルは、以下のパスに格納されています。
C:\ProgramData\ssh\sshd_config
エクスプローラーでは C:\ProgramData は隠しフォルダとなっています。メモ帳などを管理者権限で開いて編集します。
notepad C:\ProgramData\ssh\sshd_config
Windows における公開鍵配置の重要な違い
Windows 版 OpenSSH で最もつまずきやすいのが、「ログインするユーザーの権限グループによって公開鍵の配置先が異なる」という点です。
1. 一般ユーザーの場合
Administrators グループに属さない一般ローカルユーザーは、Linux と同様にユーザープロファイル配下に公開鍵を配置します。
C:\Users\<ユーザー名>\.ssh\authorized_keys
2. 管理者ユーザー(Administrators グループ)の場合
対象ユーザーが Administrators グループに所属している場合、sshd_config の末尾にあるデフォルト設定によって、ユーザーフォルダ配下の authorized_keys は無視されます。
代わりに、以下のシステム共通ファイルに公開鍵を追記する必要があります。
C:\ProgramData\ssh\administrators_authorized_keys
sshd_config 内の該当定義は以下のようになっています。
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
▸ administrators_authorized_keys のアクセス権限設定
このファイルは、セキュリティ上、アクセス権(ACL)が厳格に保護されている必要があります。 他のユーザーからの読み取り権限が残っていると、安全のために認証が自動的に拒否されます。
公開鍵を配置した後、管理者 PowerShell で以下のコマンドを実行してアクセス権を正しく設定します。
# 権限の継承を無効化し、SYSTEM と Administrators のみにフルコントロールを付与
$path = "C:\ProgramData\ssh\administrators_authorized_keys"
icacls.exe $path /inheritance:r /grant "NT AUTHORITY\SYSTEM:(F)" "BUILTIN\Administrators:(F)"
デフォルト接続シェルの変更(PowerShell への設定)
SSH 接続直後のデフォルトシェルは通常コマンドプロンプト(cmd.exe)です。
これを PowerShell に変更したい場合は、以下のレジストリコマンドを実行します。
# デフォルトシェルを Windows PowerShell に設定
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell `
-Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
-PropertyType String -Force
# PowerShell 7 (pwsh) がインストールされている場合の指定例
# -Value "C:\Program Files\PowerShell\7\pwsh.exe"
設定変更後は、以下のコマンドで SSH サービスを再起動して反映させます。
Restart-Service sshd
第4章 SSH クライアントの基本操作
鍵ペアの生成(ssh-keygen)
クライアント側(手元の作業 PC)で、認証に使用する公開鍵と秘密鍵のペアを生成します。
現代の SSH では、高速かつ極めて安全性の高い Ed25519 方式が強く推奨されています。
ssh-keygen -t ed25519 -C "your_name@example.com"
コマンドを実行すると、以下の対話形式で質問されます。
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):
Enter same passphrase again:
-
保存場所:
特に理由がなければ Enter キーを押し、デフォルトのパス(
~/.ssh/id_ed25519)を選択します。 -
パスフレーズ:
秘密鍵を紛失した際の保護のため、英数字や記号を組み合わせた推測されにくいパスフレーズを入力します。
生成が完了すると、~/.ssh/ ディレクトリに以下の 2 つのファイルが作成されます。
id_ed25519: 秘密鍵(手元 PC で厳重に管理、誰にも渡さない)id_ed25519.pub: 公開鍵(接続先サーバへ登録する)
▸ 秘密鍵のファイル権限(Linux / macOS)
Linux や macOS では、秘密鍵のアクセス権が広すぎると SSH クライアントが警告を出して接続を拒否します。
必ず所有者のみが読み書きできる権限(600)に設定します。
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
サーバへの公開鍵の登録
生成した公開鍵(id_ed25519.pub)の内容を、接続先サーバの ~/.ssh/authorized_keys に登録します。
1. Linux サーバへの自動登録(ssh-copy-id)
クライアントが Linux や macOS、WSL の場合、ssh-copy-id コマンドを使うことでワンステップで安全に登録できます。
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 22 username@192.168.1.100
サーバのログインパスワードを 1 度入力すると、サーバ側の ~/.ssh フォルダ作成、権限調整、および鍵の追記が自動的に完了します。
2. Windows サーバまたは手動での登録
ssh-copy-id が使用できない環境では、公開鍵の内容を直接コピーしてサーバ側のファイルに追記します。
PowerShell からリモートの Windows または Linux サーバへ転送・追記する例です。
# クライアント側で公開鍵の内容を取得
$pubKey = Get-Content ~\.ssh\id_ed25519.pub
# サーバ側の authorized_keys に追記する(SSH でコマンドを実行)
ssh username@192.168.1.100 "mkdir -p ~/.ssh && echo '$pubKey' >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
基本的な接続コマンド
公開鍵の登録後、ssh コマンドで接続テストを行います。
# 基本接続構文
ssh username@192.168.1.100
# ポート番号を変更している場合(-p オプション)
ssh -p 2222 username@192.168.1.100
# 使用する秘密鍵を明示的に指定する場合(-i オプション)
ssh -i ~/.ssh/id_ed25519 username@192.168.1.100
パスフレーズを設定している場合は、接続時にパスフレーズの入力を求められます。認証に成功すると、サーバのシェルプロンプトが表示されます。
接続を終了するには exit コマンドを実行します。
初回接続時のホスト鍵確認と known_hosts
初めてのホストへ接続する際、以下の確認メッセージが表示されます。
The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:abcd1234efgh5678...
Are you sure you want to continue connecting (yes/no/[fingerprint])?
ここで yes を入力すると接続が続行され、クライアントの ~/.ssh/known_hosts に相手先サーバのホスト公開鍵が記録されます。
▸ ホスト鍵変更警告への対処
サーバを再構築した場合などに、次回接続時に以下の警告が発生することがあります。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
これは「以前記録されたホスト鍵と、現在のサーバのホスト鍵が異なる」という重大な警告です。 正規のサーバ再構築であることが確認できている場合に限り、以下のコマンドで古い鍵情報を消去して再接続します。
ssh-keygen -R 192.168.1.100
詳細ログ出力による接続トラブルシューティング
接続がうまくいかない場合、-v(Verbose: 詳細)オプションを付与して実行すると、接続・認証処理の内部ログが画面に表示されます。
# 詳細ログ(-v、さらに詳しい -vv、最も詳細な -vvv)
ssh -v -i ~/.ssh/id_ed25519 username@192.168.1.100
どの秘密鍵を試行したか、サーバからどのような認証方式が返されたか、どこで拒否されたかが明確に判別できます。
リモートコマンドの実行
SSH はインタラクティブなシェルログインだけでなく、リモートサーバ上で特定のコマンドを単発実行して結果を受け取ることができます。
# サーバのディスク使用量を確認
ssh username@192.168.1.100 "df -h"
# サーバの特定サービスの状態を確認
ssh username@192.168.1.100 "systemctl status nginx"
手元のスクリプトやバッチ処理から遠隔の作業を自動化する際に非常に重宝します。
第5章 .ssh/config による接続管理
なぜ ssh-agent を使わずに .ssh/config を使うのか
SSH の接続管理では、パスフレーズ入力を省略・保持するために ssh-agent を利用する方法が紹介されることがあります。
しかし、ssh-agent はバックグラウンド常駐プロセスの管理や環境変数の引き継ぎが必要であり、端末の再起動や新しいシェル起動時にプロセスが二重起動したり切断されたりする管理上の煩雑さがあります。
また、エージェントに多数の秘密鍵が登録されていると、接続時に保有するすべての鍵を順次試行してしまい、サーバ側の最大試行回数を超過して Too many authentication failures エラーで接続が拒否されるトラブルが頻発します。
これに対し、クライアント設定ファイル(~/.ssh/config)のみを用いた管理方式には以下の決定的な利点があります。
-
プロセスの常駐が不要:
単なるプレーンテキストの設定ファイルであるため、エージェントプロセスの起動や状態を気にする必要がありません。
-
ホストと秘密鍵の完全な 1 対 1 紐付け:
どのサーバにどのユーザー名、ポート番号、秘密鍵でアクセスするかが設定ファイル上で明示的に宣言され、意図しない鍵の誤用や試行オーバーを完全に防ぐことができます。
-
極めて短いコマンド実行:
長大なホスト名やポート指定、秘密鍵オプションを入力することなく、短い別名(エイリアス)を指定するだけで接続が完了します。
.ssh/config の基本構文と主要ディレクティブ
クライアントのホームディレクトリ配下に config ファイルを作成します。
~/.ssh/config
基本構成は Host <エイリアス> から始まり、インデントして接続パラメータを記述します。
Host dev-server
HostName 192.168.1.50
User developer
Port 22
IdentityFile ~/.ssh/id_ed25519_dev
IdentitiesOnly yes
主要ディレクティブの意味
-
Host:
コマンドラインで指定する接続エイリアス(別名)です。任意の識別しやすい文字列を指定します。
-
HostName:
実際の接続先 IP アドレス、またはドメイン名(FQDN)を指定します。
-
User:
ログインするリモートサーバ上のユーザー名を指定します。
-
Port:
接続先の SSH ポート番号を指定します(省略時は 22)。
-
IdentityFile:
このホストへの接続に使用する秘密鍵のパスを指定します。
-
IdentitiesOnly yes:
極めて重要なディレクティブです。明示的に指定した
IdentityFileの鍵のみを認証に使用するよう SSH クライアントに強制します。デフォルト鍵や他の鍵を自動試行させないことで、認証エラーを根本から排除します。
実践的な設定例
複数のサーバを用途別に整理し、全ホスト共通のタイムアウト対策を加えた標準的な設定例です。
# 共通のベース設定(全ホストに適用)
Host *
# 接続が切れないよう 60 秒ごとにキープアライブパケットを送信
ServerAliveInterval 60
ServerAliveCountMax 3
# 明示指定した鍵のみを使用
IdentitiesOnly yes
# 開発用 Debian サーバ
Host dev
HostName 192.168.1.100
User debian
Port 22
IdentityFile ~/.ssh/id_ed25519_dev
# 社内 Windows サーバ(ポート 2222)
Host win-server
HostName 192.168.1.150
User admin
Port 2222
IdentityFile ~/.ssh/id_ed25519_win
# クラウド本番サーバ
Host prod
HostName 203.0.113.10
User ubuntu
Port 22
IdentityFile ~/.ssh/id_ed25519_prod
上記のように記述しておけば、ターミナルで以下の短いコマンドを叩くだけで、正しいポート、ユーザー、秘密鍵で即座に接続されます。
ssh dev
ssh win-server
ssh prod
踏み台サーバ(ジャンプホスト)経由の接続
セキュリティの厳しい社内ネットワークや VPC 環境では、プライベートネットワーク内のサーバへ直接アクセスできず、踏み台(Bastion)サーバを経由してアクセスする構成が一般的です。
ProxyJump ディレクティブを使用すると、透過的な踏み台接続を 1 行で定義できます。
# 外部公開されている踏み台サーバ
Host bastion
HostName 203.0.113.5
User bastion-user
Port 22
IdentityFile ~/.ssh/id_ed25519_bastion
IdentitiesOnly yes
# プライベート空間にある内部 DB サーバ
Host internal-db
HostName 10.0.1.20
User db-admin
Port 22
IdentityFile ~/.ssh/id_ed25519_internal
IdentitiesOnly yes
ProxyJump bastion
この設定により、利用者は単に以下を実行するだけで、クライアントが裏で自動的に踏み台サーバを経由して内部サーバへ安全にトンネリング接続します。
ssh internal-db
ファイルのアクセス権限管理
config ファイルは、他者から改ざんされると不正なホストへ接続させられるリスクがあるため、アクセス権限を厳格にしておく必要があります。
Linux / macOS / WSL の場合
chmod 600 ~/.ssh/config
Windows の場合
PowerShell で以下のコマンドを実行し、現在のユーザーのみにフルコントロール権限を与え、他ユーザーの権限を削除します。
$path = "$HOME\.ssh\config"
icacls.exe $path /inheritance:r /grant "$($env:USERNAME):(F)"
第6章 ポート転送(SSHトンネル)
ポート転送(SSH トンネル)とは
ポート転送(ポートフォワーディング)は、SSH の暗号化された通信経路(トンネル)の中に別の TCP 通信を通す技術です。
この技術を使うことで、インターネットに直接公開されていない社内 Web 画面やプライベートなデータベース(MySQL や PostgreSQL など)に対し、手元の PC から安全にアクセスできるようになります。
SSH のポート転送には、通信の向きや用途に応じて以下の 3 種類が存在します。
-
ローカルポート転送(-L):
手元 PC のポートへの通信を、SSH サーバ経由で目的のリモートサーバへ転送します。
-
リモートポート転送(-R):
リモートサーバのポートへの通信を、SSH サーバ経由で手元のローカル PC へ転送します。
-
ダイナミックポート転送(-D):
手元 PC を SOCKS プロキシ化し、任意の宛先への通信を SSH サーバ経由で中継します。
1. ローカルポート転送(-L)
リモートネットワーク内に存在する非公開サービスへアクセスする最も代表的な手法です。
[手元 PC (localhost:8080)] ===(SSH暗号化トンネル)===> [SSH サーバ] ───> [社内Web (192.168.1.200:80)]
コマンド構文
ssh -L <ローカルポート>:<転送先ホスト>:<転送先ポート> <ユーザー名>@<SSHサーバ>
具体例:リモートのデータベースに接続する
外部から接続できないリモートサーバ上の PostgreSQL(ポート 5432)に接続したい場合:
ssh -L 15432:localhost:5432 user@ssh-server
このコマンドを実行している間、手元 PC の localhost:15432 に接続するだけで、自動的にリモートサーバ上の localhost:5432 へパケットが暗号化転送されます。手元の GUI データベースクライアントから安全に操作できます。
2. リモートポート転送(-R)
手元のローカル PC で動作している開発用サーバーなどを、離れたリモートサーバ側からアクセス可能にする手法です。
[リモートクライアント] ───> [SSH サーバ (:8080)] ===(SSH暗号化トンネル)===> [手元 PC (localhost:3000)]
コマンド構文
ssh -R <リモートポート>:<ローカルホスト>:<ローカルポート> <ユーザー名>@<SSHサーバ>
具体例:手元で開発中の Web アプリを共有する
手元の PC で動いている Node.js 開発サーバー(ポート 3000)を、リモートサーバのポート 8080 で待ち受けて公開する場合:
ssh -R 8080:localhost:3000 user@ssh-server
リモートサーバ上で curl http://localhost:8080 を実行すると、手元 PC のポート 3000 で動作する Web アプリが応答します。
▸ リモートポートを外部ホストに公開する場合(GatewayPorts)
デフォルトでは、リモート転送されたポートはリモートサーバ自身のループバック(127.0.0.1)にのみバインドされます。外部の第三者マシンからもアクセス可能にするには、サーバ側の /etc/ssh/sshd_config で GatewayPorts yes を有効化する必要があります。
3. ダイナミックポート転送(-D)
手元 PC の指定ポートを SOCKS5 プロキシサーバーとして機能させます。 Web ブラウザ等のプロキシ設定をこれに向けることで、ブラウザからのすべてのアクセスがあたかも SSH サーバからアクセスしているかのように振る舞います。
コマンド構文
ssh -D <ローカルポート> <ユーザー名>@<SSHサーバ>
具体例:SOCKS プロキシの起動
ssh -D 1080 user@ssh-server
手元 PC のブラウザ設定で SOCKS5 プロキシとして 127.0.0.1:1080 を指定すると、安全でないフリー Wi-Fi 環境からでも、すべてのブラウジング通信を SSH 暗号化トンネル経由で行うことができます。
トンネル専用の便利なオプション(-N と -f)
ポート転送のトンネルを維持するだけで、リモートサーバのシェルプロンプトを操作する必要がない場合は、以下のオプションを組み合わせます。
-N: リモートコマンドを実行せず、ポート転送のみを行う。-f: 認証完了後、直ちにプロセスをバックグラウンドへ移行する。
# バックグラウンドでローカルポート転送を常駐
ssh -f -N -L 15432:localhost:5432 user@ssh-server
バックグラウンド接続を終了したい場合は、kill コマンドで対象プロセスの PID を停止します。
.ssh/config によるポート転送の自動化
コマンドラインで長い引数を指定する代わりに、~/.ssh/config に転送定義をあらかじめ記述しておくことができます。
# 社内 DB トンネル用定義
Host tunnel-db
HostName 203.0.113.10
User developer
IdentityFile ~/.ssh/id_ed25519_dev
IdentitiesOnly yes
# ローカル 15432 をリモートの 5432 に転送
LocalForward 15432 localhost:5432
# SOCKS プロキシ用定義
Host socks-proxy
HostName 203.0.113.20
User proxy-user
IdentityFile ~/.ssh/id_ed25519_proxy
IdentitiesOnly yes
# ローカル 1080 を SOCKS プロキシ化
DynamicForward 1080
これにより、単に ssh tunnel-db や ssh -f -N tunnel-db と実行するだけで、意図したポート転送が即座に開始されます。
第7章 scp によるファイル転送
scp とは何か
scp(Secure Copy Protocol)は、SSH の暗号化通信を利用して、ネットワーク上の 2 台のコンピュータ間でファイルやディレクトリを安全にコピーするためのコマンドです。
従来の平文 FTP と異なり、認証パスワードやファイルの内容全体が暗号化されるため、機密ファイルや設定ファイルも安全に送受信できます。
構文は標準の cp(コピー)コマンドに非常に近く、直感的に操作できる特徴を持っています。
基本構文と主要オプション
scp の基本構造は「コピー元(source)」と「コピー先(destination)」の指定です。
scp [オプション] <コピー元> <コピー先>
リモートホストを指定する場合は <ユーザー名>@<ホスト名>:<パス> の形式で記述します。
主要オプション一覧
| オプション | 役割・説明 |
|---|---|
-r | ディレクトリ内を再帰的にすべてコピーする |
-p | 元ファイルの最終更新日時・アクセス日時・アクセス権限を保持する |
-P <ポート> | 接続先 SSH サーバのポート番号を指定する(大文字の P である点に注意) |
-i <秘密鍵> | 認証に使用する秘密鍵ファイルを明示的に指定する |
-v | 詳細なデバッグログを表示する |
▸ ポート番号指定オプションの注意点
通常の ssh コマンドではポート番号指定に小文字の -p を使いますが、scp では -p は属性保持(preserve)に割り当てられているため、ポート指定には 大文字の -P を使用します。
ファイル転送の実践操作
1. ローカルからリモートへアップロードする
手元のローカル PC にあるファイルを、リモートサーバの特定ディレクトリへ送信します。
# 単一ファイルのアップロード
scp app.tar.gz user@192.168.1.100:/var/www/
# ポート 2222 かつ秘密鍵を指定してアップロード
scp -P 2222 -i ~/.ssh/id_ed25519 app.tar.gz user@192.168.1.100:/var/www/
2. リモートからローカルへダウンロードする
リモートサーバ上にあるログファイルやバックアップを手元の作業 PC へ取得します。
# サーバ上のログファイルを手元カレントディレクトリ(.)にダウンロード
scp user@192.168.1.100:/var/log/nginx/access.log .
3. ディレクトリ全体の再帰コピー(-r)
フォルダ全体を丸ごと転送する場合は -r オプションを付与します。
# ローカルの dist フォルダ全体をサーバへ転送
scp -r ./dist user@192.168.1.100:/var/www/html/
.ssh/config のエイリアスを活用した効率的な転送
~/.ssh/config にホスト設定を記述しておくと、scp コマンドでもそのエイリアスがそのまま適用されます。
Host prod
HostName 203.0.113.10
User ubuntu
Port 2222
IdentityFile ~/.ssh/id_ed25519_prod
IdentitiesOnly yes
上記の設定が済んでいれば、ポート番号やユーザー名、秘密鍵の指定をすべて省略し、ローカルの cp コマンドと全く同じ感覚で簡潔に転送できます。
# 設定エイリアス prod を指定してアップロード
scp release.zip prod:/opt/app/
# 設定エイリアス prod から設定ファイルをダウンロード
scp prod:/opt/app/config.json ./
複雑な接続パラメータの入力ミスを防ぎ、日常のファイル転送作業を格段に安全・迅速に行うことができます。
近年の OpenSSH における scp の変化(SFTP ベース化)
歴史的に scp は古い rcp プロトコルをベースにしており、ワイルドカード展開やエスケープ処理に起因する脆弱性が指摘されていました。
これを受けて、OpenSSH 9.0 以降では、scp コマンドの内部実装が従来の SCP プロトコルから、より安全で現代的な SFTP(SSH File Transfer Protocol) を標準プロトコルとして使用するように刷新されました。
利用者は従来の scp のコマンド構文をそのまま使い続けながら、内部ではより厳格で安全なファイル転送プロトコルの保護を享受できます。