---
title: リバースプロキシとロードバランシング
url: https://doc.liz6.com/ja/networking/06-HTTP/04-reverse-proxy-and-load-balancing
locale: ja
area: networking
tags:
- networking
- HTTP
date: 2026-06-30
modified: 2026-07-16
description: リバースプロキシは単なる「リクエストの転送」ではありません——TLS 終端、キャッシュ、圧縮、レートリミット、ヘルスチェック、ブルーグリーンデプロイメントなど、現代アーキテクチャにおけるトラフィック管理はすべてこのレイヤーに集約されています。nginx/Caddy/HAProxy の設定哲学はそれぞれ異なります。
---

# リバースプロキシとロードバランシング

> リバースプロキシは単なる「リクエストの転送」ではありません——TLS 終端、キャッシュ、圧縮、レートリミット、ヘルスチェック、ブルーグリーンデプロイメントなど、現代アーキテクチャにおけるトラフィック管理はすべてこのレイヤーに集約されています。nginx/Caddy/HAProxy の設定哲学はそれぞれ異なります。

## 概要

リバースプロキシはサーバー側のフロントエンドです。すべての外部リクエストを受信し、TLS 終端、SNI ルーティング、レートリミット、ログ記録を行い、リクエストをバックエンドサービスに転送します。ロードバランサは、ポリシー（ラウンドロビン/最少接続/IP ハッシュなど）に基づいてリクエストを複数のバックエンドインスタンスに分散し、可用性とスループットを向上させます。Caddy は自動 TLS（ACME + Let's Encrypt のゼロコンフィグ）で知られ、nginx/HAProxy は高性能と豊富な L4/L7 機能でエンタープライズ環境を牽引しています。リバースプロキシを理解することは、インターネットサービスをデプロイする前提条件です。

## リバースプロキシとフォワードプロキシ

<svg viewBox="0 0 720 320" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Source Han Sans CN','Microsoft YaHei',sans-serif" role="img" aria-label="フォワードプロキシとリバースプロキシのリクエストフロー比較">
  <defs><marker id="rpah" markerWidth="10" markerHeight="8" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#475569"/></marker></defs>
  <rect width="720" height="320" fill="#ffffff"/>
  <text x="360" y="28" text-anchor="middle" font-size="17" font-weight="700" fill="#1f2933">フォワードプロキシ vs リバースプロキシ: 誰が誰を代理するか</text>

  <text x="40" y="54" font-size="13" font-weight="700" fill="#334155">フォワードプロキシ</text>
  <rect x="40" y="62" width="80" height="34" rx="6" fill="#e2e8f0"/>
  <text x="80" y="83" text-anchor="middle" font-size="12" fill="#334155">Client</text>
  <line x1="120" y1="79" x2="156" y2="79" stroke="#475569" stroke-width="1.6" marker-end="url(#rpah)"/>
  <rect x="160" y="62" width="80" height="34" rx="6" fill="#cbd5e1"/>
  <text x="200" y="83" text-anchor="middle" font-size="12" fill="#334155">Proxy</text>
  <line x1="240" y1="79" x2="276" y2="79" stroke="#475569" stroke-width="1.6" marker-end="url(#rpah)"/>
  <rect x="280" y="62" width="90" height="34" rx="6" fill="#e2e8f0"/>
  <text x="325" y="83" text-anchor="middle" font-size="12" fill="#334155">Target</text>
  <text x="40" y="114" font-size="11" fill="#64748b">例: 本体の mihomo :7890 → ブラウザのトラフィックを国外へプロキシ</text>

  <line x1="40" y1="130" x2="680" y2="130" stroke="#e2e8f0" stroke-width="1"/>

  <text x="40" y="150" font-size="13" font-weight="700" fill="#0f766e">リバースプロキシ</text>
  <rect x="40" y="160" width="70" height="36" rx="6" fill="#ccfbf1"/>
  <text x="75" y="182" text-anchor="middle" font-size="11" fill="#115e59">Client</text>
  <line x1="110" y1="178" x2="146" y2="178" stroke="#475569" stroke-width="1.6" marker-end="url(#rpah)"/>
  <rect x="150" y="160" width="170" height="36" rx="6" fill="#f0fdfa" stroke="#99f6e4" stroke-dasharray="4 3"/>
  <text x="235" y="175" text-anchor="middle" font-size="11" fill="#0f766e">grafana.liz6.com</text>
  <text x="235" y="190" text-anchor="middle" font-size="9.5" fill="#0f766e">(Target のように見える)</text>
  <line x1="320" y1="178" x2="356" y2="178" stroke="#475569" stroke-width="1.6" marker-end="url(#rpah)"/>
  <text x="338" y="170" text-anchor="middle" font-size="9.5" fill="#64748b">実は</text>
  <rect x="360" y="160" width="110" height="36" rx="6" fill="#0d9488"/>
  <text x="415" y="175" text-anchor="middle" font-size="11" font-weight="600" fill="#ffffff">Caddy:443</text>
  <text x="415" y="190" text-anchor="middle" font-size="9.5" fill="#ffffff">(Proxy)</text>
  <line x1="470" y1="178" x2="506" y2="178" stroke="#475569" stroke-width="1.6" marker-end="url(#rpah)"/>
  <rect x="510" y="160" width="140" height="36" rx="6" fill="#ccfbf1" stroke="#99f6e4"/>
  <text x="580" y="175" text-anchor="middle" font-size="11" fill="#115e59">127.0.0.1:3000</text>
  <text x="580" y="190" text-anchor="middle" font-size="9.5" fill="#115e59">(Backend)</text>
  <text x="40" y="214" font-size="11" fill="#64748b">Client は自分が Grafana に直接接続していると思い込んでおり、それが localhost 上にあることを知らない</text>

  <rect x="40" y="236" width="640" height="56" rx="8" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="56" y="258" font-size="12.5" fill="#115e59">フォワードプロキシは Client を助けて外部ネットワークにアクセスし、Target に対して Client を隠します。一方、リバースプロキシはその逆で、</text>
  <text x="56" y="278" font-size="12.5" fill="#115e59">Client に対して Target 自体であるかのように振る舞い、真の Backend を背後に隠します。</text>
</svg>

## Caddy 設定

```caddy
grafana.liz6.com {
    reverse_proxy 127.0.0.1:3000 {
        header_up Host {upstream_hostport}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }
}

chat.liz6.com {
    reverse_proxy 127.0.0.1:3001
}
```

リバースプロキシの役割:
1. **TLS Termination**: Caddy が TLS を処理 → バックエンドは HTTP → バックエンドは TLS を処理する必要がない
2. **SNI Routing**: 同一ポート (443) で SNI に基づき異なるバックエンドへルーティング
3. **Request rewriting**: `X-Forwarded-*` ヘッダーの追加、パス/ヘッダーの変更
4. **Rate Limiting**: クライアントごとまたはエンドポイントごとのレートリミット
5. **Access Log**: ログの一元化 (Caddy JSON アクセスログ)

## L4 と L7 ロードバランシング

<svg viewBox="0 0 720 360" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Source Han Sans CN','Microsoft YaHei',sans-serif" role="img" aria-label="L4 と L7 ロードバランシングの原理比較">
  <rect width="720" height="360" fill="#ffffff"/>
  <text x="360" y="28" text-anchor="middle" font-size="17" font-weight="700" fill="#1f2933">L4 vs L7: HTTP を解析するかどうかで、ルーティング能力と速度が決まる</text>

  <rect x="40" y="44" width="310" height="26" rx="6" fill="#94a3b8"/>
  <text x="195" y="61" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">L4 · TCP(HTTP を解析しない)</text>
  <rect x="40" y="80" width="310" height="40" rx="6" fill="#f1f5f9" stroke="#e2e8f0"/>
  <text x="52" y="104" font-size="10.5" fill="#475569">nginx stream モジュール / HAProxy mode tcp</text>
  <rect x="40" y="130" width="310" height="56" rx="6" fill="#f1f5f9" stroke="#e2e8f0"/>
  <text x="52" y="152" font-size="11" font-weight="600" fill="#334155">HTTP を解析しない → TCP ペイロードのみを参照 → ただし非常に高速</text>
  <text x="52" y="172" font-size="10.5" fill="#64748b">URL や Host ヘッダーに基づくルーティングは不可</text>
  <rect x="40" y="196" width="310" height="48" rx="6" fill="#dcfce7" stroke="#4ade80"/>
  <text x="52" y="216" font-size="11" font-weight="700" fill="#166534">利点: 非常に高速</text>
  <text x="52" y="234" font-size="10.5" fill="#15803d">生 TCP 転送や WebSocket パススルーに適している</text>

  <rect x="370" y="44" width="310" height="26" rx="6" fill="#4f46e5"/>
  <text x="525" y="61" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">L7 · HTTP(HTTP を解析し、コンテンツに基づいてルーティング)</text>
  <rect x="370" y="80" width="310" height="40" rx="6" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="382" y="104" font-size="10.5" fill="#3730a3">nginx http モジュール / HAProxy mode http / Caddy</text>
  <rect x="370" y="130" width="310" height="72" rx="6" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="382" y="148" font-size="10.5" font-weight="600" fill="#3730a3">HTTP を解析 → Host / URL /</text>
  <text x="382" y="164" font-size="10.5" font-weight="600" fill="#3730a3">ヘッダー / Cookie / Method に基づいてルーティング可能</text>
  <text x="382" y="182" font-size="10" fill="#4338ca">コンテンツベースのレートリミットやリクエスト検証も可能</text>
  <rect x="370" y="212" width="310" height="48" rx="6" fill="#ffedd5" stroke="#f97316"/>
  <text x="382" y="232" font-size="11" font-weight="700" fill="#9a3412">代償: やや低速</text>
  <text x="382" y="250" font-size="10.5" fill="#c2410c">HTTP パースのオーバーヘッド</text>

  <rect x="40" y="282" width="640" height="56" rx="8" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="56" y="304" font-size="12.5" fill="#3730a3">L4 と L7 のどちらを選ぶかは、コンテンツベースのルーティングが必要かどうかによる: 純粋な転送や WebSocket パススルーには速度を優先して L4 を使用し、</text>
  <text x="56" y="324" font-size="12.5" fill="#3730a3">Host / Path / ヘッダーに基づく分散やコンテンツレベルのレートリミットを行うには、L7 を使用する必要がある。</text>
</svg>

## ロードバランシングアルゴリズム

```
ラウンドロビン:        バックエンドを順に巡回
最少接続:            接続数が最も少ないバックエンドを選択 (L7 のみ有効)
ランダム:              ランダム
IP ハッシュ:           同一クライアント IP → 同一バックエンド → スティッキー
一貫性ハッシュ:        ハッシュリング → バックエンドの増減時に 1/N だけが再ハッシュ
重み付け:              バックエンドの重み → weight=3 なら 3 倍のトラフィック

ヘルスチェック:
  パッシブ: 実際のリクエストの失敗から検出 (max_fails=N)
  アクティブ: 定期的に GET /health → 200 を期待 → 失敗時に down とマーク
  slow_start: バックエンド回復後、トラフィックを段階的に増加 (フラッディングを回避)
```

## 参考

- **Caddy**: caddyserver.com/docs/caddyfile/directives/reverse_proxy
- **nginx**: nginx.org/en/docs/http/ngx_http_upstream_module.html
- **HAProxy**: haproxy.org

*Keywords: reverse proxy, SNI routing, L4/L7 LB, health check, sticky session, rate limiting, Caddy*
