はじめに
EC2の単一構成の場合に、Cloudfront+WAFを導入する構成を構築してみる。
今回は、ドメイン管理サービスにRoute53は使用せずに、Cloudflareを利用する。
環境
AWS
- EC2
- Cloudfront
- WAF
- ACM準備
以下の準備が完了していること
- AWSのアカウントが作成されていること
- EC2が構築されていること
EC2インスタンスの構築
今回はテスト用に作成をしておく。
| 項目 | 設定値 |
|---|---|
| 名前 | server |
| OS | AmazonLinux2023 AMI |
| アーキテクチャ | 64ビット(Arm) |
| インスタンスタイプ | t4g.nano |
| キーペア | server(新規で作成) |
| セキュリティグループ | ssh,http,https (自分のIPのみ) |
| ストレージ | 8GB (gp3) |
上記構成で構築を行う。
構築後、確認用のため以下のアプリケーションをインストールしておく。
dnf install -y httpd phpまた、固定のIPをつけておきたいため、Elastic IPも付与しておく。
固定IP付与後、EC2のインスタンスにドメインを割り振っておく。
構成図
導入前-構成図
導入前の構成図は以下の通りとなる。
導入後-構成図
導入後の構成図は以下の通りとなる。
※静的コンテンツも動的コンテンツもEC2のインスタンス内にあるという前提となる。
この構成には、以下改善したほうが良い点があるが、一旦ここでは扱わないことにする。
ALBを追加して、プライベートサブネットとNAT GateWayの構成にしたほうが良い- 静的コンテンツは
S3などに分離して配置する
作業
まずは、Cloudfrontの設置から行う。Cloudfrontのディストリビューション作成時に、WAFも同時に作成できるが今回は一つずつ作成して検証をしていく。
Cloudfrontを作成する
1. AWSコンソールより、「Cloudfront」サービスを選択する

2. ナビゲーションペインの「ディストリビューション」を選択し、「ディストリビューションを作成」を選択する

3. 設定を変更し、「ディストリビューション」を作成する
設定については以下を変更する。
| 項目 | 設定値 |
|---|---|
| Origin domain | ec2-54-178-217-170.ap-northeast-1.compute.amazonaws.com (※1) |
| プロトコル | HTTPのみ (※2) |
| 名前 | ec2-54-178-217-170.ap-northeast-1.compute.amazonaws.com |
| Enable Origin Shield | いいえ |
| オブジェクトを自動的に圧縮 | Yes |
| ビューワープロトコルポリシー | Redirect HTTP to HTTPS (※3) |
| 許可された HTTP メソッド | GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE (※4) |
| ビューワーのアクセスを制限する | No |
| キャッシュキーとオリジンリクエスト | Cache policy and origin request policy (recommended) |
後は適当にデフォルトの設定を使用することにした。 エッジロケーションとか料金にかかわる部分についてはちゃんと考えておいたほうがよさそう。
※1Origin domainについて、オリジンとするEC2サーバのドメイン名となる。Distribution settings referenceを見ると、EC2サーバの設定については、パブリック IPv4 DNS を指定しているようだが、独自のWebサーバ(通常の設定したドメイン名)でもよさそう。
- Distribution settings reference
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesDomainName
※2Cloudfront-オリジン間のプロトコルとなる。httpsで接続させたい場合は、EC2内の証明書とCloudfrontで利用する証明書を一致させないといけないので、また別の手順が必要となる。
- CloudFrontのオリジンをEC2にしてHTTPS通信を強制する構成について
https://dev.classmethod.jp/articles/how-to-create-cloudfront-ec2-e2e-https-connection/
※3
ビューワー・・・接続するクライアントのこと。http and httpsとするとどちらでも接続ができるが、httpsとしたいので、Redirect HTTP to HTTPSにしておく。HTTPS only でもよいと思うのだが。
※4GET,HEAD以外に、POSTやPUTなども利用できるようにしないと、オリジンへの接続時にアプリケーションの登録更新で正しく動作しないため。
静的コンテンツの場合は、GET, HEADで事足りるが、今回は分離していない構成ということでこれを選択。

4. ディストリビューションが作成された

5. ステータスが「有効」になっていればOK

EC2のセキュリティグループを変更する
CloudfrontからのEC2へトラフィックが流れる形となるので、それ以外からのトラフィックについては拒否しておきたい。
そのため、セキュリティグループをCloudfrontのhttp/httpsのみのプロトコルのみ許可するように設定をする。
1. 「EC2」サービスからナビゲーションペインより「セキュリティグループ」を選択し、「セキュリティグループを作成」を選択する

2. セキュリティグループを設定する
今回は、80のみ許可すれば問題ない。
※オリジン間のプロトコルで、httpsも許可している場合は、443も空けておくこと。
Cloudfrontのリストは、マネージドプレフィックスリストという予め用意されているソースがあるため、これを選択する。
- Amazon CloudFront用のAWS マネージドプレフィックスリストを使用したオリジンへのアクセス制限
https://aws.amazon.com/jp/blogs/news/limit-access-to-your-origins-using-the-aws-managed-prefix-list-for-amazon-cloudfront/

3. 「EC2」サービスから「インスタンス」を選択し、セキュリティグループを変更する
対象のインスタンスを選択し、「アクション」→「セキュリティ」→「セキュリティグループを変更する」を選択する。

4. 作成したセキュリティグループをアタッチし、「保存」を選択する

ACM(AWS Certificate Manager)で証明書をリクエストする
Cloudfrontで代替ドメイン名を設定するために(test.k-bushi.comでアクセスさせるため)、証明書をリクエストする。
※米国東部 (バージニア北部) リージョン (us-east-1) にある必要があるため注意。
1. 「Certificate Manager」サービスを選択する

2. 「証明書をリクエスト」を選択する

3. 「証明書をリクエスト」を行う
4. リクエスト完了後、ドメインを設定する
以下のドメインを設定する。

5. 発行済みとなれば完了

Cloudfrontで代替ドメイン名を設定する
1. 「Cloudfront」サービスで「ディストリビューション」を選択し、編集をする
「ディストリビューション」→ 先ほど作成したディストリビューションのID部分を選択 → 「編集」を選択する。

動作確認では、Cloudfront経由でEC2インスタンスへのアクセスができているかどうかについてを確認する。
2. Alternative domain name (CNAMEs) - optional`を入力、証明書を選択し、変更を保存する

3. ディストリビューションの画面で設定が確認できればOK
後は「デプロイ」ステータス→「最終変更日時」が表示されれば完了している。

DNSレコードを変更する
test.k-bushi.comがまだEC2インスタンスへ向いてしまっているので、Cloudfrontへ向くように変更する。
1. 変更するCNAMEレコードの値を確認する
「Cloudfront」→「ディストリビューション」→作成したディストリビューションを選択→「ディストリビューションドメイン名」を確認する。

2. ドメイン管理サービスでCNAMEレコードを追加する
-test IN A [IPアドレス]
+test IN CNAME [Cloudfrontのディストリビューション名]
※元々あったAレコードは削除しておく。

EC2+Cloudfront構成の疎通確認
これでようやく確認できるようになったので、test.k-bushi.comにアクセスをしてみる。

できているのでOK! 次はWAFを設定してみる。
WAFの設定
先ほどは設定をしていなかったWAFをこのステップで設定する。
1. 「Cloudfront」サービスで「ディストリビューション」を選択し、Editをする
「ディストリビューション」→ 先ほど作成したディストリビューションのID部分を選択 → 「Edit」を選択する。

2. 「セキュリティ保護を有効にする」とし、設定を変更し「Save Changes」を選択する
「セキュリティ保護を有効にする」を押すと、オプションが選べるようになる。
今回は下記の設定とした。

3. 設定が反映されていれば完了

参考
Distribution settings reference
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesDomainNameCloudFrontのオリジンをEC2にしてHTTPS通信を強制する構成について
https://dev.classmethod.jp/articles/how-to-create-cloudfront-ec2-e2e-https-connection/Amazon CloudFront用のAWS マネージドプレフィックスリストを使用したオリジンへのアクセス制限
https://aws.amazon.com/jp/blogs/news/limit-access-to-your-origins-using-the-aws-managed-prefix-list-for-amazon-cloudfront/代替ドメイン名 (CNAME) を追加することによって、カスタム URL を使用する
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html独自ドメインでCloudFront にアクセスできるようにする
https://qiita.com/kanadeee/items/752e20af5b071ef0e011
おわりに
EC2+Cloudfront+WAFという構成を構築してみた。EC2をオリジンにしたことはなかったので、意外と学びがあった。
また、WAFについてだが、個別のページと作るともっと複雑な手順だった気がするがCloudfrontで設定するWAFはすごい簡単だった…。WAFのサービスページだと、ルールの設定とかも細かく決めれたような気がするのだが。

