あるマシンが VPN 経由で別のマシンに到達しており、今度はプロバイダーのプライベートネットワーク上で同じシェルを使いたいと考えています。ルートは存在し、ping は成功するのに、SSH は依然として拒否します。よくある原因は、デーモンが新しいアドレスで一度も待ち受けていなかったことであり、接続先が存在しないのです。これはファイアウォールの問題になる前に、アドレスバインドの問題です。

新しいルートが新しいリスナーを作らない理由

待ち受けソケットは、受け入れるアドレスを指定したプロセスによって作成されます。ルートはパケットの行き先を伝えるだけで、宛先にリスナーを作るわけではありません。sshd が単一の ListenAddress で構成されている場合、インターフェースが稼働していても、他のローカルアドレスへの接続は拒否されます。ポートを所有するソケットユニットについても同じで、だからこそ最初の確認は常に「実際に何が待ち受けているか」です。

二つの経路は、インターフェース名ではなく宛先アドレスで比較してください。クライアントはアドレスに接続するのであり、ファイアウォール規則が意味を持つ前に、そのアドレスがバインドされている必要があります。

アドレスとリスナーを一覧表示する

何かを編集する前に、ホスト上のアドレスと現在存在するソケットを記録します。

ip -br addr
ss -ltnp | grep ':22'

アドレス一覧は、どのプライベートアドレスが実在し、どのインターフェースにあるかを示し、ソケット一覧は何かがそれにバインドされているかどうかを示します。0.0.0.0:22 で待ち受けるリスナーはすでにすべてのアドレスを受け入れるため、新しいバインドを追加しても何も変わりません。特定の一つのアドレスで待ち受けるリスナーは、拒否の理由をすぐに説明します。ポートがデーモンではなくソケットユニットに属している場合、デーモンの構成だけでは話が済みません。

バインドを追加し、古いものを残す

OpenSSH は複数の ListenAddress エントリを受け付けるため、プライベート経路を追加しても VPN 経路を残せます。再読み込みの前にファイルをテストしてください。

sshd -t
systemctl reload sshd

構成テストが失敗しても実行中のデーモンはそのまま残り、編集している経路経由で接続しているときにはまさにそれが望ましい動作です。既存のエントリを残したまま新しいローカルアドレスを追加し、現在のセッションを切断せずにサービスが再読み込みされることを確認します。ソケット起動型のインストールでは、代わりにソケットユニットへアドレスを追加し、そのユニットを再読み込みします。その後リスナー一覧をもう一度読み、バインドが現れなかったなら間違ったコンポーネントを編集したということです。

古いセッションを閉じる前に新しいセッションを検証する

元のセッションを開いたまま新しいアドレスに接続し、詳細出力でどのアドレスと鍵が使われたかを確認します。プローブが二回成功するまで、元のセッションは開いたままにしてください。

ssh -v [email protected]

宛先アドレスと提示されたホスト鍵についてのデバッグ行を読みます。ホスト鍵のフィンガープリントは、ネットワークがプライベートだと説明されているからといって未知の鍵を受け入れるのではなく、すでに信頼している値と照合して確認してください。新しい宛先には独自の known_hosts エントリが必要で、それは想定どおりです。古い管理セッションは、プライベート経路が機能してから初めて閉じるべきです。

SSH は転送を保護しますが、それだけで二つのネットワークが同等になるわけではありません。プライベートな中継の信頼がデータに見合うかを、依存する前に判断してください。

関連記事