SSHについて勉強し直した

[OPENLOGI Advent Calendar 2019](https://qiita.com/advent-calendar/2019/openlogi) の記事です。

恥ずかしながら普段使っているSSHのことをあまり分かっていなかったので、
何番煎じか分かりませんが使い方など改めて確認しました。

## 環境
- MacOS Mojave
- OpenSSH_7.9p1

## 公開鍵認証の仕組み
SSHの認証方式はいくつかありますが、公開鍵認証について見ていきます。

一般的な説明としてサーバがクライアントの公開鍵で乱数を暗号化し、クライアントはそれを秘密鍵で復号・・という話がほとんどだったのですが、下記の記事によるとこれは誤りだそうです。

[SSHの公開鍵認証における良くある誤解の話
](https://qiita.com/angel_p_57/items/2e3f3f8661de32a0d432)

公開鍵認証は暗号化/復号化という話でなく電子署名の性質を利用したもので、
かなり簡単に言うと **クライアントが秘密鍵で署名したデータを、サーバが公開鍵で検証する** という仕組みだそうです。

記事にも記載されているリンク [RFC4252の和訳](https://www.unixuser.org/~haruyama/RFC/ssh/rfc4252.txt) を確認してもそのように書いてありました。

```
7.  公開鍵認証法: "publickey"
（中略）
   この認証法では, 秘密鍵を所持によって認証を行なう.  ユーザの秘密鍵で作られた署名を送ることで, この認証法は動作する.  サーバは, 鍵がユーザの正当な認証情報かどうかをチェックしなければならない. また, 署名が正当かチェックしなければならない.  以上の両方が成立したら, 認証の要求は受け入れられなければならない. さもなければ, 拒否されなければならない.  
``` 

う〜ん、誤った説明で覚えてました

## 実際の利用の流れ
以降はOpenSSHでSSH通信を行う手順について見ていきます。
下記を参考にしています
[Generating a new SSH key and adding it to the ssh-agent](https://help.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)

### 鍵の作成
まずはクライアント側で秘密鍵・公開鍵のペアを作る必要があります
作り方の流れです

1. `ssh-keygen -t rsa -b 4096 -C "your_email@example.com"` を入力
2. 鍵のファイルパスを指定する
3. パスフレーズを入力する。不要な場合そのままEnter
4. randomartが表示され、指定したパスに公開鍵、秘密鍵ができる。`.pub` が公開鍵

#### 引数について
上記で付けた引数の意味は下記です

- `-t rsa` は暗号化方式をRSAに指定する
- `-b 4096` は鍵長を4096bitに指定
- `-C "your_email@example.com"` はコメント

詳しく見ていきます

#### 暗号化方式と鍵長の指定
`-t rsa -b 4096` の部分です

公開鍵暗号の方式としてRSA,DSA,ECDSAなどいくつかあり、それぞれ鍵長も指定できるがどれがよいのでしょうか

[SSH key-type, rsa, dsa, ecdsa, are there easy answers for which to choose when?](https://security.stackexchange.com/questions/23383/ssh-key-type-rsa-dsa-ecdsa-are-there-easy-answers-for-which-to-choose-when)
[ECDSA鍵をGitHubで使う
](https://qiita.com/darai0512/items/c7b47d1b3fe06c4dea7d)
いくつか調べた感じ下記のような状況だそうです

- 基本的にはRSA 2048bit以上を使えばよい。1024bitは危険
- ECDSAは新しい軽量のアルゴリズムで、例えば256bitだとRSA 2048bitより安全かつ2倍早いらしい
  - ただし新しいので対応していない環境があるかもしれない
  - 今後の主流になっていくと思われる
- DSAは以前OpenSSHのデフォルトで採用されていたのだが、鍵長が1024bit固定で現在は脆弱なため非推奨。OpenSSH 7.0以降では受け付けなくなった
  - そのため古い公開鍵がDSAだったときにログインできないことがあるかもしれない
  - 参考：[SSH鍵の暗号化方式を強化してみた。](https://blog.ayurina.net/2016/07/15/ssh%E9%8D%B5%E3%81%AE%E6%9A%97%E5%8F%B7%E5%8C%96%E6%96%B9%E5%BC%8F%E3%82%92%E5%BC%B7%E5%8C%96%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F%E3%80%82/)

なお、何も指定しない場合のデフォルトはRSA 2048bitとなります（`OpenSSH_7.9p1`）
なので今の所デフォルトでも大丈夫そうですね！！

なお、暗号化方式と鍵長の確認がしたい場合は下記で可能です
`ssh-keygen -lf ~/.ssh/id_rsa.pub`


#### コメント
`-C` で指定したやつ。
公開鍵の末尾に付きます。デフォルトだと自分のホスト名になります
慣習的にメールアドレスを書いておくそうですが、公開鍵なので情報を載せたくない場合は空文字を指定します

### 接続
公開鍵をサーバに登録すればsshコマンドで接続ができます


コマンド例：

```
ssh -i /path/to/private_key hostname@ec1-23-45-67-89.ap-northeast-1.compute.amazonaws.com
```

`-i` で使用する秘密鍵を指定しますが、デフォルトで `~/.ssh/id_rsa` が使用されます（macの場合）

サーバに初めて接続しようとした場合fingerprintについてなにやら確認されます

```
The authenticity of host 'github.com (52.192.72.89)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? 
```

この文は「接続しようとしているホストを知らないのでfingerprintを確認してね！」というものですが、
fingerprintとは何なのか、また知らないとか知ってるとかを何で判断しているのか

#### fingerprint
サーバ側の公開鍵をハッシュ化したものです

接続を試行したとき、クライアントはこのサーバの公開鍵を元にした情報を受け取っています

クライアント側では別途正しいfingerprintをサーバ管理者からもらい、それと一致していることを確認することで、正当なサーバであることを確認することができます

例えばGuthubは下記URLでfingerprintを公開しています
https://help.github.com/en/github/authenticating-to-github/githubs-ssh-key-fingerprints

確認で表示されたものと同じ値が記載されているので、正しいサーバに接続しようとしていることが分かります

```
SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 (RSA)
```

なお別途16進数の値も記載がありますが、OpenSSH 6.8より前のバージョンではハッシュアルゴリズムが違う（MD5）ので、その値です

要はサーバ側の鍵情報が正しいことを確認できればいいのですが、
なぜハッシュ化しているかというと短くして人間が認識しやすくしているそうです
ちなみに鍵作成時に表示されたrandomartは、同様の理由でfingerprintを2次元の図形にしたものです


#### 二回目以降の接続
初回接続されるとホストの宛先と公開鍵のペアが `~/.ssh/known_hosts` に記載されます

次回以降に接続を試行するときはこの情報を参照し、ホストと受け取った公開鍵（fingerprint）が一致していれば知っている（正当な）ホストだと判断されます

逆に異なる場合は中間者攻撃の可能性がある旨が表示され接続が失敗します

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Please contact your system administrator.
Add correct host key in <.ssh/known_hosts> to get rid of this message.
Offending RSA key in <.ssh/known_hosts:183>
RSA host key for github.com has changed and you have requested strict checking.
Host key verification failed.
```

例えばknown_hostsの公開鍵を別のに書き換えてみると上記の表示になります

上記エラーでたらとりあえずknown_hosts消しとけ！みたいな記事が割とありましたが、仕組みを知っておくのは大事だと思いました

## 便利な使い方
### ホストのエイリアスを登録
登録することで `ssh <alias>` と入力して接続できます

```:~/.ssh/config
Host server01
    HostName 192.168.1.2
    Port 22
    User username
    IdentityFile ~/.ssh/id_rsa
```

のように書くと、

```
$ ssh server01
```
で接続できるようになります

## おわりに
というわけで普段なかなかちゃんと見られないところを確認しました。
誤り等あればご指摘いただけると幸いです！