概要
グローバルに配信するWebコンテンツに対して、特定の国からのアクセスを制限したいケースがあります。たとえば、コンプライアンス要件やライセンス上の理由から、特定の国のユーザーにはコンテンツを配信できない場合です。
Amazon CloudFrontの地理的制限(Geo-Restriction)機能を使用すると、CloudFrontのエッジロケーションレベルで国単位のアクセス制御を実現できます。さらに、S3バケットへの直接アクセスを防ぐためにOAC(Origin Access Control)を併用することで、CloudFrontを経由しないアクセスをブロックし、地理的制限を確実に適用できます。
本記事では、CloudFrontの地理的制限の仕組みと、OACによるオリジン保護を組み合わせたコンテンツアクセス制御について解説します。

クラウドおさる国ごとに配信を止める CloudFront の地理的制限と、その制限を裏口から迂回させないための OAC を、あわせて確かめる記事でござる。表門だけ固めても裏口が開いていては意味がない、というお話でござるな。
この記事のメリット
- CloudFrontの地理的制限の仕組みと許可リスト・拒否リストの使い分けを理解できる
- OACによるS3バケット保護の重要性と設定方法を把握できる(レガシーのOAIとの違いも整理できる)
- S3バケットポリシーによる国別制限やRoute 53の地理的ルーティングでは不十分な理由を理解できる
- CloudFrontの地理的制限とOACを組み合わせた実践的な設定手順を体験できる
- SCS試験で「国別コンテンツ制限」を問われた際に正確に判断できるようになる
執筆者とキャラクター紹介
執筆者:土肥(とひ)
株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。


クラウドおさる



はじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。



基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。



猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。
技術解説
CloudFrontの地理的制限とは
CloudFrontの地理的制限は、ディストリビューション単位で特定の国からのアクセスを許可または拒否する機能です。CloudFrontは、リクエスト元のIPアドレスから国を判定し、設定に基づいてアクセスを制御します。
国の判定にはMaxMind社のGeoIPデータベースが使用されます。IPアドレスと国の対応は定期的に更新されますが、100%の精度ではない点に留意が必要です。
地理的制限が適用された場合、拒否対象の国からのリクエストにはHTTPステータスコード 403(Forbidden) が返されます。
許可リストと拒否リストの使い分け
地理的制限には2つのアプローチがあります。
| アプローチ | 設定方法 | ユースケース |
|---|---|---|
| 許可リスト(Allowlist) | アクセスを許可する国を指定し、それ以外はすべて拒否 | 配信先が限定されている場合(例: 日本国内のみに配信) |
| 拒否リスト(Denylist) | アクセスを拒否する国を指定し、それ以外はすべて許可 | 大部分の国には配信し、一部の国のみブロックしたい場合 |
許可リストは「ホワイトリスト型」のため、指定し忘れた国からのアクセスはすべて拒否されます。一方、拒否リストは「ブラックリスト型」のため、指定し忘れた国からのアクセスは許可されます。要件に応じて適切なアプローチを選択することが重要です。



許可リストは書き忘れた国が締め出され、拒否リストは書き忘れた国が素通りするのでござる。猿山の長老会も、入山を許す群れを名簿に書くか、断る群れを書くかで、名簿漏れの意味が真逆になるのでござるな。
オリジンアクセスコントロール(OAC)によるオリジン保護
CloudFrontの地理的制限を有効にしても、S3バケットに直接アクセスされると制限が適用されません。S3のバケットURLに直接アクセスすれば、CloudFrontを経由しないため地理的制限を迂回できてしまいます。
これを防ぐために、OAC(Origin Access Control)を使用してS3バケットへのアクセスをCloudFrontディストリビューション経由のみに制限します。
OACの仕組みは以下の通りです。
- CloudFrontがオリジンへのリクエストにSigV4署名を付ける
- S3バケットポリシーで、サービスプリンシパル
cloudfront.amazonaws.comからのアクセスだけを許可する - さらに
AWS:SourceArn条件で、特定のディストリビューションからのリクエストに限定する - S3バケットのパブリックアクセスはブロックする
- ユーザーはCloudFrontのドメイン名を通じてのみコンテンツにアクセスできる
| 項目 | OAI(レガシー) | OAC(現行) |
|---|---|---|
| バケットポリシーのプリンシパル | arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <ID> | サービスプリンシパル cloudfront.amazonaws.com |
| ディストリビューション単位の限定 | OAIごとに分ける | AWS:SourceArn 条件で指定 |
| SSE-KMS で暗号化したオブジェクト | 非対応 | 対応 |
| 現在のコンソール | 新規ディストリビューション作成画面では選べない | 既定で有効(推奨) |


OAIは引き続き既存のディストリビューションで利用できますが、AWSはOACの使用を推奨しています。現在のディストリビューション作成ウィザードにはOAIを選ぶ項目自体がありません。



地理的制限をかけても、S3 のバケット URL に直接来られたら CloudFront を通らず制限は効かないのでござる。だから OAC で、バケットへの入口を CloudFront 経由だけに絞るのでござるぞ。
他のアプローチが不十分な理由
国別のアクセス制限を実現する手段として、以下のアプローチが考えられますが、それぞれに制約があります。
S3バケットポリシーによる国別制限
S3バケットポリシーの条件キーには、リクエスト元の国を直接判定する仕組みがありません。aws:SourceIp 条件キーでIPアドレス範囲を指定することは可能ですが、国単位でのIPアドレス範囲は膨大かつ変動するため、実用的ではありません。
さらに、CloudFront経由でS3にアクセスする場合、S3が受け取るリクエスト元のIPアドレスはCloudFrontエッジロケーションのIPアドレスであり、エンドユーザーのIPアドレスではありません。そのため、S3バケットポリシーの aws:SourceIp でエンドユーザーの国を判定すること自体が不可能です。
Route 53の地理的位置ルーティング
Route 53の地理的位置ルーティングを使用すると、DNSレベルで特定の国からのリクエストを異なるエンドポイントに誘導できます。しかし、この方法には以下の制約があります。
- DNS解決の迂回: ユーザーがCloudFrontディストリビューションのIPアドレスを直接指定してアクセスすると、Route 53のDNSルーティングを迂回できる
- DNSキャッシュの問題: DNSレコードのTTL期間中は、ルーティング変更が反映されない場合がある
これらの理由から、CloudFrontの地理的制限とOACの組み合わせが、国別アクセス制御の実装として適切な方法です。
実践
ここでは、S3バケットをオリジンとするCloudFrontディストリビューションに地理的制限を設定し、特定の国からのアクセスを拒否する構成を作成します。また、OACによってS3バケットへの直接アクセスをブロックし、CloudFront経由でのみコンテンツにアクセスできるようにします。
前提条件
- リージョン:
ap-northeast-1(東京) - 以下のリソースが作成済みであること
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| S3バケット | geo-restriction-lab-<アカウントID> | コンテンツ配信用オリジン |
S3バケットにはテスト用のHTMLファイル(
index.html)がアップロード済みであることを前提とします。
手順1: S3バケットのパブリックアクセスをブロックする
まず、S3バケットへの直接アクセスをブロックし、CloudFront経由のみでアクセスできるようにします。
- AWSマネジメントコンソールにログインし、右上のリージョンが「アジアパシフィック(東京) ap-northeast-1」であることを確認します。
- 上部の検索バーに
S3と入力し、表示された「S3」を選択します。 - バケット一覧からバケット(
geo-restriction-lab-<アカウントID>)をクリックします。 - 「アクセス許可」タブを選択します。
- 「ブロックパブリックアクセス(バケット設定)」セクションの「編集」をクリックします。
- 「パブリックアクセスをすべてブロック」にチェックを入れます。
- 「変更の保存」をクリックし、確認ダイアログに
確認と入力して保存します。


手順2: CloudFrontディストリビューションを作成する
- 上部の検索バーに
CloudFrontと入力し、表示された「CloudFront」を選択します。 - 「ディストリビューションを作成」をクリックすると、6ステップのウィザード(Choose a plan / Get started / Specify origin / Enable security / Get TLS certificate / Review and create)が開きます。
ステップ1: Choose a plan
料金体系を選びます。定額のプラン(Flat-rate plans)と従量課金(Pay as you go)のどちらかを選択します。
- 検証目的では「Pay as you go」を選び、「Choose pay-as-you-go」をクリックします


Flat-rate plans を選ぶと、トラフィックの有無にかかわらず月額の定額料金が発生します。検証用のディストリビューションでは従量課金を選びます。
ステップ2: Get started
- Distribution name:
geo-restriction-lab - Distribution type: 「Single website or app」(デフォルト)
- ドメインの項目は空のままにします(CloudFrontのデフォルトドメインを使います)
- 「Next」をクリックします
ステップ3: Specify origin
- Origin type: 「Amazon S3」を選択します
- S3 origin:
geo-restriction-lab-<アカウントID>.s3.ap-northeast-1.amazonaws.comを入力します(「Browse S3」からバケットを選ぶこともできます) - 「Allow private S3 bucket access to CloudFront – Recommended」にチェックが入っていることを確認します。これがOACの設定で、CloudFrontがS3バケットポリシーを自動的に更新します
- 「オリジン設定」「Cache settings」は推奨設定(Use recommended …)のままにします
- 「Next」をクリックします


ステップ4: Enable security
- 「セキュリティ保護を有効にしないでください」を選択します(AWS WAF は使いません)
- 「Next」をクリックします
ここで「セキュリティ保護を有効にする」を選ぶと AWS WAF のウェブ ACL が作成され、月額の利用料が発生します。
ステップ5: Review and create
- Billing が「Pay-as-you-go ($0/month)」、Grant CloudFront access to origin が「Yes」になっていることを確認します
- 「Create distribution」をクリックします
ディストリビューションが作成されると、詳細画面にディストリビューションドメイン名(dxxxxxxxxxxxxx.cloudfront.net)が表示されます。デプロイが完了するまで数分かかります。


デフォルトルートオブジェクトの設定
現在の作成ウィザードにはデフォルトルートオブジェクトの入力欄がないため、作成後に設定します。
- ディストリビューションの詳細画面で「一般」タブを選択します
- 「設定」セクションの「編集」をクリックします
- 「デフォルトルートオブジェクト」に
index.htmlを入力して保存します
これで https://<ディストリビューションドメイン名>/ にアクセスしたときに index.html が返るようになります。
手順3: S3バケットポリシーを確認する
手順2で「Allow private S3 bucket access to CloudFront」を有効にしたため、S3バケットポリシーにOACを許可するポリシーが自動的に設定されています。
- S3コンソールに移動し、バケット(
geo-restriction-lab-<アカウントID>)の「アクセス許可」タブを選択します。 - 「バケットポリシー」セクションで、以下のようなポリシーが設定されていることを確認します。
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::geo-restriction-lab-<アカウントID>/*",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:cloudfront::<アカウントID>:distribution/<ディストリビューションID>"
}
}
}
]
}プリンシパルがIAMユーザーではなくサービスプリンシパル cloudfront.amazonaws.com になっており、AWS:SourceArn 条件で「このディストリビューションからのリクエストであること」まで絞り込まれています。これがOACのポリシーです。





自動で入ったバケットポリシーは、プリンシパルが cloudfront.amazonaws.com で、AWS:SourceArn でこのディストリビューションに絞られているのでござる。どの CloudFront でもよいわけではない、という点が OAC の要でござるな。
手順4: CloudFrontに地理的制限を設定する
- CloudFrontコンソールに移動し、手順2で作成したディストリビューションをクリックします。
- 「セキュリティ」タブを選択します。
- 一番下の「CloudFront geographic restrictions」は折りたたまれています。見出しをクリックして展開し、「Edit」をクリックします。
- 以下を設定します。
- Restriction type: 「Block list」を選択(「No restrictions」「Allow list」「Block list」の3択)
- 国: 「Select countries」のプルダウンから拒否する国を選びます(例: テスト用に日本以外の任意の国を追加)


- 「変更を保存」をクリックします。
- ディストリビューションのステータスが「デプロイ中」に変わります。デプロイが完了するまで数分待ちます。
手順5: アクセスの動作を確認する
CloudFront経由のアクセス確認
- ブラウザで CloudFrontのディストリビューションドメイン名(
https://dxxxxxxxxxxxx.cloudfront.net)にアクセスします。 - 日本からのアクセスが拒否リストに含まれていなければ、
index.htmlの内容が正常に表示されます。


S3バケットへの直接アクセス確認
- ブラウザでS3バケットのURLに直接アクセスします。
https://geo-restriction-lab-<アカウントID>.s3.ap-northeast-1.amazonaws.com/index.html- OACによるバケットポリシー制限により、403 AccessDenied エラーが返されることを確認します。


これにより、S3バケットに直接アクセスしてCloudFrontの地理的制限を迂回することが不可能であることを確認できます。ブラウザではXMLのエラーレスポンスがそのまま表示されます。
地理的制限による拒否の確認
拒否リストに指定した国からアクセスした場合、CloudFrontは以下のようなエラーレスポンスを返します。
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
</Error>HTTPステータスコード403とともに、CloudFrontのエッジロケーションでリクエストが拒否されます。オリジンのS3バケットにはリクエストが到達しません。
CloudFrontの地理的制限はエッジロケーションで処理されるため、オリジンに負荷をかけることなく不要なトラフィックを遮断できます。



国別に配信を止めたいとき、バケットポリシーの aws:SourceIp や Route 53 の地理的位置ルーティングと取り違えないか、が問われる観点でござる。エッジで止める地理的制限と、迂回を塞ぐ OAC の組み合わせで答えるのでござるな。
まとめ
- CloudFrontの地理的制限は、エッジロケーションレベルで国単位のアクセス制御を行う機能で、許可リストと拒否リストの2つのアプローチがある
- 国の判定にはMaxMind社のGeoIPデータベースが使用され、リクエスト元のIPアドレスから自動的に判定される
- OACを使用してS3バケットへのアクセスをCloudFront経由のみに制限することで、地理的制限の迂回を防止できる。バケットポリシーはサービスプリンシパル
cloudfront.amazonaws.comとAWS:SourceArn条件で構成される - S3バケットポリシーの
aws:SourceIpによる国別制限は、CloudFront経由のアクセスではエンドユーザーのIPアドレスを取得できないため不適切 - Route 53の地理的位置ルーティングは、IPアドレス直接指定による迂回が可能なため単独では不十分
- CloudFrontの地理的制限 + OAC の組み合わせが、国別コンテンツ制限の推奨アーキテクチャ(OAIはレガシーで、現在の作成ウィザードでは選択できない)
参照先
- 地理的制限を使用してコンテンツのアクセスを制限する
- オリジンアクセスコントロール (OAC) を使用して Amazon S3 オリジンへのアクセスを制限する
- Amazon S3 オリジンへのアクセスの制限
- Amazon CloudFront の仕組み
- Amazon Route 53 の地理的位置ルーティング










