以下のようなインフラ構成の各ポイントにおいて、それぞれ表題のアクセス制限をかけてみます。

【クライアント〜CloudFront間】
WAFを使用して社内IPのみ許可します。
アクセス制限はIPでの判定以外にもURLクエリに特定の文字が含まれているかで判定したり、リクエスト送信元の国で判定することが可能です。
【CloudFront〜ALB間】
外部からALBへ直接アクセスすることを禁止します。
HTTPヘッダにCloudFrontで設定したTokenもどきの文字列があるときのみ許可します。
【ALB〜Webサーバ(EC2)間】
外部からWebサーバへ直接アクセスすることを禁止します。
セキュリティグループでALB経由のアクセスのみ許可します。
アクセス制限の設定手順
セキュリティグループの作成
EC2とALBにそれぞれ割り当てるセキュリティグループを作成します。
基本的な手順は、こちらのセキュリティグループの作成 を参考にしてください。
ALB用セキュリティグループの作成
HTTP80番ポートをソース0.0.0.0/0で作成します。

EC2用セキュリティグループの作成
最初は戸惑うかもしれませんが、HTTP80番ポートのソースに上記で作成したALB用セキュリティグループ自体を指定します。
カスタムを選択するとセキュリティグループの候補が自動的に表示されます

EC2の作成
最終的なアクセス先となるWebサーバを作成します。
基本的な手順は、こちらのEC2作成を参考にしてください。
当該手順の ステップ 6: セキュリティグループの設定 で、今回作成した、EC2用セキュリティグループ を割り当てください。
ALBの作成
ALB(アプリケーションロードバランサー)を作成します。
ベースとなるALBの作成
基本的な手順は、こちらのロードバランサー作成 を参考にしてください。
当該手順の セキュリティグループの割り当て で、今回作成したALB用のセキュリティグループを割り当てください。
リスナールールの設定
ALBにリスナールールを設定します。
左ペイン [ ロードバランサー ] → [ リスナータブ ] → [ ルールの表示/編集 ] をクリックします。

アクセス制限のルールを追加
次の画面で、画面上部の [ + ] アイコン → [ + ルールの挿入 ] をクリックします。
[ IF(すべてに一致) ] → [ +条件の追加 ] → [ HTTPヘッダー ] を選択し、header typeに X-Test-Token 、値に test1234 を入力します。
[ THEN ] → [ + アクションの追加 ] → [ 転送先 ] を選択し、今回作成したEC2を選択します。
上記設定したら画面上部の [ 保存 ] ボタンを押します。
デフォルト動作の変更
次に、画面上部の [ えんぴつ ] アイコン → [ HTTP 80: デフォルトアクション ] の左の[ えんぴつ ] アイコン をクリックします。
[ THEN ] → [ 転送先 ] の [ ゴミ箱 ] アイコンクリック → [ + アクションの追加 ] → [ 固定レスポンスを返す ] → [ レスポンスコード ] に 404 を入力します。
上記設定したら画面上部の [ 更新 ] ボタンを押します。
最終的に、以下のようになっていればOKです。

WAFの作成
CloudFrontにIP制限をかけるWAFを作成します。
まずIP Setsを作成しそれをACLに割り当てる流れですすめます。
IP sets の作成
まずアクセスを許可するIPリストを定義します。
画面上部検索窓 [ WAF ] で検索 → 当該サービスをクリック → 左ペインの [ IP sets ] をクリック → プルダウンで [ Global(CloudFront)]を選択 → [ Create IP set ] をクリックします。

次の画面で以下のように入力します。 [ IP addresses ] が複数ある場合は以下のように複数行に渡って入力します。

Web ACLs の作成
IP Setsと同様に [ Global(CloudFront)]を選択、 [ Create web ACL ] をクリックします。

Describe web ACL and associate it to AWS resources
Web ACL details
以下のとおり設定します。
項目 | 値 |
---|---|
Name | test-acl |
CloudWatch metric name | test-acl |
Resource type | CloudFront distributions |
Region | 自動的に Global(CloudFront) が選択される |
Associated AWS resources – optional
特になにも追加せずデフォルトのまま [ Next ] をクリックします。
Add rules and rule groups
Rules
Add my own rules and rule group を選択します。

次の画面で以下のとおり設定します。
Add my own rules and rule groups
Rule type
IP set を選択します。
Rule
Name に test-rule を入力します。
IP set
以下のとおり設定し [ Add rule ] をクリックします。
項目 | 値 |
---|---|
IP set | 作成した test-ip-set を選択 |
IP address to use as the originating address | Source IP address |
Action | Allow |
Default web ACL action for requests that don’t match any rules
[ Default action ] で Block を選択し [ Next ] をクリックします。
Set rule priority
test-rule にチェックを選択し [ Next ] クリックします。
Configure metrics
Amazon CloudWatch metrics と Request sampling options は、それぞれ利用するならば適宜チェックを入れ [ Next ] をクリックします。
CloudFront作成
最後にCloudFrontを作成します。
画面上部検索窓 [ CloudFront ] で検索 → 当該サービスをクリック → 左ペインの [ ディストリビューション ] → [ ディストリビューションを作成 ] をクリックします。
次画面で以下のとおりに設定し、画面下部の [ ディストリビューションを作成 ] をクリックします。明記していないものはデフォルトのままでOKです。
オリジン
項目 | 値 | 備考 |
---|---|---|
オリジンドメイン | 作成したALBのドメイン | 自動で候補が表示されます |
カスタムヘッダー ヘッダ名 | X-Test-Token | [ ヘッダーを追加 ] をクリックして表示します |
カスタムヘッダー ヘッダ値 | test1234 | [ ヘッダーを追加 ] をクリックして表示します |
設定
項目 | 値 | 備考 |
---|---|---|
AWS WAF ウェブ ACL | test-acl | 作成したACLです。自動で候補が表示されます |
テスト
これで構築完了したのでCurlコマンドで、それぞれのポイントにアクセスしてみます。
EC2へリクエスト
まずEC2への直接アクセスはタイムアウトとなります。
% curl -m 2 -w '%{http_code}\n' http://xxxxxxx.ap-northeast-1.compute.amazonaws.com
000
curl: (28) Connection timed out after 2000 milliseconds
%
ALBへリクエスト
ALBへのアクセスはヘッダのX-Test-Token がない場合や、値が間違っている(今回は、test1234 以外)場合、404となります。
% curl -m 2 -w '%{http_code}\n' http://xxxxxxx.ap-northeast-1.elb.amazonaws.com/
Not Found404
%
% curl -m 2 -w '%{http_code}\n' -H 'X-Test-Token:testoreore' http://xxxxxx.ap-northeast-1.elb.amazonaws.com/
Not Found404
%
%
### ヘッダを正常に指定すればOK
% curl -m 2 -w '%{http_code}\n' -H 'X-Test-Token:test1234' http://xxxxxx.ap-northeast-1.elb.amazonaws.com/
Hello World.
200
%
CloudFrontへリクエスト
CloudFrontへのアクセスは許可IPではない場合、403でCloudFrontデフォルトのエラー画面が表示されます。
% curl -m 2 -w '%{http_code}\n' https://xxxxxx.cloudfront.net/
....
Generated by cloudfront (CloudFront)
Request ID: xxxxxxxxxyyyyyyyyyzzzzzzzz==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>403
%
%
### 許可IPの端末からのリクエストであればOK. 成功レスポンス。
% curl -m 2 -w '%{http_code}\n' https://xxxxxx.cloudfront.net/
Hello World.
200
%
Tips
CloudFrontのIPレンジはこちらで確認できます。
のでALBのリスナールール(やWAF)を利用すればCloudFront〜ALB間はIP制限はできそう。
(Terraform ではこちらのタイプを使用することでIPレンジを取得できます。)
だがこのIPレンジが固定とは特に書いてないので変動があった場合、事故る可能性があるので、今回のような、ヘッダへのTokenもどきセットが無難でしょうか。。。
今回は以上です〜ノシ
参考
〃 ̄∇)ゞアリガトォーーーーーーーーーーーーーーー♪
AWS WAFV2でIPアドレス制限してみた
CloudFront専用のALBをリクエストルーティングで設定してみた
CloudFront エッジサーバーの場所と IP アドレス範囲
AWS WAF