AWS

AWS CloudFront 〜 ALB 〜 Webサーバ間で一連のアクセス制限を行う CFはIP制限 & ALBはCF経由のアクセスのみ許可 & サーバはALB経由のみ許可

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

CloudFront〜ALB〜Webサーバのインフラ構成図

【クライアント〜CloudFront間】
CDNはどこからでも高速にアクセスできるぜことが売りの一つではありますが、開発環境のみアクセス制限をかけたいことがあると思います。

アクセス制限には、クエリに特定の文字が含まれてることや、リクエスト送信元の国 など様々な方法で縛ることができます。

今回はWAFを使用して社内IPのみ許可します。


【CloudFront〜ALB間】
ALBへ直接アクセスすることを禁止します。

HTTPヘッダにCloudFrontで設定したTokenもどきの文字列があるときのみ許可します。


【ALB〜Webサーバ(EC2)間】
Webサーバへ直接アクセスすることを禁止します。

セキュリティグループでALB経由のアクセスのみ許可します。

スポンサーリンク

構築手順

セキュリティグループ作成

EC2とALBにそれぞれ割り当てるセキュリティグループを作成します。
基本的な手順は、こちらの記事のセキュリティグループ作成 を参考にしてください。

ALB用セキュリティグループ作成

HTTP80番ポートをALL解放 で作成します。

AWSマネジメントコンソールのインバウンドルール設定画面


EC2用セキュリティグループ作成

HTTP80番ポートのソースに、上記で作成したALB用セキュリティグループ自体(少し変に感じるかもしれませんが)を指定します。

カスタムを選択するとセキュリティグループの候補が自動的に表示されます

AWSマネジメントコンソールのインバウンドルール設定画面

EC2 作成

最終的なアクセス先となるWebサーバを作成します。

基本的な手順は、こちらの記事のEC2作成 を参考にしてください。

当該手順の ステップ 6: セキュリティグループの設定 で、今回作成した、EC2用セキュリティグループ を割り当てください。

ALB 作成

ALB(アプリケーションロードバランサー)を作成します。

ベースとなるALBの作成

基本的な手順は、こちらの記事のロードバランサー作成 を参考にしてください。

当該手順の セキュリティグループの割り当て で、今回作成したALB用のセキュリティグループを割り当てください。


リスナールール設定

今回はそれに加えてリスナールールを設定します。

左ペイン [ ロードバランサー ] → [ リスナータブ ] → [ ルールの表示/編集 ] をクリックします。

AWSマネジメントコンソールのロードバランサー設定画面


アクセス制限のルールを追加

次の画面で、画面上部の [ ] アイコン → [ ルールの挿入 ] をクリックします。

[ IF(すべてに一致) ] → [ 条件の追加 ] → [ HTTPヘッダー ] を選択し、header typeに X-Test-Token 、値に test1234 を入力します。

[ THEN ] → [ アクションの追加 ] → [ 転送先 ] を選択し、今回作成したEC2を選択します。

上記設定したら画面上部の [ 保存 ] ボタンを押します。

デフォルト動作の変更

次に、画面上部の [ えんぴつ ] アイコン → [ HTTP 80: デフォルトアクション ] の左の[ えんぴつ ] アイコン をクリックします。

[ THEN ] → [ 転送先 ] の [ ゴミ箱 ] アイコンクリック → [ アクションの追加 ] → [ 固定レスポンスを返す ] → [ レスポンスコード ] に 404 を入力します。

上記設定したら画面上部の [ 更新 ] ボタンを押します。


最終的に、以下のようになっていればOKです。

AWSマネジメントコンソールのリスナールール設定画面


WAF作成

CloudFrontにIP制限をかけるWAFを作成します。

まずIP Setsを作成しそれをACLに割り当てる流れですすめます。

IP sets 作成

まずアクセスを許可するIPリストを定義します。

画面上部検索窓 [ WAF ] で検索 → 当該サービスをクリック → 左ペインの [ IP sets ] をクリック → プルダウンで [ Global(CloudFront)]を選択 → [ Create IP set ] をクリックします。

AWSマネジメントコンソールのWAF設定画面


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

AWSマネジメントコンソールのWAF設定画面

Web ACLs 作成

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

AWSマネジメントコンソールのWAF ACL設定画面
Describe web ACL and associate it to AWS resources

以下を入力し、Associated AWS resources – optional は特に何も選択せず [ Next ] をクリックします。


【Web ACL details】

項目
Nametest-acl
CloudWatch metric nametest-acl
Resource typeCloudFront distributions
Region自動的に Global(CloudFront) が選択される
Add rules and rule groups

【Rules】
Add my own rules and rule group を選択します。

AWSマネジメントコンソールのWAF ACL設定画面

【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
ActionAllow


【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を作成します。

ここで今までに作成したWAF、ALBを割り当てます。


画面上部検索窓 [ CloudFront ] で検索 → 当該サービスをクリック → 左ペインの [ ディストリビューション ]  →  [ ディストリビューションを作成 ] をクリックします。

次画面にて、以下を入力します。これ以外は(今回は)すべてデフォルトのままで大丈夫です。

【オリジン】

項目備考
オリジンドメイン 作成したALBのドメイン自動で候補が表示されます
カスタムヘッダー
ヘッダ名
X-Test-Token[ ヘッダーを追加 ] をクリックして表示します
カスタムヘッダー
ヘッダ名
test1234[ ヘッダーを追加 ] をクリックして表示します


【設定】

項目備考
AWS WAF ウェブ ACLtest-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
% 

余談

CloudFrontのIPレンジはこちらで確認できます。

のでALBのリスナールール(やWAF)を利用すればCloudFront〜ALB間はIP制限はできそう。
(Terraform ではこちらのタイプを使用することでIPレンジを取得できます。)

だがこのIPレンジが固定とは特に書いてないので変動があった場合、事故る可能性があるので、今回のような、ヘッダへのTokenもどきセットが無難でしょうか。。。

今回は以上です〜ノシ

参考

〃 ̄∇)ゞアリガトォーーーーーーーーーーーーーーー♪

AWS WAFV2でIPアドレス制限してみた
CloudFront専用のALBをリクエストルーティングで設定してみた
CloudFront エッジサーバーの場所と IP アドレス範囲
AWS WAF

関連書籍

更新履歴

  • 2021.07.18 WAF作成の最初のサービス検索手順を追記
  • 2021.08.16 CloudFrontコンソール画面のUI更新を反映、全面的にレイアウトを改善