# Synology DSM で SSH ポートを開けても接続できない：ポートずれの振り返り

![{群晖|シノロジー} DSM {前端|フロントエンド}ポートと sshd {設定|せってい}の{分裂|ぶんれつ}{模式図|もしきず}](https://img.leeguoo.com/media/6a321a71-660f-4b08-b4e7-ef6a89c09be2/synology-ssh-port-drift.webp)

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 {設定|せってい}として{解析|かいせき}し、{起動|きどう}に{失敗|しっぱい}したことです。

```text
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 はこう{報告|ほうこく}しました。

```text
Directive 'Port' is not allowed within a Match block
```

この{誤|あやま}りは{複雑|ふくざつ}ではありません。{修正|しゅうせい}{方法|ほうほう}は、`Port` を{全体|ぜんたい}{設定|せってい}{領域|りょういき}、つまり `Match` より{前|まえ}に{置|お}くことです。{修正|しゅうせい}後、`sshd -t` は{通|とお}り、{古|ふる}いポートが{待|ま}ち{受|う}けを{始|はじ}めました。

## 2つ{目|め}の{落|お}とし{穴|あな}：フロントエンドを{変|か}えても、{古|ふる}い{設定|せってい}は{消|き}えなかった

その後、DSM のフロントエンドで SSH を{新|あたら}しいポートに{変更|へんこう}しました。すると、さらに{直感|ちょっかん}に{反|はん}する{状態|じょうたい}になりました。

```text
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` もそれを{直接|ちょくせつ}{確認|かくにん}しました。

```text
port <old-port>
port <new-port>
```

なぜフロントエンドはすでに{新|あたら}しいポートなのに、システムにはまだ{古|ふる}いポートが{残|のこ}るのでしょうか。{答|こた}えは2つのファイルにあります。

```text
/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 に{短|みじか}いエラーを{書|か}いていました。クライアントにはこう{見|み}えます。

```text
Permission denied, please try again.
```

{同|おな}じ{機器|きき}、{同|おな}じ{管理者|かんりしゃ}アカウント、{同|おな}じ{鍵|かぎ}で、{新|あたら}しいポートに{変|か}えると{入|はい}れます。この{差|さ}はアカウント{権限|けんげん}の{問題|もんだい}には{見|み}えず、むしろ Synology がセッション{段階|だんかい}で `/etc/synoinfo.conf` の SSH ポートだけを{認|みと}めているように{見|み}えます。{古|ふる}いポートは OpenSSH {設定|せってい}によって{余分|よぶん}に{出|で}てきた{入口|いりぐち}であり、もう DSM が{認|みと}める{入口|いりぐち}ではない、ということです。

この{判断|はんだん}を{過度|かど}に{広|ひろ}げる{必要|ひつよう}はありません。{運用|うんよう}にとって{十分|じゅうぶん}な{結論|けつろん}は、DSM の SSH ポートと `sshd_config` の `Port` に{同時|どうじ}に{話|はな}させないことです。

## {収束|しゅうそく}{作業|さぎょう}

{修復|しゅうふく}で{行|おこな}ったのは1つだけです。DSM のポート{情報|じょうほう}を{残|のこ}し、{手書|てが}きの{残骸|ざんがい}を{消|け}しました。

{元|もと}の{設定|せってい}をバックアップします。

```bash
cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.before-remove-old-port
```

この{行|ぎょう}を、

```text
Port <old-port>
```

コメントに{変|か}えます。

```text
#Port <old-port>
# Removed local stale override; DSM SSH port is stored in /etc/synoinfo.conf ssh_port.
```

その後、チェックして reload します。

```bash
/bin/sshd -t -f /etc/ssh/sshd_config
/bin/systemctl reload sshd
```

{修正|しゅうせい}後の{有効|ゆうこう}{設定|せってい}には、ポートが1つだけ{残|のこ}りました。

```text
port <new-port>
```

{別|べつ}の{機器|きき}から{検証|けんしょう}します。

```bash
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つを{実行|じっこう}すべきでした。

```bash
/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 ポート{問題|もんだい}に{遭遇|そうぐう}したら、この{順番|じゅんばん}で{進|すす}めます。

1. `sshd -t` で、まず{設定|せってい}ファイルを OpenSSH が{解析|かいせき}できるか{確認|かくにん}する。
2. `sshd -T | grep '^port '` で、OpenSSH が{最終的|さいしゅうてき}にどのポートを{認識|にんしき}しているか{見|み}る。
3. `grep ssh_port /etc/synoinfo.conf` で、DSM フロントエンドがどのポートを{認識|にんしき}しているか{見|み}る。
4. `netstat -ltnp` で、{実際|じっさい}の{待|ま}ち{受|う}けを{見|み}る。
5. {新|あたら}しい SSH セッションを{開|ひら}いて{検証|けんしょう}し、{確認|かくにん}してから Telnet を{閉|と}じる。

今回の{問題|もんだい}を{修正|しゅうせい}したあと、{安定|あんてい}した{入口|いりぐち}は1つだけ{残|のこ}しました。

```bash
ssh -p <new-port> <admin-user>@<nas-host>
```

{推測|すいそく}を{減|へ}らし、{最終|さいしゅう}{状態|じょうたい}をよく{見|み}ること。NAS のような半分 appliance、半分 Linux のシステムでは、フロントエンド{状態|じょうたい}と{下層|かそう}{設定|せってい}が{同時|どうじ}に{存在|そんざい}します。{両者|りょうしゃ}が{一致|いっち}しないとき、{実際|じっさい}の{動作|どうさ}は{起動|きどう}されたプロセスだけに{従|したが}います。
