⚠️ 記事内に広告を含みます。

CloudfrontとS3で静的サイトを公開する全ての方法

CloudfrontとS3で静的サイトを公開する全ての方法

クラウドフロントはAWSが提供するCDNサービスです。

CDNはオリジンサーバに代わってユーザにデータを配信するサービスでオリジンに負荷をかけることなく、世界のユーザからのアクセスを大量に捌くことができます。

CloudFrontを理解する

CloudFront(CF)はAWSが提供するCDNのサービス名です。

CDNは下図のようにユーザからのアクセスに対してオリジンとなるwebサーバ等の代わりにデータを返却するキャッシュサーバの役割があります。

CloudFrontで登場する専門?用語がたくさんあって理解しにくいと思うのでざっとここで紹介します。ここでは主にCloudFrontで登場する用語で他のサービスではまた名前が違っているものがありますがご容赦ください。

  1. オリジン
    • CDNで配信するコンテンツ(webページ、動画像)を所持している場所(S3やwebサーバ等)
  2. キャッシュサーバ
    • オリジンが持つコンテンツを一時的に保存(キャッシュ)して代わりに配信するサーバ。クラウドフロントもその一つ
  3. CDN (content delivery network)
    • 様々な場所に存在する複数のキャッシュサーバネットワークからユーザにコンテンツを配信するサービスでCloudFrontやAzure CDN, CloudFlare CDN, Akamai CDNなどが代表的
  4. ビューワ
    • CloudFrontにアクセスするユーザのことビューワリクエストはユーザからのCFへのリクエストを指す。ビューワプロトコルポリシーなど多くの単語がある。
  5. ポリシー
    • 大雑把に言えば設定。主に許可・不許可や含む・含まないなどの設定が記述された集合体をポリシーと呼ぶ。
      ポリシーは複数の環境にまたがって流用、適用できるので新しいCloudFrontディストリビューションを用意したときに一から設定し直さなくても済む。
      マネージドポリシーはAWSが用意してくれているポリシーで気に食わなければカスタムポリシーで好みのポリシーを作成することも可能
  6. ディストリビューション
    • Cloudfrontの作成単位。とあるwebサイトのCDNを用意する時にはディストリビューションを作成し、とある動画配信サイトを用意するときはまた別のディストリビューションを作成して配信する。
  7. ロケーション
    1. 広い意味で「位置」、地理的な場所(日本とか東京、大阪)の場合もあれば、エッジロケーションのようにCloudFrontがユーザとオリジン間の役割的にどの位置にいるか?を表わす場合もある。
  8. ビヘイビア
    1. 日本語で「ふるまい・行動」だが、CloudfrontではURL(パスパターン)の違いによる動作設定を意味する。例えば/web/ではS3オリジンでHTTPSにリダイレクト強制し、GET,HEADのみに限定して??時間キャッシュ、/adminではオリジンはEC2にするなど
  9. キャッシュキー
    • CFがキャッシュを保存する時に同一かどうかを判断する情報。基本はURL, example.com/index.htmlとexample.com/info.htmlは別のキャッシュとして保存。例えばクエリ文字列を含む場合、example.com/index.html?size=128 example.com/index.html?t=10 クエリ文字列をキャッシュキーとしない場合は同一とみなし同じキャッシュをユーザに返す。キャッシュキーとする場合は別々にキャッシュ

CDNは単にオリジンのコピーというわけではありません。

CDNの特筆すべき点は

  • 全世界にCDNの拠点(サーバ)がたくさんあって分散している
    • 大量アクセスも分散したCFが捌ける
  • ユーザから地理的に近いロケーションに接続して配信する
    • ユーザが北米、オリジンが日本でもCFは北米なら低レイテンシー・高速転送可

CloudFrontは全世界に複数のEdge Locationと呼ばれるユーザにコンテンツ配布するサーバとオリジンからデータを受け取りEdge Locationにコンテンツを渡すRegionalEdgeCacheという部分があり、効率的にコンテンツ配布するように分散化している

Edge Locationとオリジンの間にコンテンツを集約するRegional Edge cacheを挟んでいる

CloudFrontが何をもってキャッシュを利用するか?(キャッシュキー)

CloudFrontは自身が保有するキャッシュかオリジンのコンテンツどちらを返したらいいか?を決める要素がキャッシュキーと呼ばれるものです。

下の要素が同一の場合は依然と同じリクエストとみなしてキャッシュからコンテンツを返します。

  • URL
  • HTTPヘッダー
  • クエリ文字列
  • cookieパラメータ

CloudFrontではデフォルトではリクエストのホスト名とURLパス&ファイル名(クエリ文字列を含まない)です。

GET /dir1/idnex.html?querry=1021
Host: example01234.cloudfront.net

CloudFrontへのアクセス時に上記が一致した場合は同じアクセスとみなし、キャッシュがある場合はキャッシュを返します。

キャッシュキーはレガシーキャッシュでディストリビューション毎に設定してもキャッシュポリシーで定義したものを適用しても良いです。

AWS:キャッシュキーとその設定について

ヘッダーをオリジンに転送したい

オリジン側でCloudFront側がユーザから受け取ったリクエストヘッダーの中身を転送したい場合があります。ホストヘッダーをオリジンに転送するにはキャッシュキーのセッティングします。

ディストリビューションの設定でレガシーキャッシュ設定を選択して転送したいヘッダーを追加します。

キャッシュポリシーを利用する場合はCloud Frontの設定でカスタムキャッシュポリシーを作成し、キャアッシュポリシーを選択します。

ホストヘッダーをオリジンに転送: https://aws.amazon.com/jp/premiumsupport/knowledge-center/configure-cloudfront-to-forward-headers/

オリジンリクエストポリシー

オリジンの負荷低減とキャッシュヒット率の向上

Origin Shieldの利用

Origin Shieldは海外の様々な箇所からアクセスが想定される時に効果があるかもしれません。

オリジンサーバのあるリージョン(例: ap-norteast-1)に対して、北米のバージニアからアクセスが来た際は一度別リージョンのRegional Edge cacheを通ってオリジンにアクセスがくる。すなわち、キャッシュヒット率が下がり、オリジンの負荷の上昇につながります。

別のエッジロケーションから来た場合はそのリージョンのRegional Edge cacheがオリジンからコンテンツを取得・キャッシュする必要があるのでオリジンにアクセスが来てしまう。

  • 日本ユーザ→Edge Location → Regional Edge cache(JP)→ オリジン
    • よくアクセスがあるのでキャッシュされている
  • 北米ユーザ→Edge Location → Regional Edge cache(US) → オリジン
    • 別リージョンなのでキャッシュをオリジンに取りに来てしまう

ここでOrigin Shieldを使用するとUSのRegional Edge CacheはオリジンではなくOrigin Shieldに取りにくいく。

  • 日本ユーザ→Edge Location → Regional Edge cache(JP) → origin shield (世界共通) → オリジン
  • 北米ユーザ→Edge Location → Regional Edge cache(US) → origin shield (世界共通) → オリジン
origin shieldがさらに間に入って各Regional Edge Cacheに配布する

Cloudfrontの各種設定

cloudfrontの設定は大まかに分けて

  • オリジンの設定
    • CFで配信したいコンテンツを持っている大元の部分を指定する設定
  • ビヘイビアの設定
    • CFへのアクセス関係の設定,キャッシュの設定等
  • CloudFront一般の設定(came, SSL, プロトコル)

の3つあります。

オリジンの設定

S3をオリジンとして設定する場合は大きく1.Publicアクセス有効 or 2.無効の2択あります。

  • Publicアクセス有効化のS3をオリジンにする
    • 静的ウェブサイトホスティングのエンドポイントを指定(???.s3-website-ap-northeast-1.amazonaws.com)
    • Publicアクセスを有効化したS3バケットを指定
  • Publicアクセスの無効のS3をオリジンにする
    • OAC (origin access control)を使用 (推奨)
    • OAI (origin access Identities)を使用 (従来法)

Publicアクセスを有効化すると下図のようにCF経由だけでなく、S3直接のアクセスも許可されます。
通常の運用では「S3へのアクセスをCF経由のみに限定したい」が多いと思うので、publicアクセスを無効化して、CF経由のみを許可、S3直は不可にします。

S3直のアクセスが来てしまう

S3のpublicアクセス無効化の場合、オリジンのアクセス制御にOACかOAIを利用しますが、新しいOACを使用するのが推奨です。

  • Origin Access Control (OAC)
  • Origin Access Identity (OAI) →非推奨

Origin Access Control (OAC)について少し解説

OAIとOACはどちらも CF経由のアクセスのみに限定するための設定です。

新登場のOACはOAIの上位互換です。

  • OAIは非推奨(そのうち消える)
  • AWS KMS(暗号化)をサポート
  • S3へのPOSTやPUTに対応

OACについて:https://aws.amazon.com/jp/blogs/news/amazon-cloudfront-introduces-origin-access-control-oac/

OACを使用した場合のフローはCFからS3オリジンへのアクセスが発生した際にOAC署名プロトコルを使用して

  1. リクエストに署名しない
  2. リクエストに署名する
  3. リクエストに署名するが認証ヘッダーを上書きしない

の3つのフローが選択できます。

OACを適用するS3のバケットは静的ウェブサイトホスティングを有効化したバケットではなく通常のバケットである必要があります。

ビヘイビアの設定

ビヘイビアは「各URLパスキャッシュ動作の設定」を行います。

URLのパスによってオリジンを何にするか?キャッシュするか?しないか?と各々で設定できます。

デフォルトでは全てのパスパターン(*)に対して同じ挙動をするように設定されています。ビヘイビアには優先順位があり、数字が若い(0にちかい)ほど優先されます。

下図では/music, admin, imagesのパスを指定して、オリジンを変更したり、キャッシュ時間・キャッシュ無効の設定を入れています。これらのパスに当てはまらないアクセスは全てデフォルト(*)の設定が適用されます。

/musicのパスは*を含まないため、/music/info.htmlのアクセスはデフォルトのビヘイビア設定が適用されます。

/images/のサブディレクトリ、/images/2022/extra.pngの設定は/images/*.pngの設定が適用されます。*は0 個以上の文字に一致するので、サブディレクトリを指定したい場合は「/images/2022/*.png」のようなパスパターンを追加するか、複数ある場合は?(任意の一文字)を使って「/image/20??/*.png」のように指定します。

細かい設定についてAWSのドキュメントを参照してください

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesCacheBehavior

https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudfront-not-following-cache-behavior/

CloudFront一般の設定

ディストリビューションの一般タブから設定できる一般の設定です。

  1. 料金クラス
    • 3つの料金クラス(All, 200, 100)がある。利用するエッジロケーションが変わる。Allと200に日本のエッジロケーションは含まれている。200にすると南米やオセアニアが除外され、それらの地域には別の地域のエッジロケーションから配信されるため該当地域はレイテンシが増加する可能性があるが、これらの地域は料金単価では請求されない(日本だとオーストラリアが若干高いくらいでメリットはあまりない)米国が安いのでレイテンシが気にならなければ100に変更してもよいかも?
  2. AWS WAF ウェブ ACL
    • AWS WAFを設定している場合はこちらを選択
  3. 代替ドメイン名(CNAME)
    • ドメイン設定を行う
  4. カスタムSSL証明書
    • 設定したドメインの証明書を設定(ACM経由)
  5. HTTPバージョン
    • HTTP2,3をサポートするか?
  6. デフォルトルールオブジェクト
    1. /にアクセスが来たときに何を返すか? index.htmlなどにする
  7. 標準ログ記録
    • S3バケットにログ出力する場合設定
  8. IPv6
    • 後述しますがIP制限を入れる場合はオフにしとくと良い

CloudFront + S3で静的サイトを公開する方法

CloudFront + S3配信の設定方法として以下4つを上げる。基本的にはOACの方法が推奨

  • Publicアクセス有効化のS3をオリジンにする
    • 静的ウェブサイトホスティングのエンドポイントを指定(???.s3-website-ap-northeast-1.amazonaws.com)
    • Publicアクセスを有効化したS3バケットを指定
  • Publicアクセスの無効のS3をオリジンにする
    • OAC (origin access control)を使用 (推奨)
    • OAI (origin access Identities)を使用 (従来法)

OACを利用した方法 (推奨)

1. AWSマネジメントコンソールでCloudFrontを選択します
2. ディストリビューション → 「ディストリビューションを作成」をクリック
3. オリジンドメインに公開したい S3バケットを選択(パブリック公開/静的ウェブサイトホスティングは不要)
4. S3バケットアクセスで「Origin access control settings (recommended)」を選択(図1)
5. Origin access controlでコントロール設定を作成をクリック(図1)

図.1オリジンの設定でOACを選択

6.任意の名前を設定し、署名動作を選択します。理由がなければデフォルトの署名リクエスト(推奨)を選択します。

  1. 署名リクエスト(推奨)
    1. CFは S3オリジンへの送信に署名をして認証ヘッダーに追加する。受信したS3は署名の検証を行い一致すればリクエストを処理する。CFへのリクエスト時に既に認証ヘッダーがある場合は上書きして署名してオリジンに送信する
  2. 認証ヘッダーを上書きしない(オプション)
    1. CFは既に認証ヘッダーがある際は署名で上書きしない。クライアント側で署名できるような場合はCFが新たに署名せずに、キャッシュポリシーの設定でクライアントの認証ヘッダーがオリジンに転送されるように設定する必要がある。
  3. リクエストに署名しない
    1. CFは署名せず、OACを利用しません。クライアント側で署名をする

7.残りの設定(デフォルトルートオブジェクトはindex.htmlにしておく)が完了したらデストリビューションを作成します。
8.ディストリビューションを設定したら S3に適用するポリシーが出てきます。

ポリシーをコピーを選択

“Action”: “s3:GetObject”とGetObjectのみが有効になっているのでPUTなどが必要であればそれをActionに追加する。

9. cluodfront.netのドメインにアクセスするか、CNAMEで登録したドメインにアクセスしてページが表示されば設定完了

OAIでCloudfront-S3間のアクセス制御を行う

1. ディストリビューションを作成、 S3バケットを選択する(静的ウェブサイトエンドポイントは選択しないので有効化の必要もない)
2. 「Legacy access identities」を選択、新しいOAIを作成する。
3.バケットポリシーを自動で更新するを選択し、他の設定を行いデプロイする。静的ウェブサイトホスティング設定ではないので、デフォルトルートオブジェクトをindex.htmlにしておく。(ドメイン名でアクセスしたらindex.htmlを見に行くように設定)

↓ のようなポリシーが S3バケットに追加されている。手動の場合は自分で追加

{
    "Version": "2012-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EH1HDMB1FH2TC"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::examplebacket/*"
        }
    ]
}

S3へのパブリックアクセスを許可して設定する

パブリックアクセスを許可したS3バケットをオリジンに設定します。

S3で直接静的サイトホスティングを行う設定をしていればパブリックアクセスを許可にする設定がされているはずです。

AWS:ウェブサイトアクセスのアクセス許可の設定

静的ウェブサイトエンドポイントをオリジンに設定する

静的ウェブサイトエンドポイントはHTTPのみ対応のためCF – S3間はHTTP通信に限定されます。

設定方法:

1. 静的ウェブサイトホスティング・パブリックアクセスを有効化した S3バケットを用意し、静的ウェブサイトエンドポイントのhttp://を取り除いた部分をコピーします。例: example-backet-namet.s3-website-ap-northeast-1.amazonaws.com

2. CloudFrontでディストリビューション作成を選択し、オリジンドメインで1.でコピーした値を貼り付けます(ドロップダウンリストからS3のバケットを選択しない)

3. キャッシュビヘイビアの設定を行います。基本デフォルトでOK。

4. 代替ドメイン名で設定したい独自ドメイン(route53以外はサブドメイン)を設定する
独自ドメインを設定する場合はcloudfrontのドメイン名をcnameまたはaliasで設定(静的ウェブサイトホスティングを有効の場合はバケット名と設定ドメイン名は共通している必要がある。

5. HTTPS化したい場合はカスタム証明書を選択する

6.デプロイ

静的ウェブサイトエンドポイントをオフの状態でオリジンに設定する

1. 同様にディストリビューションを作成をクリック、オリジンドメインの項目で対象のpublic accessをオンにしたバケットを選択

2.S3バケットアクセスでPublicを選択する。以下は同じく設定する

静的ウェブサイトホスティングをオフの状態では静的ウェブサイトホスティングで有効になる機能が

Refererヘッダーでオリジンへのアクセスを制限する

CloudFront側でRefererのヘッダに秘密の値を入れてその値をオリジンの S3に転送します。 S3のバケットポリシーでRefererの秘密の値を含む場合のみ許可することでアクセスを制限することができます。

1. 静的ウェブサイトホスティングを有効化した S3バケットの静的ウェブサイトエンドポイントのhttp://を取り除いた部分をコピーします。例: example-backet-namet.s3-website-ap-northeast-1.amazonaws.com
2. CloudFrontでディストリビューション作成を選択し、オリジンドメインで1.でコピーした値を貼り付けます。
3.カスタムヘッダーのヘッダー名にReferer, 値に秘密の値を入れます。

4. 残りの設定を行なって(特になければdefault)ディストリビューションの作成
5. S3のブロックパブリックアクセスの設定で「新しいパブリックバケットポリシーまたはアクセスポイントポリシーを介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする
任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする」のチェックを外す
6. 設定したオリジンのS3でバケットのポリシーを設定する

{
  "Version":"2012-10-17",
  "Id":"CloudFront custom referer policy example",
  "Statement":[
    {
      "Sid":"Allow get requests from CF",
      "Effect":"Allow",
      "Principal":"*",
      "Action":["s3:GetObject","s3:GetObjectVersion"],
      "Resource":"arn:aws:s3:::examplebacket/*",
      "Condition":{
        "StringLike":{"aws:Referer":["secret1234"]}
      }
    }
  ]
}

7.クラウドフロントのドメイン名からアクセス「example.cloudfront.net」見られることを確認する
8. 静的ウェブサイトエンドポイントからアクセスして閲覧できないことを確認する(Refererヘッダにシークレットキーが入っていないから)

CloudFront周りの詳細設定

CNAME(代替ドメイン名)

CloudFrontのディストリビューションを作成するとtekitoumojiretsu.cloudfront.netというドメインが発行されます。作成したCloudFrontに独自ドメインを割り当てたい場合はDNSの設定が必要です。

example.comというベースドメインであればwww.example.comのようなサブドメインのCNAMEレコードにCloudFrontのドメインを登録すれば独自ドメインを利用することができます。

Route53を利用していればエイリアスレコードをCNAMEの代わりに利用できるのでサブドメインだけでなくベースドメインをCloudFrontの独自ドメインとして利用することもできます。

  • 独自ドメインを割り当てる場合
    • route53の場合
      • エイリアスレコードで登録可能なので全てのドメインを登録可能
    • route53以外のDNS
      • サブドメインのCNAMEレコードを登録

地理的制限

地理的制限では許可または拒否のパターンで配信する国を選択できます。

CloudFrontへの攻撃や攻撃による不要なトラフィック発生を抑えるために地理的制限は有用です。

キャッシュ削除

CloudFrontはキャッシュを配信するので検証時などは特に更新したデータがキャッシュのせいで見れないパターンがあります。キャッシュ削除を実行することで最新のデータをオリジンに取りに行かせます。(検証時にはキャッシュポリシーでキャッシュを無効化にしておいた方が楽です)

キャッシュは下記のようにパスのパターンで指定できます。

ACMで証明書を取得

ACM(Amazon Certificate Manager)で証明書を取得します。

ACMはAWSサービスで利用できる無料で証明書を発行できるサービスですが、CloudFrontで使用するには証明書は、米国東部 (バージニア北部) リージョン (us-east-1) にある必要があります。

ドメインを入力してパブリック証明書をリクエストします。

route53を使用していればDNS認証で簡単に発行できます。

レコード作成をクリック後に< 5分くらい待つと発行されます。

CloudFrontの料金を低減するには?

CloudFrontの主な料金はコンテンツの転送料金です。転送料金自体は実はS3やEC2上から配信するのとそこまで差はありませんが、CDNという性質上、動画などの容量の大きなファイルを配信する機会も多く、想像を超えたアクセスあってもサーバが落ちるなどの被害がないので気付きにくいので、高額請求が来て驚くこともあるかもしれません。

CloudFrontでの料金を低減するには

  • コンテンツの圧縮
    • 画像
      • webpなどの高圧縮形式に変換したり、解像度を落とす、
      • pngはpngquanttinypngなどを使って最適化する
    • 動画
      • h.265などの高圧縮形式を使ってビットレートや解像度を落とす。
      • 動画のみyoutubeの埋め込みや別の配信サービスを使って配信する
    • ライブラリ(bootstrapなど)
      • CDNから読み込むように変更する
    • 配信エリア
      • 配信エリアをターゲットのいるエリアに限定する(地理制限で日本のみに)
    • 攻撃を防ぐ
      • AWS WAFを使ってボットのアクセス制限などを行う

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です