CloudFront と EC2 を 直接 つないで WAF でIP制限します。
普通は取らない構成ですが、興味があったので、自分用のEC2ひとつを実験台にしてやってみました。
こんな方に向けて発信しています。
- CloudFrontとEC2を直接つなぎたい
- EC2は1台しか使わない
- 柔軟にIP制限したい
- ドメイン持ってないけどHTTPSアクセスしたい
- なるべく安くおさめたい
概要

メインの内容はEC2とCloudFrontを直接つなぐことです。
結論から言うと、EC2のパブリックIPv4 DNSをCloudFrontのオリジンドメイン名に指定します。
作業としてすることは3つです。
- EC2準備
- CloudFront準備
- WAF定義
前提として、東京リージョンで作業します。
EC2 準備
インスタンス起動
以下のようにEC2を起動しました。
- Amazon Linux 2 – 64ビット (x86)
- t3.micro ( 無料枠ある方は t2.micro でも )
- セキュリティグループ名cloudfront-ec2とし、2つルールを追加
- SSH・マイIP
- HTTP・Anywhere-IPv4(任意の場所)
- 任意のキーペア指定
他の項目はデフォルトのままです。
セキュリティグループに HTTP・Anywhere-IPv4 を追加しないと、CloudFrontからのアクセスを弾いてしまいます。
EC2が野ざらしになるのですが、ここの修正は最後にやります。
Webサーバーインストール
適当なWebページが開けるようにApache2.4をインストールしておきます。
SSHして以下を実行します。
sudo yum -y update
sudo yum -y upgrade
sudo yum -y install httpd
sudo systemctl start httpd
# サービスが自動起動するように設定する
sudo systemctl enable httpd
# Apacheのバージョン確認
httpd -v
# Server version: Apache/2.4.52 ()
# Server built: Dec 30 2021 21:40:08
http://{インスタンスのパブリックIPv4 DNS}にアクセスして、Apacheのテストページが表示されればOKです。
※http://でアクセスします。
CloudFront 準備
私は以下のように作成しました。
- オリジンドメイン:EC2のパブリック IPv4 DNS
- プロトコル:HTTPのみ
- ビューワープロトコルポリシー:HTTP and HTTPS
- 許可された HTTP メソッド:GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
- Cache policy and origin request policy (recommended) を選択
- キャッシュポリシー:CachingOptimized
他はデフォルトのままです。
ちなみに「AWS WAF ウェブ ACL – オプション」は後で設定します。
(私みたいな)せっかちな人は気をつけて。
CloudFrontはすぐに使えるようになりません。
作成後にディストリビューション一覧を見ると、最終変更日が「デプロイ」になっているかもしれません。
「有効」になるまで待ちませう。
CloudFrontが有効になったら、https://{CloudFrontのドメイン名}でブラウザからアクセスしてみます。
※HTTPSでアクセスします。
Apacheのテストページが表示されればOKです。

WAF でIP制限
IPセット定義
最後にWAFを使ってホワイトリスト形式でIP制限します。
ここでは自分のIPのみ許可するようにしてみます。
- WAFのホームへアクセス
- サイドメニューからIP setクリック
- Create IP setの左隣のプルダウンからGlobal (CloudFront)を選択してCreate IP set
- IP set name:適宜入力(例:developer-ipset)
- Region:Global (CloudFront)
- IP version:IPv4
- IP addresses:アクセスを許可したいIPを入力(例:自宅のIP/32)

Web ACL作成
作成したIPセットを使ってWebACLを作成します。
- サイドメニューから「Web ACLs」クリック
- プルダウンからGlobal (CloudFront)を選択してCreate web ACL
- 先にフォームの上から4番目のResource type → CloudFront distributions
- Resorce:適宜入力(例:developer-web-acl)
- CloudWatch metric name:リソースと同じ
- Associated AWS resources で Add AWS resources
- 先ほど作成したCloudFrontを選択して Add して Next
- Add Rules から Add my own rules and rule groups を選択
- IP set を選択
- Rule:適宜入力(例:allow-ipset)
- IP set:先ほど作成したIPセットを選択
- Source IP Address・Allowを選択してAdd rule
- Default action:Block して Next
- Set rule priorityはデフォルトのままで
- Configure metricsはデフォルトのままで
- Review and create web ACLで内容を確認してCreate web ACL

CloudFront との紐づけを確認
CloudFrontのディストリビューション詳細の 一般 → 設定 で
WAFのWebACLが適用されているのがわかります。
これで準備ができたので、CloudFront経由でEC2にアクセスして確認しましょう。
これで当初の目的が達成できました🎉
これから野ざらしになっているEC2のアクセス制御をしていきます!
WAFが適用されているのを確認(おまけ)
さっきからずっとアクセスできていたので、WAFがちゃんと機能しているかわかりにくいですね。
そこで、先ほどWEbACLで定義したIPセットのアクションをBlockに変更してみます。
WebACL → 作成したACL → Rulesタブ → 該当のIPセット → 右上のEdit
でAction を BlockにしてSaveします。
自分のIPをブロックしたので、再びアクセスすると「403」エラーでアクセスできなくなりました。

WAFがちゃんと機能していることがわかりました。
これでばっちりなので、BlockしたのをAllowに戻しておきましょう。
EC2のアクセス制御
最後に、野ざらしになっているEC2を何とかします。
具体的にすることは
CloudFrontにカスタムヘッダーを追加し、Apache側でカスタムヘッダーが確認できたらアクセスを許可
するように設定します。
CloudFrontにカスタムヘッダー追加
CloudFrontのディストリビューション詳細を開き、オリジンタブから該当のオリジンを編集します。
カスタムヘッダーのキーと値は内緒です。
あとで使うので忘れないでください。

Apacheのバーチャルホストの設定を追加
既存の設定ファイルはそのままにして、以下のような内容で/etc/httpd/conf.d/vhost.confを作成します。
作成済みの方は、一番上に追加します。
2.2では書き方が違うかもしれないので注意です。
<VirtualHost *:80>
<Location '/'>
SetEnvIf カスタムヘッダ "カスタムヘッダの値" ALLOW_ACCESS
Require all denied
Require env ALLOW_ACCESS
</Location>
</VirtualHost>
Apacheの設定ファイルに大事な値を直書きしてるので、気持ち悪い人は工夫してください💦
設定ファイルを変更したら、Apacheを再起動します。
sudo service httpd restart
アクセス確認
http://{EC2のIP}の場合

https://{CloudFrontのドメイン}の場合

まとめ
CloudFrontのオリジンドメイン名にEC2のパブリックIPv4 DNSを指定して、直接つなげることができました。
最後までお読みいただきありがとうございました。
参考になれば幸いです。