最終更新日付: 2020年10月17日
Cloudfront(AWSのCDN)を利用して、
User(Google) → Cloudfront → ALB → EC2
のウェブサーバー構成は良くある構成だと思います。
このCloudfrontを用いた構成時に、Googleとかの検索エンジンから重複コンテンツ(CloudfrontアクセスとALBアクセスで)と認識されない対策のために、ALBへ直接アクセスした時にコンテンツを表示させない制限をする良い手はないのでしょうか?
レジュメ
環境・前提条件
User(Google) → Cloudfront → ALB
のCloudfront構成で確認しました。
CloudfrontのソースIPアドレスは複数あり不確定のため、ALBのSGではソースIPアドレスによるインバウンドアクセス制限が出来ない前提です。
結論、HTTPヘッダーを利用してALBへのアクセス制限をかける方法があるよ
ただし、この方法はいくらでも設定の選択肢がありますので、サンプルとして紹介します。
目的は、一般ユーザーやGoogle検索エンジンのクロールからのALBアクセスでコンテンツを表示させないことにあります。
方法1:Hostヘッダーで制限する
HTTPのHostヘッダーが正規の唯一のFQDN(上の絵の場合、www.putise.com)でアクセスしに来ているものだけ、ALBはコンテンツを返す設定にする。
この場合、
- ALBのFQDNでアクセスしに来てもアクセスできない(コンテンツを返さない)
ただし - 「正規のFQDN=ALB IPアドレス」でPCのhostsファイルに書かれアクセスしてきた場合はALBはコンテンツを返す
Cloudfrontの設定:Hostヘッダーをホワイトリストに加える
Cloudfrontの「Behavior」(動作・挙動という意味)を「Edit」し、
- 「Cache Based on Selected Request Headers」を「Whitelist」を選び
- 「Whitelist Headers」に「Host」ヘッダーをaddする※
※Cloudfrontはデフォルトでは、Hostヘッダーを「Origin Domain Name」(今回の構成ではALBのFQDN)に書き換えてしまいます。WhitelistにHostヘッダーを加えることにより、「Hostヘッダーを書換えない」設定をしています。
ALBの設定:リスナーのルールでホストヘッダー条件を加える
ALB(ロードバランサー)の「リスナー」タブから該当リスナーの「ルールの表示/編集」をクリックし、上記画面のようにホストヘッダールールを追加します。
※今回の検証ではEC2を用意するのが手間でしたので、ルールの条件にヒットした場合は、特定キーワードの固定レスポンス本文を返すように設定し、動作確認しました。
補足:Cloudfront → https → ALBの場合
CloudfrontからALBヘhttps通信させたい場合は、正規のFQDNの証明書(cloudfrontと同じ)をALBにインポートする必要があります。証明書の種類が一枚で済むメリットもありますね。
またALBへのアクセスがhttpsの場合は、cloudfrontの「Cache Based on Selected Request Headers」設定は
- Whitelistか
- Allか
しか選べず、「None(Improves Caching)」(=オブジェクトをキャッシュする際に、リクエストヘッダは考慮しない。)は選べません。上の画面のようにエラーメッセージが表示されます。
To use SSL with an ELB origin, either forward all headers or whitelist the Host header. If you do not want to forward any headers, change the Origin Protocol Policy to HTTP Only.
「ALL」を選ぶとキャッシュをしなくなってしまうので、Whilelistを選びます。whitelistはホワイトリストで選択されたヘッダーの値単位でキャッシュすると理解しています。
リクエストヘッダーに基づくコンテンツのキャッシュ - Amazon CloudFront
方法2:秘密の合言葉のようなカスタムHTTPヘッダーを用意する
Cloudfrontの設定:秘密のカスタムHTTPヘッダーを設定する
Cloudfrontの「Origin」(原点・起源という意味)を「Edit」し
- Origin Custom Headersの「Header Name」を入力し
- Origin Custom Headersの「Value」を入力
秘密で決めた一般的に使われないだろうカスタムなNameとValueを設定します。
※この設定をすると、Cloudfrontを経由するとCloudfrontがこのカスタムヘッダーを付けて、Origin(今回の場合は、ALB)へHTTPリクエストを転送します。
ALBの設定:リスナーのルールでカスタムHTTPヘッダー条件を加える
ALB(ロードバランサー)の「リスナー」タブから該当リスナーの「ルールの表示/編集」をクリックし、上記画面のようにHTTPヘッダールールを追加します。
※今回の検証ではEC2を用意するのが手間でしたので、ルールの条件にヒットした場合は、特定キーワードの固定レスポンス本文を返すように設定し、動作確認しました。
オススメしない設定:User-agentやX-Forwarded-Forによるヘッダー制限
例えば、上記のように
- Cloudfrontが自動で付加してくれるHTTPヘッダー「x-forwarded-for」でALBルールを作るとか
- Cloudfrontが自動書換えるHTTPヘッダー「User-agent=Amazon CloudFront」でALBルールを作るとか
も出来ます。
- 前者は、万万が一リバースproxyサーバーを建てられてしまいますとコンテンツを一般公開に表示させてしまいますし(そんな事をする人はほぼ無いと思いますが)
- 後者は、AWSの仕様が突然変わってしまいUser-agentが「Amazon CloudFront」でなくなってしまう可能性もゼロではありません
なので、この二つのHTTPヘッダーでも簡単にALBアクセス制限は出来ますが、あまりお勧めしません。
運用者・開発者の送信元IPアドレスだけ切り分け用にALBがコンテンツを返すルールも設定可能
上記のHTTPヘッダーを利用してALBへのアクセス制限をかける方法に加え、
送信元IPアドレスを条件にしたルールも作成sることにより、管理者や開発者は無条件に(カスタムHTTPヘッダーやHostヘッダーが無くても)動作確認用にALBがコンテンツを返すようなルールも作っておくと便利かもしれませんね。
カスタムHTTPヘッダーでALBアクセス出来る動作確認方法
今、試しにALBのルールの設定を上記のように設定したとします。
この状態で、HTTP ヘッダー x-forwarded-for を使用してアクセス出来る事を確認したいとした場合、「Postman」というツールが動作確認に役に立ちます。
Webシステムにオススメ動作確認ツール「Postman」
PostmanはPostmanアカウントorGoogleアカウントのサインインを求められますが、アカウントが無くても使えます(サインイン画面を「×」で閉じてください)。
- まずは、ALBのURLを入力します。
- 次に、「Headers」をクリックし、HeadersにカスタムHTTPヘッダーの「KEY」と「VALUE」を入力し、この状態で青色の「Send」を押します。
すると、Bodyに結果の固定レスポンス本文が帰ってきます。今回は想定通り「x-forwarded-for」という文字列が帰ってきていますので、ALBの一個目のルールがヒットしたことがわかります。
※この結果より、ALBのルールのカスタムHTTPヘッダーの「値」は「*」アスタリスクのワイルドカードが使用出来ることがわかりました。