TL;DR
リモートのHTTPSサーバーにSSHポートフォワードしてアクセスする時にSSL証明書エラーが出た。ローカルの/etc/hostsでリモートホスト名を127.0.0.1に紐付けると回避できたよ。
シュチュエーション
パンデミックもありリモートでの仕事が増えているものの、
まだまだリモート環境が前提でない社内システムにアクセスすることがあるかと思います。例えば今回遭遇したサーバーの条件としては以下のような感じでした。
- sshログインができる
- 社外向けのwebページ(ip制限はなし。basic認証あり)
- 社内向けのwebページ(イントラからのみアクセスできるようにip制限をしている)
- グローバルIP及びドメイン名は取得済み
今回問題となったのは3番目の「社内向けwebページ」へのアクセスです。
登場人物と条件
- ローカルマシン
- リモートサーバー
リモートサーバのホスト名はremote_host、ipはaaa.bbb.ccc.dddであるとします。また、社内向けwebページへのリモートサーバ自身(aaa.bbb.ccc.ddd)からのアクセスは許可されているとします。
自宅の環境でグローバルIPを持っている人はリモートサーバのip制限を書き換えてアクセス可能にすることが出来るでしょう。しかし僕はそのためだけに固定IPを取りたくはありませんでした。
発生したこと
そこで、sshポートフォワードを使ってHTTPSサーバにアクセスしようと考えました。以下のコマンドで出来るだろうと試してみました。
ssh -L 8080:remote_host:443 remote_user@remote_host
これで以下のようにlocalhost:8080にremote_host:443が紐づいていたので、
https://localhost:8080 にアクセスすれば社内サーバが見られるはずです。
127.0.0.1:8080 -> remote_host:443
が、残念なことに証明書エラーが出てしまいました。
原因
ブラウザからのメッセージを読んでみると
「localhostでは、悪意のあるユーザーによって、パスワード、メッセージ、クレジット カードなどの情報が盗まれる可能性があります。」
とのことですので、localhostは信用できないでのアクセスできません、と言われているようです。
なぜ信用できないと言われるかを考えてみます。
そもそもSSL証明書は「アクセスしたサーバが改ざんされていないこと」を証明するものです。そのため、通常はAというサーバにアクセスした時に、
証明書を見せてもらい「Aさんと名乗っている人がAさんであること」を確認することになります。
つまり、今回の状況は
「localhostさんをお願いします」
と言ったら、
「私はremote_serverというものです。認証局さんの保証付きです」
と返事が来たようなものだと理解しています。それは、なんというか普通にダメな感じがします。
対応
アクセスしたいのはremote_serverなので、
お願いする時にちゃんとremote_serverさんを指名すれば良いはずです。
しかし普通にremote_serverにアクセスするとDNSで名前解決がおこなわれてしまい、本当にremote_server(aaa.bbb.ccc.ddd)にアクセス要求してしまいます。
そして、アクセス先のサーバーではip制限がかかっているので実際にはアクセスは成功しません。
では今回どうしたかというと、
ローカル側で"remote_server"という名前をローカルマシンの127.0.0.1(localhost)に紐付けることで解決しました。どういう流れになるかというと
"remote_server":8080 -> 127.0.0.1:8080 -> remote_server:443
これでremote_serverさんをお願いして、remote_serverさんから返事がくることになります。remote_serverを127.0.0.1に結びつけるにはローカルマシンの/etc/hosts(macなら/private/etc/hosts)に以下を追記することで出来ます。
remote_server 127.0.0.1
最後に
今回はこの方法で対応したものの、
他の良いやり方があれば是非コメントで教えてください!