はじめに
本記事では、S3だけで静的サイトをホスティングし、任意のIPからのみアクセス可能にする方法を紹介します。
※コストを最小にする目的で、バケットポリシーでアクセス制御を行っていますが、高セキュリティ運用する場合は CloudFront+WAF を推奨します。
公式ドキュメント
https://docs.aws.amazon.com/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html
手順(詳細)
1. S3バケットを作る
2. バケットポリシーでIP制限を設定
例:任意のIP からのみ s3:GetObject を許可
推奨パターン(安全):明示的な Deny を使って、許可IP以外を拒否する(NotIpAddress + Deny)。Deny は Allow を打ち消すため、誤った Allow による漏れを防ぎます(AWSのポリシー評価は explicit Deny が最優先)。
↓そのままコピペして example.com(バケット名) と SourceIpの0.0.0.0 を書き換えてご自身の環境に合わせて書き換えてください
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowGetFromMyIP",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example.com/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "0.0.0.0/32"
}
}
},
{
"Sid": "DenyGetFromOtherIPs",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example.com/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"0.0.0.0/32"
]
}
}
}
]
}
上記は「許可(特定IP)+それ以外を明示的に拒否」のパターンです。Deny が優先されるため、他の Allow が誤ってあっても遮断できます。バケットポリシーの例(一般)や IP 制限の実装例は公式やナレッジセンター参照を推奨します。
公式ドキュメント
https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html
補足:
複数のIPアドレスからアクセスを許可することも可能です。
その場合はSourceIpの配列の要素に列挙してください。
"aws:SourceIp": [
"0.0.0.0/32",
"1.1.1.1/32"
]
3. Block Public Access の設定
バケットポリシーを有効にして IP 制限をかけるため、少なくとも BlockPublicPolicy を false にする必要があります。
※アカウント単位で BlockPublicPolicy が有効だとバケット側で変えられないので注意。
4. 静的ウェブサイトホスティングを有効化
- S3 → バケット → Properties → 「静的ウェブサイトホスティング」 → 有効にする
- インデックスドキュメント: index.html
- エラードキュメント: index.html (SPAを想定 React のルーティングはすべて index.html に任せるので、404でもindexを返す設定が必須です。)
※S3の「ウェブサイトエンドポイント」は http://example.com.s3-website-.amazonaws.com の形式です(HTTPSはサポートされません。HTTPSが必要なら CloudFront 経由を検討してください)。
5. ファイルをアップロード
ご自身で公開したい静的ファイルを用意してください。
今回は試験的にReactのデフォルトappをアップロードします。
Reactのデフォルトアプリケーションを作成
npx create-react-app my-app
ビルドして静的ファイルを作成
cd my-app
npm run build
build/配下のファイルをS3バケットにアップロード
6. 動作確認
エンドポイントはプロパティタブ最下部( 静的ウェブサイトホスティング )から確認できます。
-
許可したIPからブラウザで http://example.com.s3-website-.amazonaws.com にアクセス → ページが表示される(200)
S3単体での静的サイトホスティングのメリット・デメリット
項目 | メリット | デメリット |
---|---|---|
コスト | 非常に安価。アクセスが少ない場合、月数十円〜数百円で運用可能 | 大量アクセスやグローバル配信には非効率。CloudFrontに比べるとパフォーマンスは劣る |
設定の簡単さ | AWSコンソールだけで簡単に公開可能。CloudFront不要 | HTTPS対応不可(HTTPのみ)。独自ドメインでHTTPSを使うにはCloudFront必須 |
メンテナンス性 | 静的ファイルをアップロードするだけでOK | SPAのルーティング対応やカスタムエラーページは設定がやや複雑 |
アクセス制御 | バケットポリシーでIP制限やIAMユーザー単位の制御が可能 | IP制限のみの柔軟な制御。WAFのような高度な制御はできない |
配信性能 | AWS内部ネットワークの高速S3エンドポイントを利用可能 | 世界中への低レイテンシ配信は難しい。CloudFrontの方が高速 |
可用性・耐障害性 | AWS S3自体の耐障害性・冗長性あり | 高トラフィックやグローバルアクセス時のキャッシュ最適化は不可 |
SEO・SNSシェア対応 | 基本的なHTML公開は可能 | HTTPS非対応だとSEOや一部サービスのリンク表示で不利 |
まとめと補足
なぜバケットポリシーで /32 を使うのか
S3のバケットポリシーでアクセス制御を行う際、IPアドレスの範囲は CIDR(Classless Inter-Domain Routing)表記 で指定します。
/32 は 32ビットすべてがネットワーク部分 という意味で、単一のIPアドレスだけを許可 する指定です。
例えば 0.0.0.0/32 とすると、許可されるのは 0.0.0.0 だけで、それ以外のIPは拒否されます。
単一IPだけを厳格に許可したい場合に /32 が便利です。
複数IPを許可したい場合は、配列で /32 を列挙したり、サブネット(例 /24)でまとめて指定することも可能です。
※ /32 はポート番号ではなく、IPアドレス範囲の指定です。
静的ウェブサイトとは
静的ウェブサイトとは、サーバー側で動的に処理をせず、あらかじめ用意されたHTMLやCSS、JavaScriptファイルをそのまま配信するウェブサイト のことです。
特徴:
-
ファイルの中身は固定で、アクセスするたびに変化しません。
-
S3のようなストレージにファイルを置くだけで公開可能。
-
SPA(Single Page Application)やReactアプリのように、クライアント側で動的処理を行う設計も可能。
-
サーバーサイド処理(PHP, Node.jsなど)は不要なため、運用コストや設定が非常にシンプルです。
静的ウェブサイトは、小規模な社内ツールや検証サイト、低コストでの公開に最適です。HTTPSやアクセス制御など高度な機能が必要な場合は、CloudFrontなどと組み合わせて運用するのが一般的です。
最後に
今回は、ReactのデフォルトアプリをS3単体でホスティングし、特定IPからのみアクセス可能にする手順を紹介しました。
S3単体でのホスティングは非常に簡単でコストも低く、少人数向けの検証サイトや社内ツールに最適です。一方で、HTTPS非対応、柔軟なアクセス制御ができない、グローバル配信には不向きなどの制約があります。
公開範囲を広げたり、HTTPS対応が必要な場合は、CloudFront併用やWAF、署名付きURLなどの拡張も検討してください。
小規模なサイトであればS3単体でも十分実用可能と考えておりますので、今回の手順を参考にぜひ試してみてください。
勉強中の身なので、この手法についてコスト面やリスクについて皆さんの見解をコメントしていただけるとありがたいです。