リバースプロキシとは?Nginx・Caddyでの設定方法と活用パターン

kento_morota 17分で読めます

「Nginxでリバースプロキシを設定する」——Web開発の現場ではよく聞くフレーズですが、リバースプロキシが具体的にどのような役割を果たしているのか、正確に説明できるでしょうか。

本記事では、リバースプロキシの基本概念から、NginxとCaddyでの実践的な設定方法、セキュリティやパフォーマンスを向上させる活用パターンまで、体系的に解説します。

リバースプロキシとは何か

リバースプロキシは、クライアント(ブラウザ)とバックエンドサーバーの間に位置し、クライアントからのリクエストを受け取って適切なバックエンドサーバーに転送する中間サーバーです。

クライアントはリバースプロキシとのみ通信し、バックエンドサーバーの存在を意識しません。外部から見ると、リバースプロキシが最終的なサーバーに見えます。

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

「プロキシ」と聞くと、社内ネットワークからインターネットへのアクセスを中継する「フォワードプロキシ」を想像する方も多いでしょう。両者は目的と配置場所が異なります。

フォワードプロキシ

・クライアント側に配置される
・クライアントの代理としてインターネット上のサーバーにアクセスする
・クライアントの身元を隠す、アクセス制御を行う
・社内ネットワークのWebフィルタリングなどで使用される

// フォワードプロキシの通信フロー
クライアント → フォワードプロキシ → インターネット上のサーバー
(クライアントがプロキシの存在を知っている)

リバースプロキシ

・サーバー側に配置される
・サーバーの代理としてクライアントからのリクエストを受け付ける
・バックエンドサーバーの存在を隠す、負荷分散・セキュリティ向上を行う
・WebサーバーやAPIゲートウェイとして使用される

// リバースプロキシの通信フロー
クライアント → リバースプロキシ → バックエンドサーバー群
(クライアントはバックエンドの存在を知らない)

リバースプロキシの主な役割

SSL/TLS終端(SSLオフロード)
HTTPS通信の暗号化・復号処理をリバースプロキシが担当します。バックエンドサーバーはHTTPで通信するだけでよく、SSL証明書の管理も一元化できます。

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

静的コンテンツの配信
画像、CSS、JavaScriptなどの静的ファイルをリバースプロキシが直接配信します。バックエンドサーバーの負荷を軽減できます。

キャッシュ
バックエンドの応答をキャッシュし、同じリクエストに対してはキャッシュから応答します。レスポンス速度が向上し、バックエンドの負荷が大幅に軽減されます。

セキュリティ
バックエンドサーバーのIPアドレスやアーキテクチャを外部から隠蔽します。WAF(Web Application Firewall)機能やレート制限も実装できます。

Nginxでのリバースプロキシ設定

Nginxは、世界で最も広く使われているリバースプロキシ・Webサーバーの一つです。高いパフォーマンスと柔軟な設定が特徴です。

基本的なリバースプロキシ設定

# /etc/nginx/sites-available/app.example.com
server {
    listen 80;
    server_name app.example.com;

    # HTTPSへのリダイレクト
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name app.example.com;

    # SSL設定
    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;

    # リバースプロキシ設定
    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;

        # タイムアウト設定
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # バッファリング設定
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
}

重要なプロキシヘッダーの解説

proxy_set_header Host $host
元のリクエストのHostヘッダーをバックエンドに転送します。バックエンドが仮想ホストで動作している場合に重要です。

proxy_set_header X-Real-IP $remote_addr
クライアントの実際のIPアドレスをバックエンドに伝えます。リバースプロキシを経由すると、バックエンドから見える送信元IPはプロキシのIPになるため、この設定が必要です。

proxy_set_header X-Forwarded-For
リクエストが経由したプロキシのIPアドレスのチェーンを記録します。複数のプロキシを経由する場合に使います。

proxy_set_header X-Forwarded-Proto $scheme
元のリクエストがHTTPかHTTPSかをバックエンドに伝えます。バックエンドでHTTPSリダイレクトを判断する際に必要です。

パスベースのルーティング

# URLパスに応じて異なるバックエンドにルーティング
server {
    listen 443 ssl http2;
    server_name example.com;

    # APIリクエストをバックエンドAPIサーバーに転送
    location /api/ {
        proxy_pass http://localhost:8080/;
        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;
    }

    # WebSocketの接続
    location /ws/ {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
    }

    # 静的ファイルをNginxが直接配信
    location /static/ {
        alias /var/www/app/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # フロントエンド(SPA)
    location / {
        root /var/www/app/dist;
        try_files $uri $uri/ /index.html;
    }
}

キャッシュの設定

# プロキシキャッシュの設定
http {
    # キャッシュゾーンの定義
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:10m
                     max_size=1g inactive=60m use_temp_path=off;

    server {
        location /api/ {
            proxy_pass http://localhost:3000;
            proxy_cache app_cache;

            # GETリクエストのみキャッシュ
            proxy_cache_methods GET HEAD;

            # キャッシュの有効期間
            proxy_cache_valid 200 10m;    # 200レスポンスは10分間キャッシュ
            proxy_cache_valid 404 1m;     # 404レスポンスは1分間キャッシュ

            # キャッシュキーの設定
            proxy_cache_key "$scheme$request_method$host$request_uri";

            # レスポンスヘッダーにキャッシュ状態を追加(デバッグ用)
            add_header X-Cache-Status $upstream_cache_status;

            # キャッシュをバイパスする条件
            proxy_cache_bypass $http_cache_control;
            proxy_no_cache $http_pragma;
        }
    }
}

Caddyでのリバースプロキシ設定

Caddyは、自動HTTPS、シンプルな設定、高いパフォーマンスを特徴とするモダンなWebサーバーです。設定ファイルが直感的で、初心者にも扱いやすいのが魅力です。

基本的なリバースプロキシ設定

# Caddyfile
app.example.com {
    # 自動的にHTTPSが有効化される(Let's Encryptから証明書を取得)
    reverse_proxy localhost:3000
}

# これだけで以下が実現される
# - SSL/TLS証明書の自動取得・更新
# - HTTPからHTTPSへの自動リダイレクト
# - HTTP/2の有効化
# - 適切なプロキシヘッダーの設定

高度な設定例

# Caddyfile - 詳細な設定
app.example.com {
    # パスベースルーティング
    handle /api/* {
        reverse_proxy localhost:8080 {
            # ヘッダーの設定
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-Proto {scheme}

            # ヘルスチェック
            health_uri /health
            health_interval 10s
            health_timeout 5s
            health_status 200

            # 負荷分散(複数バックエンド)
            # to localhost:8080 localhost:8081 localhost:8082
            # lb_policy least_conn
        }
    }

    # WebSocket
    handle /ws/* {
        reverse_proxy localhost:8080
    }

    # 静的ファイル配信
    handle /static/* {
        root * /var/www/app
        file_server {
            precompressed gzip br
        }
        header Cache-Control "public, max-age=2592000, immutable"
    }

    # SPA(フロントエンド)
    handle {
        root * /var/www/app/dist
        try_files {path} /index.html
        file_server
    }

    # セキュリティヘッダー
    header {
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
        -Server  # Serverヘッダーを除去
    }

    # アクセスログ
    log {
        output file /var/log/caddy/access.log
        format json
    }
}

複数サイトのホスティング

# Caddyfile - 複数サイト
app.example.com {
    reverse_proxy localhost:3000
}

api.example.com {
    reverse_proxy localhost:8080
}

admin.example.com {
    # Basic認証
    basicauth {
        admin $2a$14$hashed_password_here
    }
    reverse_proxy localhost:3001
}

# すべてのサイトに自動的にHTTPS証明書が取得される

セキュリティ強化のための設定

リバースプロキシは、セキュリティの最前線として重要な役割を果たします。

レート制限

# Nginxでのレート制限
http {
    # 1秒あたり10リクエストまで許可
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

    server {
        location /api/ {
            # バーストは20リクエストまで許可し、遅延なしで処理
            limit_req zone=api_limit burst=20 nodelay;
            limit_req_status 429;

            proxy_pass http://localhost:3000;
        }

        # ログイン試行のレート制限(より厳しく)
        location /api/login {
            limit_req zone=login_limit burst=5 nodelay;
            proxy_pass http://localhost:3000;
        }
    }

    limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
}
# Caddyでのレート制限
app.example.com {
    rate_limit {
        zone api {
            key {remote_host}
            events 10
            window 1s
        }
    }

    handle /api/* {
        reverse_proxy localhost:3000
    }
}

不要な情報の隠蔽

# Nginxでのサーバー情報の隠蔽
http {
    # Serverヘッダーからバージョン情報を除去
    server_tokens off;

    server {
        # バックエンドのServerヘッダーを除去
        proxy_hide_header X-Powered-By;
        proxy_hide_header Server;

        # セキュリティヘッダーの追加
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Frame-Options "DENY" always;
        add_header Content-Security-Policy "default-src 'self'" always;
    }
}

IPアドレスによるアクセス制限

# Nginxでの管理画面へのアクセス制限
location /admin/ {
    allow 203.0.113.0/24;    # オフィスのIPアドレス範囲
    allow 198.51.100.10;     # VPNのIP
    deny all;                 # その他はすべてブロック

    proxy_pass http://localhost:3001;
}

実践的な構成パターン

リバースプロキシを活用した代表的なアーキテクチャパターンを紹介します。

SPA + APIサーバー構成

# フロントエンド(React/Vue)とバックエンドAPI を同一ドメインで配信
server {
    listen 443 ssl http2;
    server_name app.example.com;

    # APIリクエスト
    location /api/ {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # SPAのルーティング
    location / {
        root /var/www/app/dist;
        try_files $uri $uri/ /index.html;

        # 静的ファイルのキャッシュ制御
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }
}

マイクロサービスのAPIゲートウェイ

# リバースプロキシをAPIゲートウェイとして使用
server {
    listen 443 ssl http2;
    server_name api.example.com;

    # ユーザーサービス
    location /api/users/ {
        proxy_pass http://user-service:3001/;
    }

    # 商品サービス
    location /api/products/ {
        proxy_pass http://product-service:3002/;
    }

    # 注文サービス
    location /api/orders/ {
        proxy_pass http://order-service:3003/;
    }

    # 共通のプロキシ設定
    location /api/ {
        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-Request-Id $request_id;
    }
}

まとめ:リバースプロキシを活用してアーキテクチャを改善しよう

リバースプロキシは、Webアプリケーションのセキュリティ、パフォーマンス、可用性を向上させる重要なコンポーネントです。

本記事のポイントを整理します。

基本概念
・リバースプロキシはクライアントとバックエンドサーバーの間に位置する
・SSL終端、負荷分散、キャッシュ、セキュリティ強化が主な役割
・フォワードプロキシとは配置場所と目的が異なる

Nginxの活用
・高いパフォーマンスと豊富な設定オプション
・パスベースルーティング、WebSocket対応、プロキシキャッシュが可能
・設定ファイルの記述量は多いが、細かい制御が可能

Caddyの活用
・自動HTTPSにより証明書管理が不要
・シンプルな設定ファイルで直感的に設定できる
・新規プロジェクトや小〜中規模のサービスに適している

セキュリティ対策
・レート制限で過負荷やDDoS攻撃を緩和する
・サーバー情報を隠蔽して攻撃対象の情報を減らす
・IPアドレスによるアクセス制限で管理画面を保護する

リバースプロキシの設定は、最初はシンプルに始めて、必要に応じて機能を追加していくアプローチをおすすめします。NginxとCaddyのどちらを選ぶかは、プロジェクトの規模や運用体制に応じて判断してください。

#リバースプロキシ#Nginx#Caddy
共有:
無料メルマガ

週1回、最新の技術記事をお届け

AI・クラウド・開発の最新記事を毎週月曜にメールでお届けします。登録は無料、いつでも解除できます。

プライバシーポリシーに基づき管理します

起業準備に役立つ情報、もっとありますよ。

まずは話だけ聞いてもらう