普通、/etc/ssh/sshd_config.d に「50-cloud-init.conf」と「51-host.conf」の2つの設定ファイルがあったら、「50-cloud-init.conf」の設定を「51-host.conf」が上書きをする、と思ってしまうのだが。。。

現象確認

使用しているOSは、Ubuntu 26.04.1

$ cat /etc/os-release | head -4
PRETTY_NAME="Ubuntu 26.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="26.04"
VERSION="26.04.1 LTS (Resolute Raccoon)"

sshd にて、「/etc/ssh/sshd_config.d/51-host.conf」を追加している 後は、デフォルトの設定で、sshd_config 等は変更していない

$ ls -l /etc/ssh/sshd_config.d/*
-rw------- 1 root root 27 Oct 19 18:13 /etc/ssh/sshd_config.d/50-cloud-init.conf
-rw------- 1 root root 81 Oct 20 07:54 /etc/ssh/sshd_config.d/51-host.conf

それぞれの内容は次のとおり「50-cloud-init.conf」は最初から存在していたファイル

/etc/ssh/sshd_config.d/50-cloud-init.conf

PasswordAuthentication yes

/etc/ssh/sshd_config.d/51-host.conf

Port 22022
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

ご覧のようにポート番号を22022に設定、また PasswordAuthentication no としパスワードによる認証を拒否している。 この設定で、sshd を再起動するも、ポート 22022 で接続できず、また 22番で接続してもパスワードを要求してしまう。

「sshd -T」の結果は以下のとおり。

$ sudo sshd -T | grep -E '(port|password)'
port 22022
passwordauthentication yes
permitemptypasswords no
gatewayports no

PasswordAuthentication はデフォルトの no のままだが、ポートは設定どおり「22022」になっている。 だけど、22番でLISTENしている。。。(なぜ?)

$ ss -ant
State       Recv-Q      Send-Q              Local Address:Port                Peer Address:Port
LISTEN      0           4096                   127.0.0.54:53                       0.0.0.0:*
LISTEN      0           4096                127.0.0.53%lo:53                       0.0.0.0:*
LISTEN      0           4096                      0.0.0.0:22                       0.0.0.0:*
LISTEN      0           4096                         [::]:22                          [::]:*

ちなみに ufw の設定は以下のとおり。環境構築中のため「22/tcp」も許可している。

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
22022/tcp                  ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
22022/tcp (v6)             ALLOW       Anywhere (v6)

sshdのポートを 22022番に、かつ、パスワード要求をしないようにしたいのだが。。。

解決編

ポート番号が変更されない理由

Ubuntu では systemd の ssh.socket が SSH の待ち受けポートを管理しているらしい。

/etc/systemd/system/ssh.service.requires/ssh.socket

[Unit]
Description=OpenBSD Secure Shell server socket
Before=sockets.target ssh.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Socket]
ListenStream=0.0.0.0:22
ListenStream=[::]:22
BindIPv6Only=ipv6-only
Accept=no
FreeBind=yes

[Install]
WantedBy=sockets.target
RequiredBy=ssh.service

そう、ここに記載しているとおり ssh.socket は 22 番で待ち受けている。 ssh.socket サービスの状態を見てみる。

$ sudo systemctl status ssh.socket
● ssh.socket - OpenBSD Secure Shell server socket
     Loaded: loaded (/usr/lib/systemd/system/ssh.socket; enabled; preset: enabled)
     Active: active (running) since Tue 2026-10-20 07:44:58 JST; 40min ago
 Invocation: 7327f792a6584e7fb0d20962cd74ab66
   Triggers: ● ssh.service
     Listen: 0.0.0.0:22 (Stream)
             [::]:22 (Stream)

つまり、systemd が接続を受け付けて、sshd を起動・連携しているという Socket Activation の機能で行っている。 サイトを色々あさってみると、「systemctl disable --now ssh.socket」で無効化したり、「sshd.socket」を編集してポート番号を変更したり、という方法が紹介されているが、sshd_config での Port 変更だけでも、次のように実行すれば変更したポート番号 22022 でLISTENしてくれるようになる。

$ sudo systemctl daemon-reload
$ sudo systemctl restart ssh.socket
$ sudo systemctl status ssh.socket
$ ss -antl
State       Recv-Q      Send-Q              Local Address:Port                Peer Address:Port
LISTEN      0           4096                   127.0.0.54:53                       0.0.0.0:*
LISTEN      0           4096                127.0.0.53%lo:53                       0.0.0.0:*
LISTEN      0           4096                      0.0.0.0:22022                    0.0.0.0:*
LISTEN      0           4096                         [::]:22022                       [::]:*

confファイルの読み込み優先順

たとえば、PasswordAuthentication の設定を sshd_config に直接次のように記載してみる。

/etc/sshd/sshd_config

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

上記のように、「yes」が先、「no」が後、どちらの設定が有効化されるか確認してみる。

$ sudo sshd -T | grep password
passwordauthentication yes
permitemptypasswords no

先に設定した「yes」が有効になっている。 今度は、その設定を逆順にしてみる。

/etc/sshd/sshd_config

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

上記のように、「no」が先、「yes」が後、どちらの設定が有効化されるか確認してみる。

$ sudo sshd -T | grep password
passwordauthentication yes
permitemptypasswords no

今度もまた「yes」、どちらにしても「passwordauthentication yes」になってしまうのはなぜ?

ここで、「50-cloud-init.conf」で設定されている「PasswordAuthentication yes」が影響しているのでは?ということで、このファイル名をリネーム「50-cloud-init.conf.disable」、すなわち「.conf」で終わらない名前に変更してみて、sshd を再起動してみる。

$ sudo mv /etc/ssh/sshd_config.d/50-cloud-init.conf /etc/ssh/sshd_config.d/50-cloud-init.conf.disable
$ sudo systemctl restart ssh

すると、

$ sudo sshd -T | grep password
passwordauthentication no
permitemptypasswords no

となった。 OpenSSH のサーバ設定では、通常、同じ設定項目が複数回指定された場合、原則として最初に取得した値が採用されるらしい。

結論

sshd_config の設定を上書きしたい場合は、/etc/ssh/sshd_config を直接編集するのではななく、 /etc/ssh/sshd_config.d の中に、「50-cloud-init.conf」より先に読み込まれるファイル名、例えば「00-host.conf」のようなファイルを作成して、そこに、

/etc/ssh/sshd_config.d/00-host.conf

Port 22022
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

のように記載する。ファイル名からこちらの設定が先に読み込まれるので、こちらの設定が有効になる。 そして、ポート番号「Port 22022」のように変更した場合は、ssh.socket サービスを再起動させないと有効にならないということ。