
Synology DSM で、たしかに SSH を有効にして、ポートも変更したのに、外部からはまだ接続できない。この問題は、一見するとルーターのポート転送が間違っているか、アカウントやパスワードが違うように見えます。今回遭遇したのは、そのどちらでもありませんでした。
本当の落とし穴は、Synology 自身のフロントエンド状態と OpenSSH の設定ファイルの間にありました。DSM パネルには新しいポートが表示されていますが、/etc/ssh/sshd_config にはまだ古いポートが残っていました。その結果、同じ sshd プロセスが同時に2つのポートを待ち受けることになりました。1つは DSM が認識している新しいポート、もう1つは手動設定で残った古いポートです。
現場はどんな状態だったか
個人環境を公開ページに書かないため、以下では実際のホスト、アカウント、ポートを一般化しています。状況はこうでした。
- DSM の「端末」ページで SSH を有効にしていた。
- 手元の機器から
<nas-host>:<old-port>に接続すると、最初はConnection refusedだった。 - 一時的な入口からシステムに入ったあと、OpenSSH の設定ファイルが構文チェックに通らないことが分かった。
そのとき、/etc/ssh/sshd_config の先頭に OpenSSH には属さない YAML 設定が混ざっていました。内容は重要ではありません。重要なのは、それによって sshd が普通の YAML を SSH 設定として解析し、起動に失敗したことです。
Bad configuration option: version:
Bad configuration option: services:
これにより、/bin/sshd -t -f /etc/ssh/sshd_config は Bad configuration option を連続して報告します。つまり、第一の根本原因は明確でした。OpenSSH の設定ファイルが壊れていて、sshd がそもそも起動できなかったのです。
そこで、/etc.defaults/ssh/sshd_config から既定設定を復元し、SSH を起動しました。この手順で、私は小さな間違いをしました。最初に Port <old-port> をファイル末尾へ追記したのですが、既定設定の末尾はすでに Match ブロックに入っていました。OpenSSH はこう報告しました。
Directive 'Port' is not allowed within a Match block
この誤りは複雑ではありません。修正方法は、Port を全体設定領域、つまり Match より前に置くことです。修正後、sshd -t は通り、古いポートが待ち受けを始めました。
2つ目の落とし穴:フロントエンドを変えても、古い設定は消えなかった
その後、DSM のフロントエンドで SSH を新しいポートに変更しました。すると、さらに直感に反する状態になりました。
tcp 0 0 0.0.0.0:<old-port> LISTEN sshd
tcp 0 0 0.0.0.0:<new-port> LISTEN sshd
同じ sshd プロセスが2つのポートを同時に待ち受けていました。sshd -T もそれを直接確認しました。
port <old-port>
port <new-port>
なぜフロントエンドはすでに新しいポートなのに、システムにはまだ古いポートが残るのでしょうか。答えは2つのファイルにあります。
/etc/synoinfo.conf: ssh_port="<new-port>"
/etc/ssh/sshd_config: Port <old-port>
DSM 自身のポート状態は /etc/synoinfo.conf に保存されています。手動修復のときに残した Port <old-port> は OpenSSH 本来の設定です。Synology が sshd を起動するとき、両方を重ねるため、二重ポートになります。
これで、フロントエンドでは「新しいポートへの変更に成功している」ように見えるのに、実際のネットワーク動作がすっきりしない理由も説明できます。フロントエンドは嘘をついていません。DSM 自身が記録しているポートだけを表示しているのです。問題は、こちらが別に OpenSSH のポート設定を手書きで1行追加しており、DSM はそれを代わりに掃除してくれないことでした。
なぜ古いポートは認証後に切断されるのか
この点については Synology のソースコードを見ていないため、現場の証拠から判断するしかありません。
古いポートは完全に接続を拒否するわけではありません。認証成功までは進みます。sshd -ddd で一度デバッグしたところ、ログでは public key が通り、PAM account/session も通ったあと、子プロセスが stderr に短いエラーを書いていました。クライアントにはこう見えます。
Permission denied, please try again.
同じ機器、同じ管理者アカウント、同じ鍵で、新しいポートに変えると入れます。この差はアカウント権限の問題には見えず、むしろ Synology がセッション段階で /etc/synoinfo.conf の SSH ポートだけを認めているように見えます。古いポートは OpenSSH 設定によって余分に出てきた入口であり、もう DSM が認める入口ではない、ということです。
この判断を過度に広げる必要はありません。運用にとって十分な結論は、DSM の SSH ポートと sshd_config の Port に同時に話させないことです。
収束作業
修復で行ったのは1つだけです。DSM のポート情報を残し、手書きの残骸を消しました。
元の設定をバックアップします。
cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.before-remove-old-port
この行を、
Port <old-port>
コメントに変えます。
#Port <old-port>
# Removed local stale override; DSM SSH port is stored in /etc/synoinfo.conf ssh_port.
その後、チェックして reload します。
/bin/sshd -t -f /etc/ssh/sshd_config
/bin/systemctl reload sshd
修正後の有効設定には、ポートが1つだけ残りました。
port <new-port>
別の機器から検証します。
ssh -p <new-port> <admin-user>@<nas-host>
# ok
nc -vz -G 3 <nas-host> <old-port>
# Connection refused
nc -vz -G 3 <nas-host> 23
# Connection refused
これでようやく収束です。SSH は新しいポートだけを残し、古いポートは待ち受けておらず、Telnet の 23 も閉じています。
今回、どこで判断が遅れたか
最初は、アカウント、パスワード、PAM、shell、authorized_keys の権限に注意を向けていました。これらのチェックは間違いではありません。しかし、「同じアカウントで新しいポートなら入れるのに、古いポートでは認証後に切断される」という現象は説明できません。
もっと早く、この3つを実行すべきでした。
/bin/sshd -T -f /etc/ssh/sshd_config | grep '^port '
grep -n 'ssh_port' /etc/synoinfo.conf
netstat -ltnp | grep -E '(:<new-port>|:<old-port>|:23)'
この3つで、「フロントエンド状態」「OpenSSH の有効設定」「実際の待ち受けポート」を直接並べられます。3つが一致しないなら、まずパスワードや PAM を推測しないことです。
もう1つの教訓は、メーカーの既定設定を復元するとき、構文が通ることだけを見てはいけない、ということです。DSM のようなシステムは純粋な Linux サーバーではありません。独自の設定データベース、フロントエンド状態、サービススクリプトがあります。/etc/ssh/sshd_config に手動で書き込んだものは、DSM の管理パネルを上書きするのではなく、重なることがあります。
次回はこの順番で調べる
今後 DSM の SSH ポート問題に遭遇したら、この順番で進めます。
sshd -tで、まず設定ファイルを OpenSSH が解析できるか確認する。sshd -T | grep '^port 'で、OpenSSH が最終的にどのポートを認識しているか見る。grep ssh_port /etc/synoinfo.confで、DSM フロントエンドがどのポートを認識しているか見る。netstat -ltnpで、実際の待ち受けを見る。- 新しい SSH セッションを開いて検証し、確認してから Telnet を閉じる。
今回の問題を修正したあと、安定した入口は1つだけ残しました。
ssh -p <new-port> <admin-user>@<nas-host>
推測を減らし、最終状態をよく見ること。NAS のような半分 appliance、半分 Linux のシステムでは、フロントエンド状態と下層設定が同時に存在します。両者が一致しないとき、実際の動作は起動されたプロセスだけに従います。

微信
支付宝
コメント
コメントは即時公開されますが、ポリシー違反時は非表示になる場合があります。