はじめに
この記事は、実務未経験者がロールプレイング形式でアーキテクチャの設計、構築を行うといった記事です。
よろしければ<準備編><アーキテクチャ設計編><VPC、ELB編>もご覧くださいませ。
Cloudfront編
ディストリビューションの作成
Cloudfrontを使用してエッジロケーションからサービスを配信します。
エッジロケーションにキャッシングを行う事でコンテンツを、ユーザーに最も近いサーバーから配信できますので、ネットワークレイテンシの低減やオリジンサーバーの負荷軽減を行う事ができます。
ELBなど動的コンテンツオリジンにする場合はどれをキャッシュして、どれをキャッシュさせないのかを検討する必要があります。
今回はとりあえずキャッシングを行わない方針でCloudfrontを導入していきます。
ちなみにキャッシュしない CloudFront は CDN 本来の「エッジサーバにコンテンツをキャッシュし高速に配信する」というメリットはありませんが、それでも導入するメリットは結構あります。
- HTTP/2 や IPv6、gzip 圧縮といった技術要素を手軽に導入できる
- DDoS 対策に一定の効果がある
- パス毎にオリジンを変える事ができる
- Amazon WAFを手軽に使える
- 単一リージョンで世界中にサービス展開しているような構成だとレイテンシ改善が期待できる
- CloudFront のエッジは世界中に 50 以上あり、最も近いエッジサーバに誘導されるから
- CloudFront のエッジサーバからオリジンサーバへのリクエストは AWS の太いバックボーンを通るから
などなど
実際にCloudfrontでキャッシングさせない方針で導入しているサービスも結構見られます。(Amazon WAFを利用したいからという理由で導入するケースも結構多い気がします)
では実際にCloudfrontの設定を行なっていきましょう!
マネジメントコンールの「Cloudfront」→「Create Distribution」に進んでください。
Webの方の「Get Started」をクリック
Cloudfrontは未だに日本後対応してないんですよねー
結構設定項目が多いので、早く対応して欲しいです
Origin Settings
「Origin Domain Name」は前回作成したALBを指定してください。
「Origin Path」はコンテンツをおいているパスを指定してください。
ApacheのDocumentRootを変更しているので一旦デフォルトのままでいきます
「Origin Protocol Policy」は
- HTTP Only
- HTTPのみ許可
- HTTPS Only
- HTTPSのみ許可
- Match Viewer
- どっちも許可
から選べます。 後ほど変更もできますので、とりあえずMatch Viewerを選んでおきます。
- Origin Connection Attempts
- オリジンへの接続を試行する回数
- Origin Connection Timeout
- オリジンへの接続を確立しようとするときにCloudFrontが待機する時間
- Origin Response Timeout
- CloudFrontがカスタムオリジンからの応答を待機する時間
- Origin Keep-alive Timeout
- CloudFrontが接続を閉じる前にカスタムオリジンサーバーとのアイドル接続を維持する時間
の設定項目もとりあえずデフォルトでいいかと思います。
処理に時間かかったり、読み込みが遅いコンテンツの場合はここを変更するといいでしょう
- Origin Custom Headers
Cloudfrontを通過するときに好きなヘッダー、値を追加する事ができます。
アクセス制限をしたりする場合によく使いますね。
後ほど設定しますので一旦スルー
Default Cache Behavior Settings
こちらの項目は別途変更を行うので、一旦スルーします
Distribution Settings
「Price Class」
はどこの地域のエッジロケーションを利用するか指定する事が出来ます。
コストを抑えたいときはここを設定してください。
「AWS WAF Web ACL」
後ほどWeb ACLを作成しますので一旦スルー
「Alternate Domain Names」
「SSL Certificate」
ドメインを指定出来ます。後ほど設定しますので一旦スルー
ちなみに設定を行わない場合はデフォルトのドメイン名になります。(デフォルトのドメイン名でもHTTPS化出来ます)
djfaeihfa3eji22.cloudfront.net
みたいな感じですね
残りの項目はCloudfrontのログの設定です。
こちらも後ほど設定していきますので一旦スルーで大丈夫です。
Cloudfrontは世界に200以上のエッジロケーションがあるので、一回設定を変更すると結構時間かかります。
Behaviorsの設定
Statusが「In Progress」の状態でも変更を行えますので、先ほど作成したディストリビューションを指定してオリジンの詳細設定を行いましょう。
「Behaviors」のタブを選択してください。
現時点では全てのパスが先ほど作成したオリジンにアクセスするように設定されてます。
リストを追加する事ができ、複数ある場合は上から順に適用されます。
Default (*)はどのパスでも当てはまらない場合にアクセスするといったものです。
ELBなどで動的コンテンツをオリジンとして指定する場合は
→Default ()はキャッシュさせて、その他のリストはキャッシュさせる
→Default ()はキャッシュさせず、その他のリストはキャッシュさせる
の2種類の方法を取る事ができます。
キャッシュさせない場合
まずはキャッシュさせない場合はこちらの設定で大丈夫です。
Minimum TTL、Maximum TTL、Default TTLは「Cache Based on Selected Request Headers」をALLに設定すると自動的に0になります。
項目 | 設定値 |
---|---|
Allowed HTTP Methods | GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE |
Cache Based on Selected Request Headers | ALL |
Minimum TTL | 0 |
Maximum TTL | 0 |
Default TTL | 0 |
Forward Cookies | ALL |
Query String Forwarding and Caching | Forward all,cache based on all |
その他はデフォルトで大丈夫です。
キャッシュさせる場合
項目 | 設定値 |
---|---|
Allowed HTTP Methods | GET, HEAD |
Cache Based on Selected Request Headers | WhiteListにて必要なHeaderを追加(ALLにするとTTLが0に設定されます) |
Minimum TTL | 0 |
Maximum TTL | お好みのTTL |
Default TTL | お好みのTTL |
Forward Cookies | None or whitelist (ALLにするとキャッシュされないので注意) |
Query String Forwarding and Caching | Forward all,cache based on all |
「Cache Based on Selected Request Headers」
でよく追加するヘッダーについて紹介します。
Authorization
管理画面にベーシック認証を入れる時などに必要です。
CloudFront-Forwarded-Proto
Origin側へプロトコルを通知します。
Host
Origin側へアクセス先ホスト名を通知します。
コンテンツによって使用したいヘッダーを追加して下さい。
キャッシュさせる場合においても
ログイン系、管理ページ系などはキャッシュしないように設定する必要があります。
特定地域からのアクセスをブロックする
今回は日本以外からのアクセスをブロックしてみます
「ディストリビュション」→「Restrictions」→「Edit」を洗濯してください
ホワイトリスト、ブラックリスト形式を選択できます。
今回は日本のみを許可したいので、「ホワイトリスト」、「JP--JAPAN」で設定しました。
カスタムエラーレスポンスとしてSorry Pageを実装
エラーページを表示させましょう。
準備として、適当なS3バケットを作成、エラーページで使用したいファイルをアップロードしてください。
S3をCloudfrontで配信する場合、S3の静的ウェブホスティング、通常バケット、CustomOrigin(Cloudfrontで最初に設定するオリジン)の3種類があります。
- 通常バケット
- CloudFront⇔Origin間のHTTPSを自動で設定してくれる
- S3の静的ウェブホスティング
- HTTPS化出来ない
- CustomOrigin
- HTTPS化する際に自分でSSL証明書を用意する必要がある
などの違いがありますので、今回は通常バケットで用意します。
まずはS3のオリジン登録を行う為に
「Origins and Origin Groups」→「Create Origin」を選択して下さい。
先ほどと同じようにS3のドメイン選択、パスの指定を行なって下さい。
また、S3への直接アクセスを制限する為に、OAIを設定しましょう。
「Restrict Bucket Access」をYesに選択すると、OAIの設定項目が追加されます。
「Origin Access Identity」→Create a New Identity
「Grant Read Permissions on Bucket」→Yes, Update Bucket Policy
と設定すると、自動でOAIの作成、バケットポリシーにOAIのIDを追加してくれます。
後は「Behaviors」の設定を行なって、先ほど作成したオリジンを追加して下さい。
キャッシュに関してはエラーページで設定出来ますので、こちらではキャッシュしない設定で大丈夫です。
エラーページを追加する為に「Error Pages」→「Create Custom Error Response」にて設定を行います。
注意点として、長い時間のTTLを設定すると、エラーページから戻らなくなります。
補足として、「Behaviors」でキャッシュを行う設定を行なった場合、2XX・3XXに対しては設定したTTLが反映されるのですが、
4XX・5XXに対してはデフォルトで1分間のTTLが設定されています。
もし、エラーに対するTTLの変更を行いたい場合は「Error Pages」より、各エラーに対してのTTLを設定して下さい。
CloudFrontのアクセスログをS3に収集
前回作成したログ専用のバケットを選択して下さい。
プレフィックスを設定できますので今回は「Cloudfront/」を入力します。
ログを確認してみましょう。
プレフィックスの設定通り、minamialb/Cloudfrontにログが収集されてます。
WAF
CloudFrontからのアクセスのみを許可(オリジンへの直接アクセスを禁止)
現時点では、Cloudfrontからだけではなく、オリジンのALBに対しアクセスが可能となっています。
セキュリティ対策としてWAFをCloudfrontに適用し、アクセス制限を行う場合はALBへの直接アクセスを禁止しましょう。
方法としてはALBを使う方法、WAFを使う方法が一般的ですが、今回はWAFを使ってみます。
現在WAFはWAF v2とWAF Classicがありますが、せっかくなので新しいWAF v2を選択しました。
マネジメントコンソールの「AWS WAF」→「Web ACLs」→「Create web ACL」から作成していきます。
「Regional resources」を選択して、ALBが設置されているリージョンを選択します。
その後「Add AWS resources」からWAFを適用したいALBを選択して下さい。
WAF v2では様々なマネージドルールを使用できますが、今回は「Add rules」→「Add my own rules and rule groups」からカスタムルールを作成します。
カスタムルールの設定を
項目 | 設定値 |
---|---|
Rule type | Rule builder |
Type | Regular rule |
If a request | matches the statement |
Inspect | Header |
Header field name | 任意のヘッダー |
Match type | Exactly matches strings |
String to match | 任意の文字列 |
Text transformation | None |
Action | Allow |
の様にして下さい
「Header field name」
「String to match」
に関しては、Cloudfrontの「カスタムオリジンヘッダー」の設定よりヘッダーを追加します。
セキュリティの為、なるべく予測されにくいヘッダーの作成を行って下さい
最後に
「Default web ACL action for requests that don't match any rules」をBlockに
カスタムルールの「Action」をAllowにする事で、ルールに対応する場合のみアクセス許可をする事ができます。
WAFの方では設定完了ですので、Cloudfrontの設定より、「カスタムオリジンヘッダー」を追加していきましょう。
「Origins」の設定画面から、ALBを選択します。
「Origin Custom Headers」より先ほど設定したヘッダーの名前、値を入力して下さい。
注意 今回はテストの為「test」という文字列にしていますが、実際に運用する場合はセキュリティの面から予想されにくいヘッダー名、値にして下さい。
実際にALBのDNS名からアクセスすると「403 forbidden」が表示されるかと思います。
Web ACLの設定
最後に
参考
「キャッシュさせないCloudFrontディストリビューションを設定してみた(CloudFormationテンプレート付)」
https://dev.classmethod.jp/articles/create-no-cached-cloudfront-distribution/
「Amazon Athena で CloudFront のアクセスログを集計する」
https://dev.classmethod.jp/articles/athena-cloudfront-log-activity/
「Athena で CloudFront ログ解析」
https://qiita.com/ytanaka3/items/ad5e7d96bc425ff4c843
「キャッシュしない CloudFront とそのメリット・デメリット」
https://blog.manabusakai.com/2016/11/no-cache-cloudfront/
「AWS Cloudfrontの地域制限機能を使って特定地域からのアクセスを遮断する」
https://beyondjapan.com/blog/2016/09/aws-cloudfront-specificarea-blocking/
「CloudFrontを利用してオリジンサーバー障害時にS3上のコンテンツを表示する」
https://dev.classmethod.jp/articles/cloudfront-sorry-s3/
「CloudFrontのCustom Error Responseを利用して、S3上にあるSorryページを表示する」
https://dev.classmethod.jp/articles/cloudfront_customerrorresponse_s3/
「CloudFront および Lambda@Edge のメトリクスの表示」
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html
「AWS WAFを利用してCloudFrontのELBオリジンへ直接アクセスを制限してみた」
https://dev.classmethod.jp/articles/restrict-elb-origin-awswaf/
「いますぐ使う CloudFront」
https://qiita.com/sasasin/items/0f0ec1a90af6295589f9
「AWS CloudFrontで極力キャッシュさせたくない時の話」
https://qiita.com/shogomuranushi/items/a2367350ea54a8f41257