CloudFront専用のALBをリクエストルーティングで設定してみた

ALBに新機能が登場し、高度なリクエストルーティングが可能になりました!! 従来のホストヘッダー、パスパターンに加えて、HTTPヘッダーとメソッド、クエリ文字列、および送信元IPアドレスによる制御が可能になります!
2019.03.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

AWSチームのすずきです。

ALBの高度なリクエストルーティング を利用して、CloudFront、CDNを経由しない、ELBへの直リクエストを禁止したALBを設定する機会がありましたので、紹介させていただきます。

https://dev.classmethod.jp/cloud/aws/advanced-request-routing-for-alb/

ELB設定

デフォルトルールの編集

設定対象のALBを選択、「リスナー」のタブより「ルールの表示/編集」より設定を行います。

「デフォルトアクション」 のルールを変更します。

デフォルトアクションとして以下を設定しました

  • 固定レスポンスを返す
  • レスポンスコード: 403
  • Content-Type: text/plain;
  • レスポンス本文: Not authorized CloudFront access.

カスタムルールの追加

アクセスを許可(ターゲットへの転送)を許可する、新しいルールを追加します。

ルールの条件として、「HTTPヘッダ」「HTTPリクエストメソッド」「クエリ文字列」「送信元IP」の指定が可能になりました。

今回、特定のCloudFrontディストリビューション(ユーザエージェントと、カスタムヘッダ(x-pre-shared-key)で判定)と、 管理端末(許可IPアドレス)のみ、許可する設定を行いました。

ルール1

  • HTTPヘッダー User-agentAmazon CloudFront
  • HTTPヘッダー x-pre-shared-keysesame-ouvre-toi

ルール2

  • 送信元 IP が x.x.x.x/32(管理端末のIP)

CloudFront 設定

アクセスを許可するCloudFrontディストリビューションのOrigin 設定として、ALBルールに対応するカスタムヘッダーを追加しました。

今回、ELBのデフォルトDNS名を利用するため、Origin Protocol Policy はHTTPとしましたが、実環境では第三者に不正参照されないHTTPSとする事。 また、アクセス許可に利用するカスタムヘッダも推測されにくい文字列とする事をおすすめします。

動作確認

CloudFrontを経由したリクエストが正常応答し、ELB直接のリクエストは拒否される事を確認できました。

CloudFront

ALB

  • 許可IP以外

  • 403 Forbidden 応答が戻されている事が確認できました。
$ curl -v http://alb03-0000000000.ap-northeast-1.elb.amazonaws.com/
*   Trying 54.xx.xx.xx...
* TCP_NODELAY set
* Connected to alb03-000000000.ap-northeast-1.elb.amazonaws.com (54.xx.xx.xx) port 80 (#0)
> GET / HTTP/1.1
> Host: alb03-000000000.ap-northeast-1.elb.amazonaws.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Server: awselb/2.0
< Date: Thu, 28 Mar 2019 05:09:46 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 33
< Connection: keep-alive
<
* Connection #0 to host alb03-000000000.ap-northeast-1.elb.amazonaws.com left intact
Not authorized CloudFront access.

リダイレクト設定

デフォルトアクション、リダイレクト設定を行う事で、ELB宛のリクエストをCloudFrontにリダイレクトさせる設定を試みました。

  • 301 Moved Permanently、指定したCloudFrontのURLにリダイレクトさせる事ができました。
$ curl -v http://alb03-000000000.ap-northeast-1.elb.amazonaws.com/main-news-stick.png
*   Trying 54.xx.xx.xx...
* TCP_NODELAY set
* Connected to alb03-000000000.ap-northeast-1.elb.amazonaws.com (54.xx.xx.xx) port 80 (#0)
> GET /main-news-stick.png HTTP/1.1
> Host: alb03-000000000.ap-northeast-1.elb.amazonaws.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: awselb/2.0
< Date: Thu, 28 Mar 2019 05:05:04 GMT
< Content-Type: text/html
< Content-Length: 150
< Connection: keep-alive
< Location: https://54.d23xxxxxxxxxx.cloudfront.net:443/main-news-stick.png
<
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
</body>
</html>
* Connection #0 to host alb03-000000000.ap-northeast-1.elb.amazonaws.com left intact

ELB配下のEC2(httpd)によるリダイレクトなどで、意図せずELBにアクセスしたユーザを CloudFrontの正規URLに誘導する事が可能です。

まとめ

CloudFront経由のアクセスのみを許可、ELBへの直接参照を禁止する設定、 これまでもAWS WAFなどを利用する事で実現可能でしたが、ALBのリクエストルーティングでも設定可能になりました。

AWS WAFを利用してCloudFrontのELBオリジンへ直接アクセスを制限してみた

ALBのリクエストルーティング、利用できるルールや件数に制限がありますが、 その制限に収まるシンプルなアクセス制御を実施する場合には、活用頂ければと思います。

Limits for Your Application Load Balancers