SSHのユーザー認証を、公開鍵認証に設定するための手順（クライアント・サーバー）

## この記事について

自分用に、SSH接続のユーザー認証を、公開鍵認証に設定するハンズオンを記載しました。
クライアント・サーバーの両方の手順を記載しています。

## ハンズオン環境

ハンズオンの環境として、docker-composeで、クライアントコンテナとサーバーコンテナを作成し、各種操作を行います。
クライアント・サーバーともに、OSはubuntuです。

### Dockerファイル・docker-composeファイル

``` docker-compose.yml
services:
  ssh_host:
    build:
      context: .
      dockerfile: ./Dockerfile_ubuntu
    ports:
      - 1222:22
  
  ssh_client:
    image: ubuntu:latest
    tty: true

```

- ssh_hostコンテナの接続するためのホスト名は、`ssh_host`となります

``` Dockerfile_ubuntu
FROM ubuntu:latest

ENV SSH_HOST_USER ssh_server
ENV SSH_HOST_PASSWORD password

RUN apt update -y && apt install -y openssh-server
RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
# -m: create the user's home directory
RUN useradd -m ${SSH_HOST_USER}
RUN echo "${SSH_HOST_USER}:${SSH_HOST_PASSWORD}" | chpasswd
# new login shell for the SSH_HOSR_USER
RUN usermod -s /bin/bash ${SSH_HOST_USER}
# -A：create host key in /etc/ssh/
RUN ssh-keygen -A
# make /run/ssh
RUN mkdir /run/sshd
EXPOSE 22

# -D：sshd does not become a demon
CMD ["/usr/sbin/sshd", "-D"]
```

- `RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config`
    - クライアント側のキーファイルを転送するため、パスワード認証をONにしてます
- `RUN ssh-keygen -A`
    - ssh-keygenは、公開鍵・秘密鍵を作るためのコマンドです
    - Aオプションは、sshサーバー用の公開鍵・秘密鍵を作成します

## ユーザー認証を公開鍵認証に切り替える手順

### 1. SSH接続に必要なファイルの作成

これからの設定に必要な下記ファイルを作成していきます。

- クライアント
    - 公開鍵・秘密鍵
- サーバー
    - 公開鍵・秘密鍵
        - Dockerfileで作成済み
    - クライアント公開鍵の接続許可リスト（`~/.ssh/authorized_keys`）

#### 【クライアント】openssh-clientをインストール

サーバー側は、Dockerfileでインストール済みです。

```
ssh_client@ff7820b9a1f0:~$sudo apt -y update && sudo apt -y install openssh-client
```

#### 【クライアント】鍵を作成

```
ssh_client@ff7820b9a1f0:~$ssh-keygen -t rsa
This system has been minimized by removing packages and content that are
rsa):
Created directory '/home/ssh_client/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
...
```

#### 【サーバー】`~/.ssh/authorized_keys`作成

ssh接続するために、サーバー側が持つ公開鍵の許可リスト（`~/.ssh/authorized_keys`）に、クライアントの公開鍵を記載する必要があります。

```
ssh_server@7d2a0223cbe8:~$ mkdir -m 700 ~/.ssh
ssh_server@7d2a0223cbe8:~$ touch ~/.ssh/authorized_keys
ssh_server@7d2a0223cbe8:~$ chmod 600 ~/.ssh/authorized_keys
```

- `mkdir -m 700 ~/.ssh`
    - ssh_serverだけが、読み書き実行できるように、`~/.ssh`ディレクトリを作成します
- `chmod 600 ~/.ssh/authorized_keys`
    - ssh_serverだけが、読み書きできるように、`~/.ssh/authorized_keys`の権限を変更します

### 2. `~/.ssh/authorized_keys`にクライアントの公開鍵を登録

クライアントの公開鍵を、サーバーに転送し、`~/.ssh/authorized_keys`に書き込みます。

#### 【クライアント】公開鍵をサーバーに転送

```
ssh_client@ff7820b9a1f0:~$ scp ~/.ssh/id_rsa.pub ssh_server@ssh_host:~/.ssh/
id_rsa.pub                                                 100% 2610     1.7MB/s   00:00 
```


#### 【クライアント】パスワード認証でssh接続

Dockerfileで、パスワード認証をONにしているため、ssh_serverのパスワードを入力して、ssh接続します。

```
ssh_client@ff7820b9a1f0:~$ ssh ssh_server@ssh_host
The authenticity of host 'ssh_host (172.20.0.3)' can't be established.
ED25519 key fingerprint is SHA256:sy43SPeQhsc08V+tQdlQLE0yCQMlObkBZ350/iYEZCM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'ssh_host' (ED25519) to the list of known hosts.
ssh_server@ssh_host's password: 
```

##### Are you sure you want to continue connecting (yes/no/[fingerprint])? について

初めてのホストにSSH接続するとき、記載がないファイルは接続しますか？と表示されます。
yesを入力すると、クライアントの`~/.ssh/known_hosts`に、接続したサーバーとサーバー側の公開鍵の情報が書き込まれます。

書き込まれた情報は、サーバーのなりすましの確認をするために使われます。

2回目以降の接続時、サーバーが持つ公開鍵と`~/.ssh/known_hosts`に書き込まれた公開鍵が、異なっていた場合、そのサーバーは、初回接続時のサーバーを偽っている可能性があるということですね。

#### 【クライアント（SSHサーバーにログイン）】転送した公開鍵を、~/.ssh/authorized_keysに書き込み

```
ssh_server@e5ebaaeda57f:~$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
ssh_server@e5ebaaeda57f:~$ rm ~/.ssh/id_rsa.pub
```

### 3. サーバーのユーザー認証方式をパスワード->公開鍵認証に変更

サーバーの設定ファイル`/etc/ssh/sshd_config`には、パスワード認証のONOFF設定があります。
これをOFFにし、sshdプロセスを再起動しましょう。

#### 【サーバー（ルートユーザー）】/etc/ssh/sshd_config内のパスワード認証設定を切る

```
root@e5ebaaeda57f:/# sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
```

#### 【サーバー（ルートユーザー）】sshdのデーモンプロセスを再起動

`/etc/ssh/sshd_config`を再読み込みするため、sshdのプロセスを再起動します。

```
root@e5ebaaeda57f:/# kill --HUP `cat /var/run/sshd.pid`
```

#### 4. 接続確認

### 【クライアント】公開鍵認証でログインできることを確認

```
ssh_client@ff7820b9a1f0:~$ ssh ssh_server@ssh_host
```

## SSH接続で使用する各ファイル

SSH接続の際に使用する各種ファイルを下記にまとめます。

|| クライアント（ssh） | サーバー（sshd※） |
|:-:|:-:|:-:|
|設定ファイル| `etc/ssh/ssh_config`  | `/etc/ssh/sshd_config` |
|公開鍵| `~/.ssh/id_rsa.pub`  | `/etc/ssh/ssh_host_rsa_key.pub` |
|秘密鍵| `~/.ssh/id_rsa`  | `/etc/ssh/ssh_host_rsa_key`  |
|接続相手の公開鍵が記載されているファイル| `~/.ssh/known_hosts`  | `~/.ssh/authorized_keys` |

※ sshのdemonの略です。

## まとめ

SSH接続のユーザー認証を、公開鍵認証に設定するハンズオンを記載しました。
大まかな手順は以下です。

1. 各種ファイルの作成
    - クライアント・サーバーの公開・秘密鍵
    - `~/.ssh/authorized_keys`（サーバー側）
2. `~/.ssh/authorized_keys`に、クライアントの公開鍵を書き込み
    - パスワード認証で公開鍵を転送＆書き込みました
3. パスワード認証のOFF・sshdプロセスの再起動
    - パスワード認証の設定は、`/etc/ssh/sshd_config`にあります
    - 設定を書き換えたら、再読み込みのためプロセスを再起動させましょう