DNS ALIAS 非対応の外部 DNS でも実現できる APEXドメイン転送 AWS サーバレスソリューション(前編)

こんにちは、SCSKでテクニカルエスコートサービスを担当している兒玉です。

Webサイトを作成する際に、APEXドメインへのアクセスを転送したい、と思うことはありませんか?
APEXドメイン(アペックスドメイン、Zone APEX 、ネイキッドドメイン、ルートドメインとも呼ばれる)とは、「example.com」のようにサブドメイン(www.など)を含まない、ドメイン名そのもののアドレスを指します。

Webサイトにアクセスするユーザー側の立場として考えると、サブドメインあるいはサーバー名を指定してアクセスするのは入力するのが面倒ですし、通例として www に決まっているとしても、決まっているならそっちに自動的に誘導してほしいと考えるのは自然な考えだと思います。

ところが、DNSの仕組みからすると、APEXドメインはちょっと厄介で、APEXドメインには CNAME 適用できないという制約があります。

# これはできない(RFC違反)
example.com. CNAME d123456789.cloudfront.net.

# サブドメインならOK
www.example.com. CNAME d123456789.cloudfront.net.

CNAMEはそもそも「このドメインのことは全部あっちの窓口にお願いします」という記述なのですが、APEXドメインにはSOA(Start Of Authority) つまり「このドメインの責任者は私です」という名札をつけて立っている担当者がいる状況なわけです。
こんな矛盾した記述がされているドメインにDNSが問い合わせを行うと、混乱を招いてしまうため禁止されているんですね。

しかし、wwwなどサーバ名なしのドメインからそのドメインのホームページにたどり着きたいという動機もわかります。

では、どうすればよいか。

選択肢としては3つあります。

1. Amazon Route 53のALIASレコードを使う
Route 53を使っている場合、ALIASレコードという特殊なレコードタイプが使えます。これはAWS独自の機能で、APEXドメインでもCloudFrontやALBを指定できます。

しかし、これはRoute 53を使っている場合のみ。DNSサーバーを移管したくない、あるいは移管できない状況ではこの選択肢は採用できません。

2. 外部DNSプロバイダーの独自機能を使う
一部のDNSプロバイダー(Cloudflare、DNSimpleなど)は、ALIAS相当の独自機能を提供しています。

しかし、全てのプロバイダーが対応しているわけではありませんし、移管できない状況であれば 1. のケースと同様にこちらも採用できません。

3. 固定IPアドレスを使う
Aレコードで固定IPアドレスを指定する方法。これならどのDNSプロバイダーでも使えます。

仕方なく 3. を選ぶことになります。ところが、AWS上でベストプラクティスとされる CloudFront や ALBは動的IPなので、固定IPアドレスを持つサーバー(例えば Elastic IP + EC2)が別に必要になってしまいます。これをうまくサーバレスで解決するソリューションを考えます。

まとめると、こんな状況ではないでしょうか?

  • 会社のポリシーでALIAS相当の機能に対応していない外部DNSプロバイダーを使わなければならない
  • でもAPEXドメインでのアクセスを受け付けたい
  • CloudFrontやALBなど、AWSのサービスにリダイレクトしたい
  • サーバーの維持管理をしたくないのできればサーバーレスで実現したい 

このソリューションでは、こんな状況を解決いたします!

前編では、検証用のリダイレクト先環境と証明書の準備までを行います。

 

ソリューションの全体像

ソリューションの全体像は以下のようになります。

他社DNSでのAPEXドメインレコードに対する要件(IPアドレスを直接設定)を満たすために、Network Load Balancer(NLB) に Elastic IP を付与し、Webサイトとして必要な証明書は Application Load Balancer(ALB) で行い、サブドメインに対するリダイレクト処理を行うHTML応答を Lambda関数内で生成、レスポンスとして返却することで、ブラウザにサブドメインへリダイレクトするよう促します。

ソリューションの全体像と処理概要

この処理をフロー図にすると以下のようになります。

このソリューションの料金概算

前提条件

  • リージョン: ap-northeast-1(東京)
  • 月間リクエスト数: 100万リクエスト(想定)
  • 平均レスポンスサイズ: 10KB
  • 稼働時間: 24時間365日(730時間/月)

使用サービスと料金

AWS Lambda

設定
  • メモリ: 128MB
  • ランタイム: Python 3.12
  • 平均実行時間: 100ms(想定)
料金
  • リクエスト料金: $0.20 per 1M requests
    • 100万リクエスト × $0.20 = $0.20/月
  • コンピューティング料金: $0.0000166667 per GB-second
    • 100万リクエスト × 0.1秒 × 0.125GB = 12,500 GB-秒
    • 12,500 GB-秒 × $0.0000166667 = $0.21/月
  • Lambda合計: $0.41/月

 

Application Load Balancer (ALB)

料金
  • ALB時間料金: $0.0243 per hour(東京リージョン)
    • 730時間 × $0.0243 = $17.74/月
  • LCU料金: $0.008 per LCU-hour
    • 想定: 0.5 LCU/時間(低トラフィック)
    • 730時間 × 0.5 LCU × $0.008 = $2.92/月
  • ALB合計: $20.66/月

 

Network Load Balancer (NLB)

料金
  • NLB時間料金: $0.0243 per hour(東京リージョン)
    • 730時間 × $0.0243 = $17.74/月
  • NLCU料金: $0.006 per NLCU-hour
    • 想定: 0.5 NLCU/時間(低トラフィック)
    • 730時間 × 0.5 NLCU × $0.006 = $2.19/月
  • NLB合計: $19.93/月

 

Elastic IP Address

料金
  • Public IPv4アドレス料金: $0.005 per IP per hour
    • 2個のElastic IP × 730時間 × $0.005 = $7.30/月
  • Elastic IP合計: $7.30/月

 

AWS WAF

設定
  •  Web ACL: 1個
  • マネージドルール: 3個(AWSManagedRulesCommonRuleSet、SQLi、KnownBadInputs)
  • カスタムルール: 1個(Rate-based rule)
  • 合計ルール数: 4個
料金
  • Web ACL料金: $5.00 per month
  • ルール料金: $1.00 per rule per month
    • 4ルール × $1.00 = $4.00/月
  • リクエスト料金: $0.60 per 1M requests
    • 100万リクエスト × $0.60 = $0.60/月
  • WAF合計: $9.60/月

 

VPC関連リソース

料金
  • VPC: 無料
  • Subnets: 無料
  • Internet Gateway: 無料
  • Route Tables: 無料
  • Security Groups: 無料
  • VPC合計:$0.00/月

 

その他料金

  • インターネットへのデータ転送(アウトバウンド):
    • 最初の10TB/月: $0.114 per GB(東京リージョン)
      – 次の40TB/月: $0.089 per GB
      – 次の100TB/月: $0.086 per GB
    • 100万リクエスト × 10KB = 10GB/月の場合
      – データ転送料金: 10GB × $0.114 = $1.14/月
  • その他料金合計: $1.14/月

 

VPC関連リソース

月額料金合計

 

サービス 月額料金(USD) 月額料金(JPY)※
Lambda $0.41 ¥62
ALB $20.66 ¥3,099
NLB $19.93 ¥2,990
Elastic IP (×2) $7.30 ¥1,095
WAF $9.60 ¥1,440
VPC $0.00 ¥0
ACM $0.00 ¥0
IAM $0.00 ¥0
その他 $1.14 ¥171
合計 $59.04 ¥8,857

※ 為替レート: 1 USD = 150 JPY で計算

 

検証用リダイレクト先(転送先ドメイン)の作成

本番では本来のWebサイト( 例えば www.example.com ) に転送するのですが、今回は記事用の検証なので転送先ドメインが必要です。検証用に CloudFront – S3 の環境を作成します。下図の右側の赤枠の範囲になります。

本筋でないコードを全部載せるとそれだけで記事が埋め尽くされてしまうので、必要なファイルのを zip 化したファイルのリンクを載せておきます。

test_environment.zip

SHA256: 829899f97643f4dac1dff61e7600a42da4e5afd5e3f4b702cf010d95051eb960

ダウンロードしたファイルを CloudShell などにファイルをアップロードし、
CloudShell Upload

zip ファイルの中身を展開してフォルダを移動します。

~ $ unzip test_environment.zip -d ./test_environment
Archive:  test_environment.zip
  inflating: ./test_environment/deploy_test_environment.sh  
  inflating: ./test_environment/test-environment.yaml  
  inflating: ./test_environment/TEST_ENVIRONMENT_README.md  
~ $ cd test_environment
test_environment $

 

vim などで、 deploy_test_environment.sh の中のパラメータを修正します。

  • PROFILE は AWS が使用するプロファイル名でえすが、 CloudShellからの実行の場合は “” で良いです。
  • STACK_NAME は CloudFormationが作成するスタック名です。わかりやすい名前や環境の命名規則に沿った形に変更します。
  • COST_TAG はAWS内でのコスト配分タグとして使用されるタグの値を設定します。(タグの属性名は 内部では “Cost” と固定になっています。)
deploy_test_environment.sh のパラメータ設定

deploy_test_environment.sh のパラメータ設定

パラメータを修正後、デプロイします。

test_environment $ ./deploy_test_environment.sh 

10分くらいで、デプロイが完了するので 

CloudFront Domain: abcdef01234567.cloudfront.net
Test Website URL: https://abcdef01234567.cloudfront.net

の箇所をメモしておきます。 これが転送先となる検証用リダイレクト先サイトのドメイン名とWebサイトの URL です。

Test Website URLにアクセスしてみると、

アクセスできましたね。(画像参照)
これで検証用リダイレクト先ドメインの環境ができました。

APEXドメイン/サブドメイン用のサーバー証明書の準備

転送用の APEXドメインも https でアクセスが必要ならAPEXドメイン用の証明書が必要です。

サブドメインのワイルドカードも一緒に設定します。これは転送先(www.example.comなど)でも使えますので、AWS Certification Manager から 1枚にまとめて発行します。

CloudFront で使用するので、 証明書を作成するリージョンは 米国東部(バージニア北部)(us-east-1)  である必要があります。

 

エクスポート可能な証明書は有料ですが、AWS内でのみ使用する場合はエクスポート不要なので無料で利用できます。

料金 – ACM
AWS Certificate Manager の料金 – アマゾン ウェブ サービス (AWS)

リクエストをしただけでは、証明書は有効になりません。まだ、 「保留中の検証」というステータスになっているのがわかります。
ドメインの正当な持ち主であることを証明するために、 証明書をリクエストしたドメインのDNSの 指定された CNAME名 に指定された CNAME値 を設定する必要があります。

CNAME 名 と、 CNAME 値をコピーして、 DNS のプロバイダ画面から、 CNAMEレコードを追加して、 コピーしておいた CNAME名、対応する CNAME値 を設定します。
今回はAPEXドメイン用と、 そのサブドメイン用のワイルドカードで 2 レコードありますが、設定すべき値のセットは同じだったので 追加した CNAME レコードは 1 つでした。

DNSプロバイダの設定画面はUIが様々でどう設定すれば良いかはそのプロバイダ毎に異なるのですが、きちんと設定できているかは dig コマンドで検証すればわかります。
マスクされている箇所ばかりでわかりにくいですが、

dig cname _9c63abcdef0123456789abcdef01234.example.com.

と打って、応答の ANSWER SECTION で、 CNAME名 の対となる CNAME値 が表示されれば OK です。

しばらくすると、Certificate Manager の証明書のステータスが「発行済み」に、ドメインのステータスが 「成功」 に変わります。

これで証明書は利用可能になりました。

検証用リダイレクト先サイトに ACM 証明書を設定

転送先となる検証用リダイレクト先(www.example.com) の CloudFront に、サブドメイン  www.example.com を担当してもらうために、担当するサブドメイン名とCertificate Managerから取得した証明書を設定します。

CloudFormationスタックに、先程作成した検証用リダイレクト先のスタックがありますので、 CloudFrontDistributionId の 値 にあるディストリビューションを覚えておいて、マネジメントコンソールの CloudFront の画面から開きます。

ディストリビューションの画面から Add domain をクリック

www.example.com (実際は自分のドメイン名) を入力して、Next をクリック


先程作成した証明書が表示されるので、それをチェックして Next、


変更を確認してAdd domains 

Distribution updated successfully と表示され、代替ドメイン名に www.example.com 、カスタムSSL証明書の欄がチェックマークになっていればOKです。

Route domains to CloudFront ボタンを押すと、DNSサーバーに設定する レコードの情報が表示されます。これを、利用しているDNSサーバーに設定します。
DNSプロバイダーによってはAレコードに値を直接入力できない場合がありますが、その場合はCNAMEレコードとして設定しても問題ありません。

今回はここまで。

タイトルとURLをコピーしました