#はじめに

「Webサーバーの前に別のサーバーを置く」——一見すると無駄に思えますが、これがリバースプロキシです。

リバースプロキシは、クライアントとWebサーバーの間に位置し、リクエストを中継するサーバーです。セキュリティ、パフォーマンス、柔軟性を向上させる重要なインフラストラクチャコンポーネントです。

この記事を読むと、以下のことができるようになります:

  • リバースプロキシの役割を理解できる
  • フォワードプロキシとの違いがわかる
  • 基本的なnginx設定ができる

#リバースプロキシとは

リバースプロキシとは、クライアントからのリクエストを受け取り、バックエンドサーバーに転送するサーバーです。

[クライアント] → [リバースプロキシ] → [Webサーバー]

                クライアントからは
                1台のサーバーに見える

クライアントはリバースプロキシとだけ通信し、背後にあるサーバーの存在を意識しません。

#フォワードプロキシとの違い

フォワードプロキシリバースプロキシ
位置クライアント側サーバー側
保護対象クライアントサーバー
用途アクセス制御、匿名化負荷分散、セキュリティ
設定者クライアントサーバー管理者
フォワードプロキシ:
[クライアント] → [プロキシ] → [インターネット] → [サーバー]

              クライアントを隠す

リバースプロキシ:
[クライアント] → [インターネット] → [プロキシ] → [サーバー]

                                  サーバーを隠す

#リバースプロキシの役割

#1. 負荷分散(ロードバランシング)

複数のバックエンドサーバーにリクエストを分散します。

                         ┌→ [サーバー1]
[クライアント] → [プロキシ] ─→ [サーバー2]
                         └→ [サーバー3]

#2. SSLターミネーション

HTTPS接続をプロキシで終端し、バックエンドにはHTTPで転送します。

[クライアント] ──HTTPS──> [プロキシ] ──HTTP──> [バックエンド]

                      SSL証明書を管理

メリット:

  • バックエンドサーバーの負荷軽減
  • 証明書管理の一元化

#3. キャッシュ

静的コンテンツをプロキシでキャッシュし、バックエンドへのリクエストを削減します。

1回目: [プロキシ] → [バックエンド]

          キャッシュ保存

2回目: [プロキシ] → キャッシュから返却(バックエンドに行かない)

#4. セキュリティ

バックエンドサーバーを外部から隠蔽し、攻撃対象を限定します。

  • バックエンドのIPアドレスを隠す
  • WAF(Web Application Firewall)機能
  • DDoS対策
  • リクエストのフィルタリング

#5. 圧縮

レスポンスをgzip/Brotliで圧縮します。

#6. URLの書き換え

リクエストURLを変換してバックエンドに転送します。

/api/v1/users → バックエンド: /users
/static/*     → 静的ファイルサーバー

#nginxによる設定例

#基本設定

# /etc/nginx/nginx.conf

http {
    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

#重要なヘッダー

ヘッダー用途
Host元のホスト名を伝える
X-Real-IPクライアントの実IPアドレス
X-Forwarded-Forプロキシチェーン全体のIPアドレス
X-Forwarded-Proto元のプロトコル(http/https)

#SSL設定

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:3000;
        # ヘッダー設定...
    }
}

# HTTPからHTTPSへリダイレクト
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

#静的ファイルの配信

server {
    listen 80;
    server_name example.com;

    # 静的ファイルはnginxが直接配信
    location /static/ {
        root /var/www;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # APIリクエストはバックエンドに転送
    location /api/ {
        proxy_pass http://localhost:3000;
    }
}

#負荷分散

upstream backend {
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}

server {
    listen 80;

    location / {
        proxy_pass http://backend;
    }
}

#キャッシュ設定

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g;

server {
    listen 80;

    location / {
        proxy_cache my_cache;
        proxy_cache_valid 200 1h;
        proxy_cache_valid 404 1m;
        proxy_pass http://localhost:3000;

        add_header X-Cache-Status $upstream_cache_status;
    }
}

#その他のリバースプロキシ

#Caddy

自動HTTPS、シンプルな設定が特徴です。

# Caddyfile
example.com {
    reverse_proxy localhost:3000
}

#Traefik

コンテナ環境向け、動的設定が得意です。

# docker-compose.yml
services:
  traefik:
    image: traefik:v2.9
    command:
      - "--providers.docker=true"
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  app:
    image: myapp
    labels:
      - "traefik.http.routers.app.rule=Host(`example.com`)"

#HAProxy

高性能な負荷分散が特徴です。

# haproxy.cfg
frontend http_front
    bind *:80
    default_backend servers

backend servers
    balance roundrobin
    server server1 192.168.1.10:3000 check
    server server2 192.168.1.11:3000 check

#クラウドサービスのリバースプロキシ

#AWS ALB(Application Load Balancer)

[クライアント] → [ALB] → [EC2/ECS/Lambda]
  • パスベースルーティング
  • ホストベースルーティング
  • SSL終端

#Cloudflare

[クライアント] → [Cloudflare] → [オリジン]
  • CDN機能
  • DDoS対策
  • WAF

#トラブルシューティング

#X-Forwarded-Forの信頼性

プロキシが複数ある場合、X-Forwarded-Forは以下のような形式になります。

X-Forwarded-For: クライアントIP, プロキシ1, プロキシ2

最初の値が必ずしも信頼できるとは限りません(クライアントが偽装可能)。

# 信頼できるプロキシを指定
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

#WebSocket対応

location /ws/ {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

#タイムアウト設定

location / {
    proxy_pass http://localhost:3000;
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
}

#まとめ

  • リバースプロキシはクライアントとサーバーの間に位置するサーバー
  • 主な役割: 負荷分散、SSLターミネーション、キャッシュ、セキュリティ
  • nginx: 最も広く使われるリバースプロキシ
  • 重要なヘッダー: X-Forwarded-ForX-Real-IPX-Forwarded-Proto
  • クラウドサービス: ALB、Cloudflareなども同様の機能を提供

#次のステップ

リバースプロキシの基本を理解したところで、次はロードバランサーについてより詳しく学びましょう。複数サーバーへのリクエスト分散方式やヘルスチェックの仕組みを紹介します。

#参考リンク