寒月記

住みにくいところをどれほどか寛容て

公開鍵認証で SSH 接続する

TL;DR

  • ssh 先に openssh-server, ssh 元に openssh-clientが必要*1
    • ssh 元が Windows なら GitBash, Cygwin, WSL なんかが入っていれば使えるはず
    • あるいは PowerShell に入れる, TeraTerm や MobaxTerm などを使う方法でも
  • ssh 元で ssh-keygen コマンドを使って鍵生成
    • rsa 4096 bit などが簡便かつ暗号強度的に良さそう
  • ssh 先に公開鍵を sftp, scp などで転送し, ~/.ssh/authorized_keys に登録
  • ssh 元の ~/.ssh/config に ssh 先の情報を記述しておくと楽
  • サーバーの /etc/ssh/sshd_configPasswordAuthenticationno にし, sshd.service を再起動して完了

1. SSH とは

 Secure SHell の略で, リモート通信, つまりネットワーク的につながった別のコンピュータを遠隔操作するための通信を暗号化するものです*2。これの平文版は telnet*3 です, 今はもう使われていないはずです。万が一使っていたらセキュリティ的にまずいので ssh を使いましょう。
 本記事では, Windows マシンから Linux マシンなどに 「公開鍵認証方式」 と呼ばれる方法を使って ssh する方法を紹介します*4

2. 公開鍵認証方式とは

 手順の説明の前に, ごく簡単に「公開鍵認証」と呼ばれるものについて説明します。

 通信は, 当事者間以外には基本的に秘匿されるべきものです。誰かに宛てた手紙を途中で他人に読まれたり, 改竄されたり, 電話の内容が他人に筒抜けだったり, というのはいやですよね。他愛もない会話ならまだしも, 悪用されると身の安全に関わる情報や, 秘密の情報が含まれていたら大問題です。
 ネットワークの通信も, 同じように暗号化, つまり当事者同士以外では内容が分からないようにしなければいけません。
これを実現する方法の一つが「公開鍵暗号」で, 公開鍵暗号を使った認証の方式が「公開鍵認証」です。

2-1. 公開鍵暗号とは

 公開鍵暗号についてもごく簡単に説明します。「錠」と「鍵」のアナロジーが一番理解しやすいと思います*5

公開鍵暗号利用の手順
  1. 公開鍵 (錠) と秘密鍵 (鍵) のペアを作る
    • 公開鍵 (錠): 通信内容を暗号化する
    • 秘密鍵 (鍵): 公開鍵 (錠) で暗号化された通信を復号する
  2. 鍵ペア作成者が「錠」として公開鍵を配る
  3. 通信者は公開鍵 (錠) の配布元との間で暗号化したい通信を, 公開鍵 (錠) を使って暗号化して送る
  4. 鍵ペア作成者は公開鍵で暗号化された 3 の通信を, 自分だけが持つ秘密鍵で復号する

これを第三者が攻撃しようとしたとき, 例えば通信を途中で傍受したとします。
暗号化されていない平文であれば, この時点でアウトです。中身を読まれてしまいます。
しかし, 公開鍵で暗号化してあれば, その内容を見ることができません。正確に言うと, 暗号化されているため見ても何が何だかわからないものになっていますので, 安心です。

2-2. 公開鍵認証

 この公開鍵暗号を利用して ssh を行うのが, (この文脈での) 公開鍵認証です。
公開鍵認証方式の利点を知るため, 他の方式と比較してみましょう。

 公開鍵認証以外の最もシンプルな認証方法としては「パスワード認証方式」があり, ssh 時にパスワードを照合することで認証, すなわち「通信相手が正しいこと」を確認します。
 しかし, パスワード認証方式には弱点があります。
パスワードは, その気になれば総当たりで文字列の組み合わせを試す, brute-force attack と呼ばれる攻撃で突破されてしまう可能性が大いにあります。
ほとんどの場合, パスワードはランダムの長い文字列になることは少なく, 設定者が覚えやすい長さ, 覚えやすい内容になりがちです。
このため, いわゆる「よくあるパスワード」であったり, 「総当たりですぐ見つかる短いパスワード」になってしまうことが多いため, パスワード認証方式での ssh の利用は推奨されていません。

公開鍵認証では, 十分な強度の鍵さえ生成すれば, こうした弱点は克服することができます。
brute-force attack により突破されない理由としては, 「鍵の長さ」さえ十分なものであれば, 現代のコンピュータでは 現実的な時間で当たりを引く ことができないためです*6。 秘密鍵さえ漏らさなければ, パスワード認証方式よりも安全なので, もしパスワード認証方式で重要なサーバーを運用している場合などは公開鍵認証方式への切り替えを強くお勧めします。
 ただし, くれぐれも秘密鍵をインターネットに公開してしまったり, メールなどで送ったりしないようご注意 を。

3. ssh で公開鍵認証方式を使う手順

 では, 本題の「公開鍵認証方式を使った ssh の設定方法」を説明します。
なお, ここでは ssh client (ssh 元) を Windows, ssh server (ssh 先) を Linux マシンとして説明します (基本的な流れは OS によらず似たようなものです)。
説明に使う環境は, ssh client が Windows10, ssh server が Ubuntu 18.04 です。

大まかな流れは以下になります。

公開鍵認証方式での ssh 設定方法
  1. ssh 先 Linux マシンの準備
    1. openssh-server をインストール
    2. sshd.service を起動
  2. ssh 元 Windows マシンの準備
    1. GitBash, Cygwin, WSL などをインストールし, ssh コマンドを使えるようにする
    2. ssh-keygen コマンドで鍵ペアを作成
  3. 公開鍵を client -> server に転送
  4. 公開鍵を server の ~/.ssh/authorized_key に登録
  5. (任意) ssh 先の情報を ssh 元の ~/.ssh/config に記述しておくと以降簡単に ssh できる
  6. パスワード認証方式を禁止しておく

以下で個々の手順を詳しく見ていきます。

3-1. ssh 先 Linux マシンの準備

 まず, ssh を受け付けられるように, openssh-server をインストールします。
Ubuntu など debian 系では以下のコマンドでインストール可能です。

$ sudo apt install openssh-server

openssh-server をインストールすると, 次のようなパッケージがインストールされます。

kangetsu@dev_persona:~$ dpkg -l | grep ssh
ii  openssh-client                        1:7.6p1-4ubuntu0.3                amd64        secure shell (SSH) client, for secure access to remote machines
ii  openssh-server                        1:7.6p1-4ubuntu0.3                amd64        secure shell (SSH) server, for secure access from remote machines
ii  openssh-sftp-server                   1:7.6p1-4ubuntu0.3                amd64        secure shell (SSH) sftp server module, for SFTP access from remote machines
ii  ssh-import-id                         5.7-0ubuntu1.1                    all          securely retrieve an SSH public key and install it locally
kangetsu@dev_persona:~$

この中で, server 側で使うのは openssh-server です。

これで, サーバー側で ssh を受け付けるために必要なソフトをインストールできました。
次に, これを起動しないと意味がないので起動します。
サービス名は, sshd.service, つまり ssh daemon*7 という名前で登録されているはずです。

$ sudo systemctl start sshd.service

これで ssh を受け付ける準備が整いました。
以降は, デフォルトでマシン起動時に sshd.service が起動するようになっているはずので気にしなくても大丈夫です。

3-2. ssh 元 Windows マシンの準備

 Linux, Mac であれば初めから ssh client が入っている (ことが多い) のですが, Windows には ssh client はデフォルトではありません。
 そこでインストールが必要なのですが, GitBash, Cygwin, WSL (Windows Subsystem for Linux) などをインストールしたり, TeraTerm や MobaxTerm などのソフトをンストール, あるいは最近では PowerShell にも Openssh をインストールできるらしいですので, 方法はお好きなもので大丈夫です。

実はこの時点で, 設定を変更していなければ ssh 自体は可能になっています。

$ ssh ${USERNAME}@${HOSTNAME}

で, ssh 先のユーザー名, ホスト名 (または IP アドレス) を入力し, そのユーザーのパスワードを入力すれば接続することができます*8

 しかしこのままではパスワード認証方式のままなので, 公開鍵認証方式の設定を進めます。
ssh 元で ssh コマンドを使えるようになったら, ssh-keygen コマンドで秘密鍵・公開鍵の鍵ペアを作成します。
オプションはいろいろありますが, 現在では暗号化方式を RSA, ビット長を 4096 とするのがわかりやすくかつ安全です。

$ ssh-keygen -t rsa -b 4096

ssh-keygen コマンドを実行すると, Enter file in which to save the key と, 鍵の保存先・鍵の名前の入力を求められます。
保存先はそのままで, 鍵の名前だけ ssh 先の環境に合わせて変えるとよいのではないでしょうか。
続いて, Enter passphrase (empty for no passphrase): と表示され, 鍵を利用するときの Passphrase, パスワードのようなものを決めろと言われます。
先ほど 「ssh をパスワード認証方式で使うのは推奨されていない」と書いたのに, 不思議に思われるかもしれません。
しかし, これはあくまで「秘密鍵を使うときに求められるパスフレーズ」であるため, たとえパスフレーズが漏洩しても秘密鍵そのものが漏洩していなければ, 第三者がサーバーに ssh することはできません*9
また, ssh パスワード認証方式のパスワードと違い, パスフレーズ自体はネットワーク上を流れずローカル上で完結するため, その意味でも安全です。
何も入力しなければ空にもできますが, 重要な環境のものは入力しておくのが安心でしょう。

これで, デフォルト通りのディレクトリに鍵名だけ変更した場合は, $HOME ディレクトリ*10.ssh ディレクトリが, さらにその中に ${KEYNAME}, ${KEYNAME}.pub という 2つのファイルが作成されます。
このうち, .pub とついている方が public key, すなわち公開鍵で, ついてない方が秘密鍵です。

今回は ssh 元が Windows なので詳しく触れませんが, Mac や Linux の場合はこの時点で秘密鍵のパーミッションを 600, すなわち所有者以外は「読み書き実行」できない状態にしておくのが安全です。

3-3. 公開鍵を client -> server に転送

 次は, 先ほど作った公開鍵を ssh 先のサーバーに転送します。
公開鍵は名前の通り広く公開されていて問題ないので, 方法は sftp, scp などを使ったり, あるいは ssh-copy-id コマンドを使ってもよいでしょう。

3-4. 公開鍵を server の ~/.ssh/authorized_keys に登録

 3-3 で公開鍵を ssh 先のサーバーに転送することができました。
ssh-copy-id コマンド以外の方法を使っている場合は, サーバー上の ssh したいユーザーのホームディレクトリ, すなわち /home/${USER} ディレクトリに .ssh ディレクトリを, さらにその中に authoeized_keys ファイルを作成し, ここに公開鍵の内容を登録します。
例えば kangetsu というユーザーでこの設定をする場合, 手順は以下になります。

公開鍵登録方法
  1. (ない場合) .ssh ディレクトリを作成
    $ mkdir /home/kangetsu/.ssh
  2. (ない場合) authorized_keys ファイルを作成
    $ touch /home/kangetsu/.ssh/authorized_keys
  3. 転送した公開鍵の内容を authorized_keys に登録 (ここでは公開鍵が .ssh ディレクトリにあるとする)
    $ cat ~/.ssh/${PUBLIC_KEY} >> ~/.ssh/authorized_keys

3 でリダイレクトを追記型にしている (>>) のは, 複数の ssh 元がある場合に, 今回記述しようとしている公開鍵以外の情報を上書きして消してしまうのを防ぐためです。
これで準備完了です。

ssh 元マシンから, 次のコマンドで ssh できることを確認してみましょう。

$ ssh -i ${PATH_TO_SECRETKEY} ${USERNAME}@${HOST}

${HOST} は IP アドレスでも構いません。
kangetsu ユーザーで xxx.xxx.xxx.xxx にアクセスする場合, 以下のようになります。

$ ssh -i ~/.ssh/id_rsa_test kangetsu@xxx.xxx.xxx.xxx

3-5. (任意) ssh 先の情報を ssh 元の ~/.ssh/config に記述しておくと以降簡単に ssh できる

 以上で, 公開鍵認証方式で ssh することができました。
パスフレーズを設定していない場合はそのまま, している場合はパスフレーズのみ求められ, 「パスワード」は求められなかったことに注目してください。

 これで公開鍵認証方式で ssh できたのでめでたし, としたいところですが, もう二手間加えて便利・セキュアにします。

まず, 毎回 ssh 時に秘密鍵, ユーザー名, ホストを指定するのは面倒なので, これを簡単にします。

ssh 元のマシンの ~/.ssh/config ファイルを作り, そこに次のような形式で接続先情報を記述しておきます。
以下は, xxx.xxx.xxx.xxx にユーザー kangetsu で, 秘密鍵 id_rsa_test を使って接続するときの記述例です。
Host の横の ssh_test という名前で, この設定を使えるようになります。

Host ssh_test
  HostName xxx.xxx.xxx.xxx
  User kangetsu
  IdentityFile D:\hogehoge\.ssh\id_rsa_test

このような config ファイルを作成しておくことで,

$ ssh ssh_test

と入力するだけで公開鍵認証が使えます。

3-6. ssh のパスワード認証方式を禁止しておく

 これまでで公開鍵認証方式を使って ssh できるようになりましたが, 実は今のままではパスワード認証方式も使えます。
すなわち, 秘密鍵を持たない第三者でも brute-force attack を仕掛けることが可能な, パスワード認証方式のデメリットを克服できていない状態となります。

公開鍵認証方式で接続することができるようになったので, パスワード認証方式での接続を禁止して, セキュアにしておきましょう。
なお, 公開鍵認証方式で接続することが確認できていないのにパスワード認証方式を禁止してしまうと, その環境には原則アクセスすることができなくなってしまうので, くれぐれも順番を間違えないようご注意ください。

パスワード認証方式を禁止する手順は以下の通りです。

パスワード認証禁止手順
  1. ssh 先のサーバーで, /etc/ssh/sshd_config ファイルの PasswordAuthenticationno にして保存
  2. sshd.service を再起動して設定を反映

以上です。
これで便利なだけでなく, セキュリティ的にもより安心な状況となりました。

4. まとめ

 以上の通り, ssh を使う場合は, 基本的には公開鍵認証方式を使うのが良いでしょう。
その際, せっかくなのでパスワード認証方式を禁止しておくのも忘れずに。ただし, 公開鍵認証方式での接続を確立してから行うことに注意してください。

また, 万が一秘密鍵が漏洩してしまったことが疑われる場合は, すぐに新しい鍵ペアを発行して登録し, 漏洩した秘密鍵・公開鍵のペアを削除して, authorized_keys を更新してください。

 個人的に, 今回の記事は何となく使っていた ssh を理解し直すのによい機会でした。
known_hosts の話なども書きたかったのですが, 長くなりすぎるしまたの機会があれば別にまとめようと思います。

5. 参考

主に参考にさせていただいた資料です, 詳しく知りたい方はこちらを読むととてもおもしろいと思います。

暗号技術入門 第3版

暗号技術入門 第3版

暗号解読(上) (新潮文庫)

暗号解読(上) (新潮文庫)

暗号解読 下巻 (新潮文庫 シ 37-3)

暗号解読 下巻 (新潮文庫 シ 37-3)

すべてがFになる (講談社文庫)

すべてがFになる (講談社文庫)

*1:厳密に言えば Openssh 以外の ssh ソフトでもよい

*2:表現が難しいので語弊があるかも, 通常の利用の範囲ではこんな理解でいいはず

*3:完全に余談ですが, 森博嗣さんの『すべてが F になる』で有名な S&M シリーズの主人公, 犀川先生が大学のラボの PC で telnet を使ってる様子がときどき描かれています。時代ですね。

*4:何番煎じか数えきれないし他の素晴らしい説明もあるけど, 自分メモも兼ねて

*5:RSA 暗号では公開鍵と秘密鍵の間で錠と鍵の役割が交換可能だったりと, これも厳密には正確ではないですが簡単のため

*6:量子コンピュータは現代のコンピュータと比べ物にならないほどの単位時間当たりの計算が可能なので, 量子コンピュータが実現すればこうした暗号は過去のものになるようです。すでに一部では実現しているとかいう噂もあったりなかったり......どこまで本当かわかりませんが

*7:よくある話ですが, demon = 悪魔 ではなく daemon = 守護神です

*8:VirtualBox などで仮想環境をローカル上に作っている場合は, この他にポートフォワーディングなりホストオンリーアダプタの設定なり, ローカル <-> VM で通信する方法の確立が必要です

*9:もちろん望ましい状況ではないですが

*10:ターミナル起動時にいるディレクトリです, 起動直後に pwd コマンドを実行したり, echo $HOME コマンドなんかで確認できます