オンプレLinuxでSSH公開鍵認証の設定をしてみよう

## はじめに
近年、AWSやAzureに代表されるパブリック・クラウドの利用が加速する時代となり、Linuxもクラウドで使う機会が多いかと思います。クラウド上のLinuxへのログオンは、公開鍵認証を使用したSSH(Secure Shell)アクセスを行うことで実現します。公開鍵認証はご存じの通り、公開鍵・秘密鍵のペアで認証を行う物であり、基本的にクラウドで鍵を作成することが可能です。
ただクラウドの場合、実際の設定作業は内部で自動的に実施してくれるため、具体的な設定内容がわからなくても、秘密鍵さえもっていればログオンできてしまいます。それ故、ある日突然、オンプレのLinuxでSSH公開鍵認証を使用できるように設定作業が必要となった場合、困ってしまうことになるかと思います。
そこで、本記事では筆者のRedhat Enterprise Linux V8.9を題材に、LinuxでSSH公開鍵認証の設定方法を簡単にまとめてみましたので、ご紹介します。(SSHは、Linuc Level2認定試験で問われるエリアの1つにもなっています。)

## Linux側でのSSH設定作業
ここでの作業は、まだSSH接続が出来ていない状態ですので、Linuxのデスクトップ環境上のTerminal、もしくは、LinuxのCUI(Character User Interface)上で作業を行います。
### SSHサーバーの用意

SSH接続を使用する場合、[OpenSSH](https://www.openssh.com/)を使用することが一般的かと思います。今回はLinux側をSSHサーバーとするため、「openssh-server」という名前のパッケージをインストールします。
```
[testuser@localhost ~]$ sudo dnf install openssh-server
```
「openssh-server」はオープン・ソースのSSHデーモンです。インストール後は、下記コマンドでSSHデーモンを起動します。
```
[testuser@localhost ssh]$ sudo systemctl start sshd
```
また、Linuxのブート時にSSHデーモンを起動できるようにすべく、下記のコマンドも実行しておきます。
```
[testuser@localhost ssh]$ sudo systemctl enable sshd
```
この後、「sudo systemctl status sshd」コマンドを実行して、下記のような出力になっていれば、まずはOKです。
```
● sshd.service - OpenSSH server daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset>
   Active: active (running) since Sat 2024-04-06 17:18:55 JST; 1h 20min ago
     Docs: man:sshd(8)
           man:sshd_config(5)
 Main PID: 1217 (sshd)
    Tasks: 1 (limit: 22810)
   Memory: 5.6M
   CGroup: /system.slice/sshd.service
           mq1217 /usr/sbin/sshd -D -oCiphers=aes256-gcm@openssh.com,chacha20-p>

 4月 06 17:18:55 localhost.localdomain systemd[1]: Starting OpenSSH server daem>
 4月 06 17:18:55 localhost.localdomain sshd[1217]: Server listening on 0.0.0.0 >
 4月 06 17:18:55 localhost.localdomain sshd[1217]: Server listening on :: port >
 4月 06 17:18:55 localhost.localdomain systemd[1]: Started OpenSSH server daemo>
 4月 06 17:19:58 localhost.localdomain sshd[2614]: Accepted publickey for test>
 4月 06 17:19:58 localhost.localdomain sshd[2614]: pam_unix(sshd:session): sess```
 ```
 ### パスワード認証でSSH接続
 SSHサーバー・デーモンのインストールが終わると、/etc/sshディレクトリ内に「sshd_config」という名前の構成ファイルが作成されます。インストール直後は、デフォルトでパスワード認証が使えるような設定となっています。また、ユーザー自身で変更しない限り、SSH接続で使用するポート番号は22番となっています。
#### ファイアウォール設定状況の確認
ファイアウォールにおいて、事前に22番ポートが開放されていることを確認します。Redhat Enterprise Linuxの場合、firewall-cmdで確認します。firewall-cmdについては、以前に投稿した下記の記事でも紹介していますので、そちらを参考にしてください。

https://qiita.com/duelist2020jp/items/cbb5e3632131ba7fe951


```
[testuser@localhost ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: bridge0 ens192
  sources:
  services: cockpit dhcpv6-client ipsec
  ports: 990/tcp 40000-50000/tcp 21/tcp 22/tcp
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```
上記の出力結果のports列に「22/tcp」という設定がされていますので、22番ポートは開放されています。開放されていない場合は、事前にポートの開放をしておいてください。

#### 端末エミュレータからパスワード認証でSSHログオン確認
Teraterm等の端末エミュレータを使用して、SSHログオンができるか否かを確認します。なお、極力最新の認証アルゴリズムに対応できるように、TeratermはV5.0以上のものをダウンロード・インストールして使用いただくことをお奨めします。

https://forest.watch.impress.co.jp/library/software/utf8teraterm/

Teratermのアイコンをクリックすると、下記のような画面が出ますので、接続先のIPアドレスを入力し、「OK」ボタンを押下します。(IPアドレスはサンプルです。)

![q1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/aa867fb4-bcc3-f102-e606-c4edb49d2503.jpeg)

次に下記のような画面が出ますので、接続先のユーザーIDとパスワードを入力して、「OK」ボタンを押し下げします。

![q2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/f3efa2df-c5c6-4809-a1ce-6a7089237a61.jpeg)

ログオンに成功すると、Teraterm上で作業を行うことが可能になります。ここでログオンに失敗した場合は、ユーザーIDやパスワードが間違っていないか等確認してください。

![q3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/cf2143d2-3d5d-e325-a95c-9ab64a92a3fc.jpeg)

### 公開鍵と秘密鍵の作成
公開鍵認証に必要な公開鍵と秘密鍵を作成します。作成は、SSHサーバー側のLinuxでも、接続元のクライアントPC環境のどちらで作成しても構いません。今回は、Windows11 PCにインストールしている「Git Bash」アプリ上で「ssh-keygen」コマンドを実行して作成しています。
```
$ ssh-keygen -t ecdsa        <== -tオプションで、認証アルゴリズムを指定。今回はecdsaを採用。
Generating public/private ecdsa key pair.
Enter file in which to save the key (/c/Users/testuser/.ssh/id_ecdsa): rh_id_ecdsa
Enter passphrase (empty for no passphrase):          <== パスワード無しの場合は空エンター
Enter same passphrase again:                         <== パスワード無しの場合は空エンター
Your identification has been saved in rh_id_ecdsa
Your public key has been saved in rh_id_ecdsa.pub
The key fingerprint is:
SHA256:S5QxNCnUZRlOoPNt+FuC9JtoTq5XO4jXPSO/xRVdZwc testuser@LAPTOP-CQMQ12C4
The key's randomart image is:
+---[ECDSA 256]---+
|     ..o*+=o  E.=|
|      ..oO.    .=|
|      o.o .    ..|
|       + o      .|
|        S o     .|
|       o *.  . . |
|       .+++o. o  |
|      .o=.=*+.   |
|      .*+ ++o+   |
+----[SHA256]-----+
```
次にSCPコマンドを実行して、先ほど作成した公開鍵(末尾に".pub"が付与されているもの)を、接続先のLinuxにアップロードします。
```
$ scp ./rh_id_ecdsa.pub testuser@192.168.20.129:/home/testuser/.ssh/rh_id_ecdsa.pub
rh_id_ecdsa.pub                               100%  186    11.2KB/s   00:00
```
Linux側の転送先のディレクトリに公開鍵ファイルが存在することを確認します。
```
[testuser@localhost ~]$ ls -l ~/.ssh/rh_id_ecdsa.pub
-rw-r--r--. 1 testuser testuser 186  4月  6 19:49 /home/testuser/.ssh/rh_id_ecdsa.pub
```
#### SSHサーバー構成ファイルの修正
公開鍵認証ができるように、/etc/ssh/sshd_configファイルの中身を修正します。具体的には下記のステートメントがデフォルトではコメントアウトされているので、先頭文字の#を外して有効化します。
```
PubkeyAuthentication yes
```
また、下記の記述に見られるように、クライアントが秘密鍵を指定してログオンを試みると、サーバー側は「.ssh/authorized_keys」ファイルの中身に格納されている公開鍵の情報を比較して、鍵の整合性をチェックします。
```
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile      .ssh/authorized_keys
```
::: note warn
ここで注意なのが、.sshディレクトリはログオン先のユーザー・ディレクトリ内に存在するので、「~/.ssh/authorized_keys」と思わず書き換えてしまいたくなりますが、ここは手を加えないようにしてください。さもないと、公開鍵認証が正しく動作しなくなってしまいます。
:::

#### authorized_keysファイルの作成
環境によっては、接続先ユーザーの.sshディレクトリ配下にauthorized_keysファイルがある場合もありますが、ない場合もあります。authorized_keysファイルは、公開鍵の情報を格納するファイルですので、下記コマンドで公開鍵の情報を書き込みます。
```
[testuser@localhost .ssh]$ cat rh_id_ecdsa.pub > authorized_keys
```
後は、「chmod 600 authorized_keys」コマンドで、ファイルのアクセス権を変更しておきます。アップロードした公開鍵は残しておいても削除してもどちらでも構いません。

#### SSHサーバー・デーモンのリスタート
構成ファイルの中身を修正したので、下記コマンドでSSHサーバー・デーモンを再起動します。エラー・メッセージが出なければ問題ありません。
```
[testuser@localhost ~]$ sudo systemctl restart sshd
```
### 端末エミュレータから公開鍵認証を使用してSSHログオン確認
Teratermアイコンをクリック後、パスワード認証時と同様に下記の画面で、接続先IPアドレスを指定して「OK」ボタンを押下します。
![q1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/6c367b1f-d23a-8fe5-d7af-5bb80c6cf732.jpeg)
下記の画面で、接続先のユーザーID、及び、作成した秘密鍵を指定の上、「OK」ボタンを押下します。
![q4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/6b0533b1-1bf8-ee08-b23e-dfa0d5a1a152.jpeg)
パスワード認証時と同様にログオン成功すれば、以後はTeratermで継続作業可能です。
![q5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/311afdef-3c2b-b9e3-b447-cb2c81b4e25a.jpeg)

この後は、よりセキュリティーを強化すべく、下記の設定を/etc/ssh/sshd_configにされることをお奨めします。
```
PermitRootLogin no              <== ルートユーザーでのSSHログオンを使用不可にする
PasswordAuthentication no       <== パスワード認証を使用不可にする。
```

## さいごに
今回は、筆者のLinux環境を元に、公開鍵認証を使用したLinuxでのSSH設定作業内容をご紹介しました。実際の設定の仕組みを理解していると、クラウド上のLinuxへの公開鍵認証でエラーになったような場合にも、エラーの勘所を見つけてトラブルシューティングが出来るようになるかなと思います。
また、IaCツールのAnsibleも管理対象サーバーへのアクセスはSSH接続を使用しますので、SSH接続の理解は必要になってきます。
ハイブリッド・クラウドの形態をもった企業が多くなってきている中、オンプレのLinuxとクラウドのLinux間でSSH接続をしたりすることもあるかと思いますので、数ある接続方式の中でもSSH接続の仕組みを最初にマスターするのが個人的にはお奨めです。