

SSHの-Lで`localhost`と`127.0.0.1`を書き分ける意味、実はほぼない
この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。
macからSSHでリモートのポートを転送してブラウザで見る、というのはよくやる作業だけど、毎回微妙に迷うポイントがいくつかあるので整理した。
おさらい:基本の書き方
ローカル8080 → リモート3000に転送する場合。
ssh -L 8080:localhost:3000 user@server.example.comSSH自体が22番以外のポートで動いてる場合は-pを足す。
ssh -p 2222 -L 8080:localhost:3000 user@server.example.com逆方向(ローカルのサービスをリモート側から見る)なら-R。
ssh -R 8080:localhost:3000 user@server.example.comここまでは普通に使ってれば覚える。
localhostと127.0.0.1、どっちを書くべきか
-L 8080:localhost:3000のlocalhost部分、これは「SSH接続先のサーバから見た接続先ホスト」を指定してる。ここを127.0.0.1にすべきという情報をたまに見るけど、実際にはサーバ上でこの2つはほぼ同じ意味(ループバックアドレス)になるので、書き分けても動作は変わらない。
差が出るとしたら、サーバ側の名前解決がIPv6の::1を優先していて、かつ転送先のアプリがIPv4の127.0.0.1でしかリッスンしていない、みたいな特殊なケースくらい。普通の環境ならlocalhostのままで問題ない。
転送してもブラウザが真っ白になるとき
原因は主に2パターンあって、切り分けが必要。
パターン1:アプリのリッスンアドレスの問題
転送先のアプリがDockerコンテナ内などで動いていて、コンテナ内部のアドレスでしかリッスンしていない場合。0.0.0.0でリッスンしてないと、SSH側からは繋がらない。
パターン2:フォワード自体が拒否されている
こっちはchannel 2: open failedみたいなエラーが出るパターン。サーバ側の/etc/ssh/sshd_configで
AllowTcpForwarding noになっていると、そもそもポートフォワード自体が拒否される。これは「アプリがどこでリッスンしてるか」とは全く別のレイヤーの話なので、真っ白になった原因を探すときは分けて考えたほうがいい。
HTTPSのポートを転送したとき
リモートの443を8443とかに転送してhttps://localhost:8443で見ると、証明書のCN/SANはサーバの本来のドメイン名(server.example.comとか)で発行されているせいで、ブラウザ側でホスト名不一致の警告が出る。
動作自体は問題ないので、警告を無視して進めば普通に繋がる。ただし初見だと「壊れてる?」と焦るので、先に知っておくと落ち着ける。
まとめると
localhostと127.0.0.1はサーバ上でほぼ同じ、書き分ける必要は基本ない- 真っ白になったら「アプリのリッスンアドレス」か「
AllowTcpForwardingの設定」かを分けて疑う - HTTPS転送時の証明書警告は仕様なので気にしなくていい