ウェブエンジニア問題集
第4.45章

SSHと公開鍵認証 — サーバーへ安全に接続する

7
この章の目次開く

SSHは、リモートサーバーへ安全にログインして操作するためのプロトコルです。 正式には Secure Shell と呼ばれ、通信内容を暗号化したうえで、相手のサーバーと自分の認証を確認します。

Web開発では、クラウド上のサーバーへ入る、GitHubへSSHで接続する、踏み台サーバー経由で内部環境へ入る、といった場面でよく使います。

学習者学習者

GitHubのSSH設定はやったことがあります。でも、サーバーに入るSSHと何が同じなのかは曖昧です。

SSHで何ができるか

SSHの代表的な用途は、手元のPCから別のサーバーへログインして、コマンドを実行することです。

ssh user@example.com
bash

このコマンドは、example.com というサーバーに user というユーザーで接続する、という意味です。 内部では、DNSで名前解決し、IPアドレスへ到達し、TCPで22番ポートへ接続し、その上でSSHの認証と暗号化通信を行います。

PC
  -> DNSで example.com をIPへ変換
  -> TCP 22番ポートへ接続
  -> SSHでサーバー確認とユーザー認証
  -> リモートシェルを操作
SSHは、TCPの上で動くアプリケーション層のプロトコルです。標準ポートは22番です。

基本の接続コマンド

よく使う形は次の通りです。

# ユーザー名とホスト名を指定
ssh user@example.com
 
# ポート番号を指定
ssh -p 2222 user@example.com
 
# 秘密鍵ファイルを指定
ssh -i ~/.ssh/id_ed25519 user@example.com
bash
指定意味
user@example.comexample.comuser として接続する
-p 222222番以外のポートへ接続する
-i ~/.ssh/id_ed25519使う秘密鍵を明示する

サーバー側でSSHが22番ではなく2222番などに変更されている場合、-p を指定しないと接続できません。

パスワード認証と公開鍵認証

SSHの認証には、主にパスワード認証と公開鍵認証があります。

認証方式仕組み実務での扱い
パスワード認証サーバー上のユーザーのパスワードを入力する総当たり攻撃に弱いため無効化されることが多い
公開鍵認証手元の秘密鍵と、サーバーに置いた公開鍵の対応を確認する推奨されることが多い

公開鍵認証では、手元のPCに 秘密鍵 を置き、サーバー側に 公開鍵 を登録します。 秘密鍵そのものをネットワークへ送るわけではありません。 サーバーは、公開鍵に対応する秘密鍵をクライアントが持っているかを暗号学的に確認します。

鍵ペアを作る

新しくSSH鍵を作るときは ssh-keygen を使います。 現在は ed25519 がよく使われます。

ssh-keygen -t ed25519 -C "taro@example.com"
bash

標準の保存先を選ぶと、次のような2つのファイルが作られます。

ファイル種類扱い
~/.ssh/id_ed25519秘密鍵自分だけが持つ
~/.ssh/id_ed25519.pub公開鍵GitHubやサーバーへ登録できる

公開鍵の中身は cat で確認できます。

cat ~/.ssh/id_ed25519.pub
bash

authorized_keysに公開鍵を登録する

サーバーへ公開鍵認証でログインするには、接続先ユーザーの ~/.ssh/authorized_keys に公開鍵を登録します。

/home/user/.ssh/authorized_keys

このファイルには「このユーザーとしてログインしてよい公開鍵」の一覧が入ります。 たとえば、手元PCの id_ed25519.pub の内容を、サーバー側の authorized_keys に1行として追加します。

# 手元PCで公開鍵を表示
cat ~/.ssh/id_ed25519.pub
bash
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... taro@example.com

サーバー側では、.ssh ディレクトリや authorized_keys の権限が広すぎるとSSHが拒否することがあります。

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
bash

known_hostsは「接続先サーバーの記録」

初めてSSH接続すると、次のような確認が出ることがあります。

The authenticity of host 'example.com' can't be established.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

これは「このサーバーを初めて見るが、本当に接続してよいか」という確認です。 yes と答えると、サーバーのホスト鍵の情報が ~/.ssh/known_hosts に保存されます。

次回以降、同じホスト名なのにホスト鍵が変わっていると警告が出ます。 これはサーバーを再作成しただけのこともありますが、中間者攻撃の可能性もあるため、理由を確認してから対応します。

ssh configで接続を短くする

毎回 ssh -i ... -p ... user@host と書くのは面倒です。 ~/.ssh/config に設定しておくと、短い名前で接続できます。

Host app-server
  HostName example.com
  User deploy
  Port 2222
  IdentityFile ~/.ssh/id_ed25519
sshconfig

この設定があれば、次のように接続できます。

ssh app-server
bash

GitHubで仕事用と個人用の鍵を分ける場合も、Host を分けて IdentityFile を指定することがあります。

GitHubのSSH接続との関係

GitHubのSSH cloneも、仕組みとしてはSSHです。

git clone git@github.com:owner/repo.git
ssh -T git@github.com
bash

通常のサーバーログインでは ssh user@example.com のように接続しますが、GitHubでは git@github.com というユーザーへ接続し、Git操作だけを許可する形になっています。 GitHub側に登録するのは公開鍵で、手元に置くのは秘密鍵です。

GitHub向けの具体的なセットアップは Gitのセットアップ で扱っています。

接続できないときの見方

SSHで接続できないときは、エラーメッセージによって見る場所が変わります。

エラー例よくある原因
Could not resolve hostnameホスト名が間違っている、DNSで名前解決できない
Connection timed outファイアウォール、セキュリティグループ、経路、ポート違い
Connection refusedサーバーへ届いたが、SSHが待ち受けていない
Permission denied (publickey)公開鍵が未登録、別の秘密鍵を使っている、ユーザー名が違う
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!サーバーのホスト鍵が変わった

原因を詳しく見るには -v を付けます。

ssh -v user@example.com
bash

さらに詳しく見る場合は -vv-vvv も使えます。 ただし、ログにはローカルのパスや鍵名が出ることがあるため、共有するときは不要な情報を伏せます。

ちゃんと使うためのポイント

  • SSHは、リモートサーバーへ安全に接続するためのプロトコル
  • 標準ポートは22番だが、環境によって変更されることがある
  • 実務ではパスワード認証より公開鍵認証がよく使われる
  • 秘密鍵は自分だけが持ち、公開鍵をサーバーやGitHubに登録する
  • authorized_keys はログインを許可する公開鍵の一覧
  • known_hosts は接続先サーバーのホスト鍵の記録
  • 接続できないときは、DNS、ポート、認証、ホスト鍵のどこで失敗しているかを分けて見る

次の章では、SSHも含めた「繋がらない」を下の層から順に調べる ネットワークの切り分け を扱います。

CS基礎クイズに挑戦するこの章で学んだCS基礎の知識を、4択クイズでアウトプットして定着させよう