🔑

Ubuntu(22.04 LTS)におけるSSH環境の構築

2024/06/05に公開

はじめに

レンタルサーバ(ConoHa)を借りて SSH 設定を行ったため、備忘録と知識の整理も兼ねて記録する。

SSHとは

Secure Shell(セキュア シェル、SSH)は、暗号や認証技術を利用して、安全にリモートコンピュータと通信するためのプロトコル。パスワードなどの認証を含むすべてのネットワーク上の通信が暗号化される。
(Wikipedia より)
簡単に言えば、安全にリモートのシェルを利用するためのプロトコル(通信規格)である。
SSH の認証方式として、パスワード認証と公開鍵認証の 2 種類がある。

パスワード認証方式

パスワード認証方式は、ユーザー名とパスワードでログインする方式である。
一般的なログイン方法と同様に、ユーザーが自分のユーザ名とパスワードを入力してサーバーにアクセスする。
公開鍵暗号方式と比べて簡単に利用できる一方、デメリットとして ID+パスワード認証方式による脆弱性がある。

公開鍵認証方式

公開鍵認証方式は公開鍵と秘密鍵の2つの鍵(キーペア)を使用した接続方式である。
ユーザーは公開鍵をサーバーに登録し、接続する際に秘密鍵を使用して認証が行われる。
メリットとしてパスワード方式と比べてセキュリティが向上するが、設定が難しいというデメリットがある。

本記事では、Ubuntu にて公開鍵暗号方式を用いたログインを行う設定について記録を残す。
なお本記事の内容は、macOS または Linux 向けを想定している。
(Windows ユーザ様すみません)

環境

  • サーバ(ConoHa)
    OS:Ubuntu 22.04.2
    SSH:OpenSSH_8.9p1 Ubuntu-3ubuntu0.3, OpenSSL 3.0.2 15 Mar 2022
  • 再現サーバ(Proxmox)
    OS:Ubuntu 24.04
    SSH:OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
  • クライアント(MacBook Pro)
    OS:macOS Vemtura 13.4.1(クライアント)
    SSH:OpenSSH_9.0p1, LibreSSL 3.3.6

導入編

鍵生成編

まずは、クライアント側で公開鍵と秘密鍵を作成する。
鍵の作成時に暗号方式を指定できる。今回は記事作成時点で RSA よりも安全面と性能面で最強と言われている、楕円曲線ベースの公開キーシステムである ed25519 方式で作成する。

まず、鍵を作成するコマンドを実行する。この時鍵生成方式(暗号アルゴリズム)を
オプション(-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa)を用いて指定する。
指定がない場合暗号アルゴリズムは rsa を用いて鍵が作成される。
他にもオプションがあるが、各オプションについてはマニュアルを読んでみてください。

% sudo ssh-keygen -t ed25519

次に、鍵をどこに出力するか問われる。

Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/koba-mac/.ssh/id_ed25519):

何も指定をせず Enter をした場合、かっこの中のパスに保存される。
(この場合には、/Users/koba-mac/.ssh に id_ed25519 という鍵が生成される。)
今回は/Users/koba-mac/.ssh に conoha という鍵を生成するようにした。

Enter file in which to save the key (/Users/koba-mac/.ssh/id_ed25519): /Users/koba-mac/.ssh/conoha

すると、今度は鍵のパスフレーズをどうするか問われる。

Enter passphrase (empty for no passphrase):

これは、鍵をパスワードで暗号化するものである。
暗号化することで、万が一に鍵が流失したとしても、使えないようにできる。
(しかし、気休め程度らしい...)
ただしこの場合、自分が認証する場合でもパスワードを入力する必要がある。
(パスワードの入力を最初だけ行い、以降省略出来る方法があるが今回は扱わない。)
設定しない場合は何もせず Enter で良い。

パスフレーズは 2 回聞かれる。(設定しない場合ここも Enter で良い)

Enter same passphrase again:

パスフレーズを 2 回入力後、鍵が生成される。

Your identification has been saved in /Users/koba-mac/.ssh/conoha
Your public key has been saved in /Users/koba-mac/.ssh/conoha.pub
The key fingerprint is:
SHA256:NEFIVohDTtdVFCBUQ7RdHCRd7txfOYjnxTABpi31gV8 koba-mac@Kobas-MacBook-Pro.local
The key's randomart image is:
+--[ED25519 256]--+
|   .oo+B*=BBBB+o.|
|   oooo .o==.o=E |
|    ..  oo..o+. .|
|       . .. ..=oo|
|        S  . o ==|
|            o . +|
|             .  .|
|                 |
|                 |
+----[SHA256]-----+

Your identification has been saved in /Users/koba-mac/.ssh/conoha
Your public key has been saved in /Users/koba-mac/.ssh/conoha.pub

これで、/Users/koba-mac/.ssh に秘密鍵 conoha と公開鍵 conoha.pub が生成される。
鍵を保存する際に鍵の名前を指定しない場合、秘密鍵 id_ed25519 と公開鍵 id_ed25519.pub が生成される。

サーバ設定編

今度は、サーバ側に鍵を登録する。
まず、「ssh でログインしたいユーザ」でサーバのコンソールにログインする。

ファイアウォール設定編

自宅内ではなく公開レンタルサーバなどのファイアウォール下でないサーバである場合は、opensshサーバをインストールする前にファイアウォールを確認する。
openssh サーバをインストールすると、すぐ ssh が有効になってしまう。
デフォルトでは、パスワード認証方式と公開鍵認証方式両方が有効になるため、セキュリティ的リスクがある。(個人の意見)
自宅の場合は基本ルータのファイアウォール下であるため、外部から接続される問題がない。
(DMZ などに置いている場合は除く)
しかし、レンタルサーバや DMZ 下などといったファイアウォール下ではない場合、外部から接続を試みられてしまう可能性がある。
そこで、ssh のデフォルトポート番号である 80 番を事前に閉じておく。

ただし、すでに ssh で接続して操作している場合ファイアウォールを有効にすると接続できなくなってしまうため、この章をスキップしてください。(今回は考慮しない。)

ファイアウォールの設定は、ubuntu に標準でインストールされている ufw を使用する。
Uncomplicated Firewall(UFW)は、簡単に使用できるよう設計された、netfilter(英語版)ファイアウォールの管理プログラムである。(Wikipedia より)
まず ufw がインストールされているか確認する。

$ sudo ufw status
Status: inactive

インバウンド(incoming)トラフィックをデフォルトでブロックするように設定する。

$ sudo ufw default deny
[sudo] password for koba:
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly) 

ufw を有効化する。

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y 
Firewall is active and enabled on system startup

opensshサーバのインストール

サーバのパッケージマネージャをアップデートする。

$ sudo apt update

サーバに openssh サーバをインストールする。

$ sudo apt install openssh-server
インストールの過程
koba@kobapc-dev:~$ sudo apt install openssh-server <-上のコマンド
[sudo] password for koba:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  libwrap0 ncurses-term openssh-sftp-server ssh-import-id
Suggested packages:
  molly-guard monkeysphere ssh-askpass
The following NEW packages will be installed:
  libwrap0 ncurses-term openssh-server openssh-sftp-server ssh-import-id
0 upgraded, 5 newly installed, 0 to remove and 17 not upgraded.
Need to get 880 kB of archives.
After this operation, 6,861 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://jp.archive.ubuntu.com/ubuntu noble/main amd64 openssh-sftp-server amd64 1:9.6p1-3ubuntu13 [37.3 kB]
Get:2 http://jp.archive.ubuntu.com/ubuntu noble/main amd64 libwrap0 amd64 7.6.q-33 [47.9 kB]
Get:3 http://jp.archive.ubuntu.com/ubuntu noble/main amd64 openssh-server amd64 1:9.6p1-3ubuntu13 [510 kB]
Get:4 http://jp.archive.ubuntu.com/ubuntu noble/main amd64 ncurses-term all 6.4+20240113-1ubuntu2 [275 kB]
Get:5 http://jp.archive.ubuntu.com/ubuntu noble/main amd64 ssh-import-id all 5.11-0ubuntu2 [10.0 kB]
Fetched 866 kB in 3s (277 kB/s)
Preconfiguring packages ...
Selecting previously unselected package openssh-sftp-server.
(Reading database ... 80404 files and directories currently installed.)
Preparing to unpack .../openssh-sftp-server_1%3a9.6p1-3ubuntu13_amd64.deb ...

~~ 省略 ~~

Running kernel seems to be up-to-date.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.

Unit sshd.service could not be found.

インストールが完了したら、以下のコマンドでバージョンが確認できると思う。

koba@kobapc-dev:~$ openssl version
OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)

sshconfigの設定

次に ssh の config を編集して設定する。
以下が ssh のディレクトリ内容である。

/etc/ssh/
├── ssh_config             # SSH クライアント設定ファイル
├── sshd_config            # SSH サーバー設定ファイル
├── ssh_host_rsa_key       # SSH ホスト RSA 秘密鍵
├── ssh_host_rsa_key.pub   # SSH ホスト RSA 公開鍵
├── ssh_host_ecdsa_key     # SSH ホスト ECDSA 秘密鍵 
├── ssh_host_ecdsa_key.pub # SSH ホスト ECDSA 公開鍵
├── ssh_host_ed25519_key   # SSH ホスト Ed25519 秘密鍵
├── ssh_host_ed25519_key.pub # SSH ホスト Ed25519 公開鍵
├── moduli                 # Diffie-Hellman グループ交換用の素数
├── ssh_import_id          # SECURID 認証用の設定ファイル
├── sshd_config.d/         # SSHD 設定ファイルの追加ディレクトリ
│   └── ...
└── ssh_known_hosts        # 既知のホスト公開鍵のデータベース

基本は、config ファイルは sshd_config だけだが、ConoHa の場合は sshd_config.d 下にも config がある。この場合は両方編集する必要がある。

まず、/etc/ssh/sshd_config を編集する。
お好きなテキストエディタで /etc/ssh/sshd_config を編集する。
このとき、管理者として実行する。

$ sudo vim /etc/ssh/sshd_config

以下の項目を変更する。

  • ポート番号の変更 22 番から 10022 に変更
  • Root でのログインを禁止
  • パスワード認証を禁止
  • 公開鍵認証を明示的に有効化(デフォルトで有効)

各設定項目についてはマニュアルを読んでみてください。

以下がファイルの変更差分である。

/etc/ssh/sshd_config
# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Include /etc/ssh/sshd_config.d/*.conf

- #Port 22
+ Port 10022
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
- #PermitRootLogin prohibit-password
+ PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

- #PubkeyAuthentication yes
+ PubkeyAuthentication yes
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
- #PasswordAuthentication yes
+ PasswordAuthentication no
#PermitEmptyPasswords no


# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
KbdInteractiveAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin prohibit-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# override default of no subsystems
Subsystem       sftp    /usr/lib/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server

次に sshd_config.d 下に config ファイルがある場合こちらも編集する。
基本 config は/etc/ssh/sshd_config.d 配下にある設定が優先される。
自分が借りた ConoHa ではデフォルトで、sshd_config.d 配下に config ファイルが追加されており、ルートログインが許可されるようになっていた。

PermitRootLogin prohibit-password

(そのため、Root ログインを自分では無効にしていたつもりが、無効にできていなかった事件があった。)
そこで、これの行を削除して対応した。
また、config をデフォルトから変更する場合は、sshd_config.d 配下に config ファイルを作ってそちらに記述する方がいいとコメントがあった。

sshd_config内にあったコメントアウト文
# To modify the system-wide sshd configuration, create a  *.conf  file under
#  /etc/ssh/sshd_config.d/  which will be automatically included below
sshd_config内にあったコメントアウト文の翻訳(chatGPT)
システム全体の sshd 設定を変更するには、/etc/ssh/sshd_config.d/ に *.conf ファイルを作成してください。
このファイルは自動的に以下に含まれる。

しかし、なぜか自分は sshd_config.d 配下に config ファイルを作る方法では設定が再起動をしないと反映されない問題が起きたため、今回はこのまま進むことにした。
原因調査中。解決したら記事を書く予定。
config ファイルが書けたら、sshd サービスを systemctl に登録する。

$ sudo systemctl enable ssh
Synchronizing state of ssh.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable ssh
Created symlink /etc/systemd/system/sshd.service → /usr/lib/systemd/system/ssh.service.
Created symlink /etc/systemd/system/multi-user.target.wants/ssh.service → /usr/lib/systemd/system/ssh.service.

config を再読み込みさせるため restart させる。

$ sudo systemctl restart sshd

sshd サービスを起動しているか(active になっているか)確認する。

sudo systemctl status sshd
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Tue 2024-06-04 19:03:32 UTC; 1s ago
TriggeredBy: ● ssh.socket
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 1229 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 1231 (sshd)
      Tasks: 1 (limit: 2276)
     Memory: 1.2M (peak: 1.5M)
        CPU: 29ms
     CGroup: /system.slice/ssh.service
             └─1231 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

Jun 04 19:03:32 koba-dev systemd[1]: Starting ssh.service - OpenBSD Secure Shell server...
Jun 04 19:03:32 koba-dev sshd[1231]: Server listening on 0.0.0.0 port 10022.
Jun 04 19:03:32 koba-dev sshd[1231]: Server listening on :: port 10022.
Jun 04 19:03:32 koba-dev systemd[1]: Started ssh.service - OpenBSD Secure Shell server.

このとき、ポート番号が自分で設定したポート番号になっていれば問題ない。
(この場合は、port を 10022 に設定していたので、10022 になっていれば良い。)

Jun 04 19:03:32 koba-dev sshd[1231]: Server listening on 0.0.0.0 port 10022.

公開鍵を設定する

公開鍵情報を /home/sshログインを行うユーザ名/.ssh/authorized_keys に追加する。
ユーザ名 koba に公開鍵を登録する場合。ユーザディレクトリー配下に .ssh というディレクトリがあるので、その中の authorized_keys というファイルに公開鍵の文字列を追加する。
公開鍵情報は、鍵生成編で作成された .pub という拡張子がつくファイルの中に書かれている。
鍵生成編の場合は、conoha.pub というファイルの中に公開鍵情報が書かれている。

vim /home/koba/.ssh/authorized_keys
/home/koba/.ssh/authorized_keys

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKLb6HWe0oDJpJwvvvVrU/D3sLxE6XoJHDL10UWDroOP koba-mac@Kobas-MacBook-Pro.local

ファイアウォールを設定していた場合

ファイアウォールを設定していた場合、現状だとファイアウォールによって ssh のポートが空いていないため、ssh のポートを解放する。
ssh を port 番号 10022 で指定していた場合、ポート 10022 を開放する。

$ sudo ufw allow 10022

接続編

実際に接続を試してみる。接続は以下のコマンドで行える。

ssh ユーザ名@IPアドレス -p sshのポート番号 -i 鍵のパス

今回の場合は以下のようになる。

$ ssh koba@192.168.1.58 -p 10022 -i /Users/koba-mac/.ssh/conoha
koba@192.168.1.58's password: 鍵のパスワードを入力(設定していない場合はスキップされる)

終わりに

以上が基本的な設定になる。
拙い文章でしたが、ここまで読んでいただき感謝する。

個人的な意見

sshd_config の設定はさまざまな流派がある。今回自分が示したものも一例であり、人によってセキュリティ方針や宗教が異なると思う。
私の設定を鵜呑みにせず、紹介したマニュアルページを調べて自分の環境に合わせた設定することを強くお勧めする。
私はよく研究室の先輩に、「ブログの記事なんて参考にせずマニュアルを見にいけよ」と言われる。そんなのは慣れている人だから言えるであって、我々初心者にはとてもハードルが高いと自分は考える。なので「人のブログなどを参考にして概要を掴み、その後マニュアルを読んで勉強する」ことがとても大事だと思う。
マニュアルを読む癖をつけることによって、最終的にはマニュアルだけで理解できるようになると考えている。

スペシャルサンクス

以下の方々にご協力いただいた。深く感謝する。

Discussion