Raspberry Piを公開鍵認証で接続できるようにする

#はじめに
Raspberry PiにLAN外から接続できるようにするに当たり、パスワード認証で接続できるようにしておくのは不安なので、本記事ではRaspberry Piにsshで接続する際にパスワード認証ではなく公開鍵認証で接続できるようにすることを目的としています。
同様の記事は数多ありますが、自分の詰まった点なども備忘録的にまとめました。
ここではRaspberry Piはセットアップ済みの状態から始めます。

#環境
##使ったもの
Raspberry Pi 3 Model B
Raspbian Buster Lite(Webサーバ用途なのでLiteで十分です)
macOS Catalina
##使わなかったもの
ディスプレイ
キーボード

すべてsshのみで設定しました。

#おおまかな流れ
1. 接続用PCで公開鍵を作成する
2. 公開鍵をRaspberry Piにscpで転送し、登録する
3. パーミッションの変更をする
3. sshでパスワード認証できないようにする

#接続用PCで公開鍵を作成する
接続するPCで以下のコマンドを実行します。
macOSの場合はターミナルにsshクライアントが導入されているのでそのまま打ち込めば大丈夫です。
Windowsの方はCygwinなどを用いて実行しましょう。

```bash
$ ssh-keygen -t rsa
```
これにより秘密鍵と公開鍵がRSAという方式で生成され、これをどこに保存するかが以下のように聞かれます。

```
Generating public/private rsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_rsa):
```
特にこだわりがなければEnterを押すことでデフォルトの/home/username/.sshに保存されます。
普通に使用する分にはそのままで良いでしょう。
Enterを押すと、公開鍵認証で接続する際に用いるパスフレーズを登録するように言われます。

```
Enter passphrase (empty for no passphrase):
```
私の環境ではセキュリティ的に問題がないと思ったので何も入力せず(登録せず)そのままEnterを押しました。
再度入力するよう求められますので、パスフレーズを登録した方はそれを入力します。

```
Enter same passphrase again:
```

ここまでで以下のようにメッセージが表示され、秘密鍵と公開鍵の作成は終わりとなります。

```
Your identification has been saved in /home/username/.ssh/id_rsa.
Your public key has been saved in /home/username/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx username@hostname
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|                 |
|                 |
|                 |
|                 |
|                 |
|                 |
|                 |
|                 |
+----[SHA256]-----+
```

#公開鍵をRaspberry Piにscpで転送し、登録する
sshの機能の一つであるscpを用いて、先程作成した公開鍵をRaspberry Piに転送し、その内容を登録します。

以下のコマンドを接続するPCで実行します。

```bash
$ scp -P 22 .ssh/id_rsa.pub pi@192.168.10.x:
```
私の環境では接続するPC(MacBook)でのデフォルトのディレクトリが[Username]なので、その直下に.sshディレクトリがあります。
そのため上記のコマンドで.sshにあるid_rsa.pubをpi@&#xFFF0;192.168.10.xに転送できますが、そうではない方は適宜id_rsa.pubのパスとRaspberry PiのIPアドレスを読み替えてください。

コマンドを入力すると、Raspberry Piのパスワードを聞かれるので、入力してEnterを押します。

```
pi@192.168.11.x's password:
```
これで公開鍵を転送できたので、次はRaspberry Piに転送した公開鍵を登録します。
登録というのは、Raspberry Piにある.sshディレクトリのauthorized_keysというファイルに公開鍵の内容を追記することです。
初回は.sshディレクトリさえ存在しないので、追記ではなく新規作成という形になります。

Raspberry Piに公開鍵の登録先である.sshディレクトリを作成しておきます。
Raspberry Piにpiユーザーでログインし、ターミナルで以下のコマンドを実行します。

```bash
$ mkdir .ssh
```
デフォルトのディレクトリ下に.sshディレクトリが作成されます。
この中にauthorized_keysというファイルが欲しいので、公開鍵の内容を書き込んだファイルを作成するため、以下のコマンドを実行します。

```bash
$ cat id_rsa.pub > .ssh/authorized_keys
```
これで公開鍵が登録されたauthorized_keysファイルが作成されますが、いくつか注意点があります。

1つ目は、ふつう公開鍵を登録する際は「上書き」ではなく「追記」という形になる点です。
今回は公開鍵を登録するのが初回だったため上記のコマンドでよかったのですが、普段は追記なので
`$ cat id_rsa.pub >> .ssh/authorized_keys`
となる点に留意してください。

2つ目は、/etc/ssh/sshd_configの編集により、sudoコマンドを用いないとcatが使えない場合です。
この場合、
`$ sudo cat id_rsa.pub`
まではsudoが適用されますが、以降のリダイレクトの
` > .ssh/authorized_keys`
の部分についてはsudoが適用されたないため、permission deniedのエラーが起きます。
この時は以下のコマンドを使いましょう。
`$ sudo sh -c "cat id_rsa.pub > .ssh/authorized_keys"`
これでおそらくauthorized_keysファイルの作成ができると思います。

authorized_keysに公開鍵を登録できたら、id_rsa.pubはもう不要なので、以下のコマンドで削除しましょう。

```bash
$ rm id_rsa.pub
```

#パーミッションの変更をする
ディレクトリやファイルにパーミッション(権限)が正しく設定されていないと、sshで接続できません。そのため適切に権限を変更します。

以下のコマンドをRaspberry Piのターミナルで実行します。

```bash
$ chmod 700 .ssh
$ chmod 600 .ssh/authorized_keys
```

ここで、sudoで.sshディレクトリを作った方やauthorized_keysファイルを作った方は、これらの所有者がrootになっている可能性があります。
もしそうであれば以下のコマンドで所有者をpiに変更しておきましょう。

```bash
$ chown pi:pi .ssh
$ chown pi:pi .ssh/authorized_keys
```
所有者や権限の確認は`$ ls -la`でできます。

ここまでで公開鍵認証での接続ができるようになったかと思います。

#sshでパスワード認証できないようにする
Raspberry Piのターミナルでホームディレクトリに戻ってから以下のコマンドを実行します。

```bash
$ sudo vi /etc/ssh/sshd_config
```
Vimエディタでsshd_configファイルを開くので、PasswordAuthenticationの項目をyesからnoに変更しましょう。
Vimの使い方がわからない人はnano等で適当に開いてみてください。nanoは操作方法が画面下部に記載されています。

```vim:/etc/ssh/sshd_config
PasswordAuthentication no
```

編集したらsshサービスを再起動しましょう。
```bash
$ /etc/ssh/sshd_config
```

以上で公開鍵認証で接続できるようになったと思います。
接続できるか確認してみましょう。
接続用のPCのターミナルで以下のコマンドを実行します。

```bash
$ssh -i .ssh/id_rsa -p 22 pi@192.168.10.xx
```
接続用PCのid_rsaの場所やポートによって適宜.ssh/id_rsaなどは読み替えてください。
うまく以下が表示されたら完了です。

```bash
pi@raspberrypi:~ $
```

#おわりに
私の環境では公開鍵を転送し登録した後、sshで何度接続しようとしてもPermission denied(Public key)のエラーが出て接続できませんでした。
この際パスワード認証も切っていたために、泣く泣くキーボードとHDMIケーブルをラズパイに挿して設定を見直していました。
結局は公開鍵と秘密鍵のペアの違いで、公開鍵を作成し直したら接続できましたが、このような初歩的なミスもあり得るので皆さんは気をつけてください。