0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS設計パターン】オリジンサーバー不要!Route 53 × CloudFront × Lambda@Edgeによる10ドメイン一括エッジリダイレクト基盤

0
Posted at

📌 はじめに

企業のマーケティングキャンペーンやブランド統合の際、複数の旧ドメインやキャンペーン用ドメイン(10個以上)を特定のターゲットURLへHTTP/HTTPS問わずリダイレクトさせたいケースが頻繁に発生します。

従来のEC2やALBを用いた構成では、Webサーバーの管理や証明書更新などの運用負荷(Operational Effort)が発生します。今回は、AWSのエッジロケーションのみで完結し、バックエンドのオリジンサーバーを一切持たない**「Originless(無源站)」エッジリダイレクトアーキテクチャ**をまとめます。

1. アーキテクチャトポロジー(Originless Edge Architecture)

                    [ クライアントブラウザ (10個のドメインのいずれかにアクセス) ]
                                      │
                                      │ (1) DNSクエリ (HTTP / HTTPS)
                                      ▼
                          [ Amazon Route 53 ]
               (10個のホストゾーン。すべて同一CloudFrontへのAlias Aレコード)
                                      │
                                      │ (2) 最寄りのエッジロケーションへアクセス (SNI)
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                      Amazon CloudFront ディストリビューション (単一)           │
│                                                                             │
│  - ACM証明書 (us-east-1): 10個のドメインを含むSANマルチドメイン証明書          │
│  - 代替ドメイン名 (CNAMEs): domain1.com, domain2.com ... domain10.com        │
│  - トリガー: Viewer Request (ビューワーリクエスト)                           │
│                                                                             │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │                    Lambda@Edge 関数                                   │  │
│  │                                                                       │  │
│  │  1. リクエストヘッダーから Host (アクセス元ドメイン) と URI Path を取得   │  │
│  │  2. パッケージ内の JSON マッピング設定 (Key-Value) を参照              │  │
│  │  3. エッジで直接 HTTP 301 / 302 リダイレクトレスポンスを生成・返却:    │  │
│  │     Status: 301 Moved Permanently                                     │  │
│  │     Header: Location: [https://target-url.com/xxx](https://target-url.com/xxx)                      │  │
│  └──────────────────────────────────┬────────────────────────────────────┘  │
└─────────────────────────────────────┼───────────────────────────────────────┘
                                      │
                                      │ (3) エッジから即座に301/302を返却(オリジン不要)
                                      ▼
                      [ ブラウザがLocationヘッダーを受け取りリダイレクト ]

2. コアステップと技術的根拠(最小の運用負荷を達成する3大メカニズム)

本設計の目標は、「最小の運用負荷(Least Operational Effort)」 で10個のドメインに対するHTTPおよびHTTPSのリダイレクトを実現することです。

① セキュリティとHTTPS終端:ACM SAN証明書(マルチドメイン証明書)

  • 単一証明書による一元管理: 10個のドメインでHTTPSを終端するため、AWS Certificate Manager (ACM)(バージニア北部 us-east-1 リージョン)で1枚のSSL/TLS証明書をリクエストします。
  • サブジェクト代替名(SAN)の活用: メインドメインに加え、残りの9ドメインをサブジェクト代替名(Subject Alternative Names, SAN)として登録します。これにより、証明書の更新管理やCloudFrontへのアタッチを1回で完結できます。

② グローバルエッジルーティング:単一のCloudFrontディストリビューション

  • ディストリビューションの集約: ドメインごとにCloudFrontを作成するのではなく、単一のディストリビューションに10個すべてのドメインを代替ドメイン名(CNAMEs)として登録し、上記のACM SAN証明書を紐付けます。
  • Originless(オリジン不要)設計: 後述のLambda@Edgeでリクエストを直接遮断・返却するため、S3バケットやEC2などのバックエンドオリジンサーバーを構成・保守する必要がありません(ダミーオリジン設定のみで動作)。

③ 動的マッピングと短絡リダイレクト:Lambda@Edge(Viewer Request)

  • Viewer Request での処理完結: CloudFrontの Viewer Request イベントでLambda@Edgeをトリガーします。
  • JSONテーブル参照によるリダイレクト:
  1. リクエストの Host ヘッダーと URI Path を抽出。
  2. 同梱したJSONファイル(またはコード内の辞書構造)からリダイレクト先を検索。
  3. HTTP 301(恒久的な移動)または HTTP 302(一時的な移動)レスポンスオブジェクトを即座に生成して返却。
  • メリット: エッジロケーションでミリ秒単位でリダイレクトが完了します。VPCやオリジンへの通信が一切発生しないため、レイテンシが極小化され、サーバー運用コストがゼロになります。

3. 実装コード例

リダイレクトルール定義 (redirect_rules.json)

{
  "domain1.com": "[https://brand-portal.com/campaign-a](https://brand-portal.com/campaign-a)",
  "domain2.com": "[https://brand-portal.com/campaign-b](https://brand-portal.com/campaign-b)",
  "[domain3.com/service](https://domain3.com/service)": "[https://service-portal.com/main](https://service-portal.com/main)"
}

Lambda@Edge 実装例 (Python 3.x)

import json
import os

# デプロイパッケージ内に含めたルール定義をロード
with open('redirect_rules.json', 'r') as f:
    REDIRECT_MAP = json.load(f)

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']
    
    # Hostヘッダーの取得
    host = headers.get('host', [{}])[0].get('value', '').lower()
    uri = request.get('uri', '')
    
    # ドメイン + パス、またはドメイン単体でマッチング
    lookup_key = f"{host}{uri}".rstrip('/')
    target_url = REDIRECT_MAP.get(lookup_key) or REDIRECT_MAP.get(host)
    
    # デフォルトのリダイレクト先(マッチしなかった場合)
    if not target_url:
        target_url = "[https://default.example.com](https://default.example.com)"

    # エッジから即座に 301 レスポンスを生成して返却
    response = {
        'status': '301',
        'statusDescription': 'Moved Permanently',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': target_url
            }],
            'cache-control': [{
                'key': 'Cache-Control',
                'value': 'max-age=3600'
            }]
        }
    }
    
    return response

4. 設計上のトレードオフとアンチパターン

アプローチ 評価と課題
S3静的ウェブサイトホスティングのリダイレクト機能 ❌ 不適: S3ウェブサイトエンドポイントはHTTPSを直接サポートしていません。HTTPS終端のために各ドメインごとにCloudFrontや個別設定が必要となり、10ドメイン構成では管理コストが増大します。
ALB + EC2/コンテナによるNginxリダイレクト ❌ 高運用負荷: Webサーバーのパッチ適用、スケーリング設定、AZ分散など、本来不要なインフラ運用オーバーヘッドが発生します。
CloudFront Functions を利用する ⚠️ 検討可能: 単純な文字列置換であればCloudFront Functionsも有力な選択肢です。ただし、多数の複雑なURLマッピングJSONファイルを外付けで管理・デプロイしたい場合や、ルール数が多い場合はLambda@Edgeのパッケージング柔軟性が有利に働きます。

5. まとめ

  • ACM SAN証明書: 1枚の証明書に10ドメインを登録することで、証明書管理コストを最小化。
  • 単一CloudFront: 10ドメインを1つのディストリビューションに束ね、グローバル展開。
  • Lambda@Edgeによるエッジ完結: オリジンサーバーを一切立てず、Viewer RequestでJSON設定を参照して301を返却することで、ミリ秒級の超低遅延と運用レスなアーキテクチャを実現。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?