リバースプロキシ
サーバの前段に立ち、リクエストを受けて後ろへ中継する仲介サーバ。
概要
リバースプロキシは、クライアントとアプリケーションサーバの間に立つ中継役です。外から届くHTTPリクエストをいったんすべて受け取り、必要な前処理をしてから後ろのサーバへ転送し、返ってきたレスポンスをクライアントへ返します。クライアントから見える相手はリバースプロキシだけで、その背後に何台のサーバがどんな構成で並んでいるかは見えません。
「プロキシ(代理)」には向きが2つあります。クライアント側に立って外への通信を代理するのがフォワードプロキシ(社内ネットワークの出口によくいるもの)、サーバ側に立って受信を代理するのがリバースプロキシです。「サーバの代理人として玄関に立つ」のがリバース、と覚えると混乱しません。
代表的な実装はnginxで、ほかにApache HTTP Server、HAProxy、Caddy、クラウド時代のEnvoyなどがあります。Webアプリの本番構成で「アプリの前に何も置かない」ことはまれで、ほとんどのサービスの玄関には何らかのリバースプロキシが立っています。
なぜ生まれたか
Webサービスを運営すると、どのアプリケーションにも共通して必要な仕事が積み上がります。TLSの暗号化処理、静的ファイルの配信、大量接続の受け付け、アクセス制御、ログの記録……。これらをアプリケーション本体(RailsやNode.jsなど、ビジネスロジックを書くためのプログラム)に全部やらせると、実装が重複するうえ、アプリのプロセスは大量の同時接続を捌くのが不得意なため、性能もセキュリティも中途半端になりがちでした。
そこで「共通の玄関仕事は、それ専用に鍛えられたサーバに一手に引き受けさせ、アプリはビジネスロジックに専念する」という役割分担が定着しました。特にnginxは、1万同時接続問題(C10K問題)を解決するために設計されたイベント駆動アーキテクチャで、遅いクライアントとの接続を大量に安く保持できます。「接続の相手はnginxが引き受け、アプリには整った形で渡す」——この緩衝材としての価値が、リバースプロキシを標準構成に押し上げました。
詳細
基本の流れ
リバースプロキシの動きは素直です。クライアントとのTLS接続を終端し、リクエストを検査・加工して、内部ネットワークのアプリケーションサーバへ転送します。
このとき内部への転送は別の接続として張り直されるため、アプリから見た接続元はプロキシになります。本来のクライアントのIPアドレスや元のプロトコルを伝えるために、X-Forwarded-For / X-Forwarded-Protoといったヘッダを付けて転送するのが慣習です。この設定を忘れると「アクセスログが全部プロキシのIPになる」「HTTPSで来たのにアプリがHTTPと誤認してリダイレクトループする」という定番のトラブルになります。
引き受ける共通処理
リバースプロキシの価値は、玄関に集約できる仕事の多さにあります。まずTLS終端——証明書の設定・更新をプロキシ1か所で管理し、後ろのアプリは平文HTTPで受けられます。次に静的ファイル配信——画像やJS/CSSはアプリを経由せずプロキシが直接返すほうが桁違いに速く済みます。さらにキャッシュとしてアプリの応答を保存して再利用でき、gzip等の圧縮、リクエストサイズの制限やレート制限、IPによるアクセス制御、認証の前置き(認証プロキシ)まで担えます。攻撃的なリクエストを検査して弾くWAFも、この位置に置かれる防御です。内部のサーバ構成を隠せること自体もセキュリティ上の利点です。
ルーティングとロードバランサとの関係
もうひとつの重要機能がルーティングです。URLのパスやHostヘッダを見て「/apiはAPIサーバへ、/はフロントエンドへ」と転送先を切り替えられるため、複数のアプリケーションを1つのドメインの下にまとめられます。
1台のサーバで複数サイトを収容するバーチャルホストも同じ仕組みです。そして転送先が複数台あれば、そこへ振り分けること——つまり負荷分散——も自然にこの位置の仕事になります。実際、ロードバランサとの境界は実務ではかなり曖昧で、L7ロードバランサとリバースプロキシは概ね同じものを別の側面から呼んだ名前です。「中継・前処理に注目すればリバースプロキシ、複数台への分散に注目すればロードバランサ」と整理しておけば十分です。
現代の構成での位置づけ
この「前段で受けて共通処理をして転送する」パターンは、形を変えながら現代のインフラ全体に浸透しています。CDNは世界規模に分散した巨大なリバースプロキシと見なせますし、KubernetesのIngressはクラスタの入口に立つリバースプロキシの設定抽象です。マイクロサービスの世界では、外向きの玄関をAPIゲートウェイ、サービス間通信に挟む小さなプロキシ群をサービスメッシュ(Envoyが代表)と呼びますが、いずれも本質はリバースプロキシです。開発環境でフロントエンドの開発サーバがAPIリクエストをバックエンドに中継する「devサーバのproxy設定」も同じ原理で、CORSを回避する手段としてよく使われます。ひとつの語彙で、インフラの広い範囲が読めるようになる——リバースプロキシはそういう基礎語彙です。