トンネル経由でウェブサイトを公開することと、ユーザーにVPNアクセスを与えることは、同じケーブルを共有する二つの別の取り決めである。前者では、公開リバースプロキシが訪問者の要求を受け取り、トンネルを越えて、誰も直接到達できないオリジンへ転送する。後者では、アプリケーションがそもそも到達可能になる前に、ユーザーがVPNに参加しなければならない。この二つの説明を混同することが、プライベートなバックエンドが最終的に公開されてしまう道である。

図の上では似て見える二つのモデル

何かを選ぶ前に矢印を描け。公開モデルはブラウザからプロキシへHTTPSで進み、次にプロキシからオリジンへトンネルを越えて進み、オリジンはインターネットからの接続を決して受け付けない。VPN専用モデルはクライアントからゲートウェイへ進み、アプリケーションはその経路の内側からしか到達できない。ユーザーのノートPCはアプリケーションと同じネットワーク上にあり、それがこのモデルの要点のすべてである。

両モデルは、誰が認証するか、どこで認証するかが異なる。前者ではプロキシが公開の入口であり、そこに設定されたポリシーに従って、到着したあらゆる要求を、敵対的なものも含めて中継する。後者では到達可能性そのものが関門であり、これは粗いが実際の受け入れである。

TLSが止まる場所と、それが実際に何を証明するか

ブラウザとプロキシの間のTLSはその区間を保護し、ブラウザが訪問しようとしたサイトを検証できるようにする。プロキシがTLSを終端すると、要求は転送される前にそのプロセス内部で読める形で存在する。オリジンへの二つ目のTLSセッションは次の区間を保護し、アプリケーションのエンドポイントを別途検証できる。どちらのセッションも、どの人間がアプリケーションを使えるかを決めない。プロキシ上のワイルドカード証明書も、その二つ目の区間には及ばない。

これが人々が暗号化という言葉に押し込めてしまう部分である。機密性、完全性、サーバーの身元はトランスポートの性質であり、認可はアプリケーションの判断である。トンネルの向こうのプライベートアドレスは、誰がソケットに到達できるかを変えるのであって、到達した後に誰がログインできるかではない。

転送されたヘッダーはプロキシからのみ信頼せよ

クライアントのアドレスで記録や認可を行うアプリケーションは、通常、プロキシが追加するヘッダーを読む。そのヘッダーはただのテキストなので、オリジンに直接到達できるものは何でも、好きなアドレスを主張できる。オリジンを制限してプロキシのトンネルアドレスだけが接続できるようにし、アプリケーションがそのアドレスからのヘッダーだけを受け入れるよう設定せよ。

curl -s -o /dev/null -w '%{http_code}
' -H 'X-Forwarded-For: 203.0.113.9' http://172.20.5.40/

その要求がプロキシではないホストから成功するなら、オリジンは無視すべきヘッダーを信頼している。アプリケーションに触れる前にリスナーを直せ。拒否は、偽のアドレスを運ぶログ行よりはるかに良い結果である。

オリジンはちょうど一か所から到達可能に保て

オリジンのリスナーをトンネルアドレスにバインドするか、プロキシへ向けたファイアウォールで囲い、その後、実際に何が待ち受けているかを確認せよ。ワイルドカードバインドで起動したサービスは、ルーティング可能だと忘れていたものも含め、ホストが持つすべてのインターフェースで接続を受け入れる。 待ち受けテーブルこそが基本の真実であり、適用しようとしていた設定ファイルではない。ワイルドカードバインドが意図的なものなら、それを狭める部品はやはりファイアウォールでなければならない。

ss -ltnp | grep -E ':(80|443)'

管理インターフェースは偶発的な露出の常連なので、同じ見直しを行え。次に二つのモデルを別々に書き留めよ。プロキシ経由の公開サイトと、トンネル経由でしか到達できない管理インターフェースである。サーバーはVPNの背後にあるという一文は、そのどれも語っていない。

関連記事