やさしいCloudFront の代替ドメイン名設定
Contents
概要
はじめに
- 今回は、CloudFront のディストリビューションに代替ドメイン名(CNAME)を設定する方法をまとめます。代替ドメイン名の設定によって、ディストリビューションにデフォルトで割り当てられたドメイン名ではなく独自のドメイン名 (例: www.example.com) が使用可能です。
前提条件
- 今回の記事では、CloudFront のオリジンにELB-EC2 を使用します。クライアントからCloudFrontまでのアクセスはHTTPS通信とし、CloudFront からオリジンまでのアクセスはHTTP通信とします。
- 事前に、SSL 証明書を準備します。証明書のドメイン名は、ディストリビューションに設定する代替ドメイン名と一致させる必要があります。今回は、Certificate Manager(ACM)で証明書を発行します。
CloudFront に代替ドメイン名を設定して公開する
オリジン・キャッシュ動作の設定
- CloudFront のコンソールを開きます。左のメニューより[Distributions]を選択し、[Create Distribution]を押します。
- 下記の画面で、「delivery method for your content」に「Web」を選択します。
- ディストリビューションを作成します。以下、オリジンの設定です。
- Origin Domain Name(オリジンドメイン名)に、オリジンに設定するELB を選択します(ELBはALB、NLBのどちらで可)。オリジンドメイン名には、ELBのDNS名以外に、S3バケット名やEC2 インスタンスのDNS名、独自のウェブサーバー(https://example.com)も指定可能です。
- Origin Path(オリジンのパス)に、ディレクトリパスを入力します。
- Minimum Origin SSL Protocol(最小限のオリジン SSL プロトコル)を指定します。
- Origin Protocol Policy(オリジンプロトコルポリシー)に、CloudFront がオリジンからオブジェクトをフェッチするときに使用するプロトコルを指定します。今回は、オリジンとするELB のリスナーに合わせてHTTP Only とします。
- その他のオリジン・キャッシュ動作の設定は、下記ドキュメントを参照ください。
ディストリビューションの設定
- Alternate Domain Names(CNAMEs)(代替ドメイン名)の設定に、設定する独自のドメイン名を指定します。
- SSL Certificate(SSL 証明書)は代替ドメイン名を指定する場合に必須です。Custom SSL Certificateを選択して、証明書を指定します。証明書は下記のいずれかとなります。今回は、ACMで発行した証明書を使用します。なお、ACMで発行する場合は、バージニア北部のリージョンに配置することを忘れずに。
- AWS Certificate Manager から提供される証明書
- サードパーティ認証機関から購入して ACM にアップロードした証明書
- サードパーティ認証機関から購入して IAM 証明書ストアにアップロードした証明書
- その他のディストリビューションの設定は、下記ドキュメントを参照ください。
ディストリビューションのドメイン名をDNS登録
- ディストリビューションが作成できたら、ステータスからデプロイされたことを確認します。
- 次に、CloudFrontによってデフォルトで割り当てられたディストリビューションのドメイン名をコピーし、DNSにレコード登録します。
CloudFront代替ドメイン名の動作確認
- クライアントからcurlコマンドで、CloudFrontの代替ドメイン名にアクセスできるかを確認します。
504 ERROR “The request could not be satisfied." の調査
- 今回は、初回に「504 ERROR The request could not be satisfied.」のエラーが発生しました。
- オリジン、CloudFrontにそれぞれ疎通確認を行い、調査します。エラーの原因は、オリジンに設定したELB のセキュリティグループにCloudFrontからのアクセスを許可していなかったためでした。(今回はNLBのためEC2側のセキュリティグループにCloudFrontからアクセスできるようインバウンドの設定を追加します)
niikawa@niikawa1:~$ curl -vv https://xyzxyzxyzxyzx.cloudfront.net
* Rebuilt URL to: https://xyzxyzxyzxyzx.cloudfront.net/
* Trying xxx.xxx.xxx.xxx...
* TCP_NODELAY set
* Connected to xyzxyzxyzxyzx.cloudfront.net (xxx.xxx.xxx.xxx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=US; ST=Washington; L=Seattle; O=Amazon.com, Inc.; CN=*.cloudfront.net
* start date: Jul 17 00:00:00 2019 GMT
* expire date: Jul 5 12:00:00 2020 GMT
* subjectAltName: host "xyzxyzxyzxyzx.cloudfront.net" matched cert's "*.cloudfront.net"
* issuer: C=US; O=DigiCert Inc; CN=DigiCert Global CA G2
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fffc6f00580)
> GET / HTTP/2
> Host: xyzxyzxyzxyzx.cloudfront.net
> User-Agent: curl/7.58.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 504
< content-type: text/html
< content-length: 1033
< server: CloudFront
< date: Thu, 09 Apr 2020 00:35:34 GMT
< x-cache: Error from cloudfront
< via: 1.1 3230a3d42078a094780d1894002fcfd5.cloudfront.net (CloudFront)
< x-amz-cf-pop: NRT12-C2
< x-amz-cf-id: bG4vtNFlQtECuxXDcUtZRGleu1OVZQO5NH0Ot5Qy7q2sQjzRgCA1MQ==
< age: 150
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>504 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
CloudFront attempted to establish a connection with the origin, but either the attempt failed or the origin closed the connection.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: QsreLiLT9THqTGxKduq8Yro-6iddWuspLwPtrwHxHiFa4CUseAxWFA==
</PRE>
<ADDRESS>
</ADDRESS>
* Connection #0 to host xyzxyzxyzxyzx.cloudfront.net left intact
</BODY></HTML>
CloudFront代替ドメイン名の疎通確認がOKに
- 前述の通りセキュリティグループを見直し、エラーを対処しました。改めてCloudFront のデフォルトのDNS名および代替ドメイン名に対して疎通確認を行い、200 OK が返ることを確認します。下記結果より、curl コマンドでレスポンスが返りました。(curl の-vv オプションの結果は省略)
niikawa@niikawa1:~$ curl https://xyzxyzxyzxyzx.cloudfront.net
backend web1
niikawa@niikawa1:~$ curl https://niikawa-test.example.com
backend web1