はじめに
本稿では、AWS Global Accelerator (以下、Global Accelerator)を利用してパブリックIPアドレスを固定化する方法を解説します。
オンプレミス環境では、VRRPなどを用いて単一のIPアドレスに接続する設計がよくありますが、その設計はAWSの冗長性・拡張性の設計思想とは異なるため、移行時に課題となります。
以前のブログ(2025.10.15 投稿)では、この課題に対する6つの実装方式を紹介しました。
本稿では、そのうち Global Acceleratorを使った方式 を詳しく解説していきます。
2025.10.15のブログでは、Global Accelerator について以下のようにご紹介しました。
5.1 AWS Global Accelerator
AWS Global Accelerator は、グローバルに固定されたパブリックIPアドレスを提供し、TCPやUDPといった特定のプロトコルに限定されない幅広い通信をサポートします。このサービスは、複数のAWSリージョンにエンドポイントを配置できるため、障害発生時には自動的に健全なリージョンへルーティングすることで、高い冗長性を実現します。特に、マルチリージョン対応のアプリケーションや、クライアント側でIPアドレスの固定が厳しく求められる場合に有効な選択肢です。
この内容について、個々の作業を出来るだけ具体的にイメージしていただきたいと考えています。合わせて、より AWS 内部の仕組みの理解に役立つようにしたいと考えています。
そこで本稿では、構成図と、構成図に合わせた AWS CLI スクリプト等のサンプルをもとに解説していきます。スクリプトは、主に CloudShell 上で実行を確認しています。
本稿の構成図
本稿でご説明する構成図は以下の通りです。
本稿の作業の段取り
本稿の構成を、以下の段取りで構築していきます。緑色の箱の部分を説明していきます。
なお、以下の基本的な部分は構築済とします。
- VPC
- サブネット
- Internet Gateway
- リージョナル NAT Gateway(手動モードで固定パブリックIPアドレスを2つ付与)
- ルーティング
- セキュリティグループ
| セキュリティ グループ |
用途 | inbound | outbound |
| ALB | ALB用 | セキュリティグループCheck が設定されたリソースからの http, https 接続を許可 ※ALB 構築時の動作確認用 |
セキュリティグループWeb が設定されたリソースに対して http 接続を許可 |
| Web | Web サーバ用 |
セキュリティグループALB が設定されたリソースからの http 接続を許可 |
0.0.0.0/0 に対して https 接続を許可 |
| Check | 動作確認 サーバ用 |
無し | 0.0.0.0/0 に対して https 接続を許可 |
- ALB関連
| 項目 | 主な設定 |
| ALB | VPC内部からの接続用(internalスキーマ設定) |
| ターゲットグループ | 負荷分散対象のターゲットに http(80/tcp)で接続 |
| リスナー | Webクライアントからの接続を受け付け、 TLS証明書 をチェックし、ターゲットグループに転送 |
| TLS証明書 | テスト用の TLS証明書 をインポート |
| 起動テンプレート | インスタンスタイプ、起動台数等を設定 |
| オートスケーリンググループ | 起動テンプレートとターゲットグループを紐づけ |
-
Systems Manager Session Manager で動作確認用仮想サーバにログインするための
IAMロール -
動作確認用仮想サーバ
-
ログ保存用S3バケット
- ALB ログ用 S3バケット
- WAFv2 ログ用 S3バケット
- Global Accelerator ログ 用 S3バケット
1. Global Acceleratorとは
Global Accelerator は、AWS のグローバルネットワークを最大限に活用し、アクセス元の最寄りのエッジロケーション(アクセス元が日本なら日本のロケーション)からトラフィックをルーティングすることで、アプリケーションの可用性とパフォーマンスを向上させるサービスです。
この Global Accelerator ですが、大きな特徴として、変更されない、固定のパブリックIPアドレス を 2 つ提供する点が挙げられます。Global Accelerator で提供される IPアドレス を利用することにより、バックエンドの環境が変化しても、利用者に公開する IPアドレス は一貫性を保つことが可能になります。
Global Accelerator の主な用途としては、以下があります。
▼Global Accelerator の主な用途
①Webサービス用
②任意のTCP/UDPプロトコル用
Global Accelerator は、このサービス単体で利用できるわけではありません。他の様々なマネージドサービスと組み合わせて使うことになります。
本稿では、①Webサービス用の構成で、他のマネージドサービスとの組み合わせについて解説を進めていきます。
2. Global Accelerator と組み合わせるマネージドサービス
Webサービスで利用することを考えると、プロトコルはセキュアな https になります。https でのアクセスになりますと、TLS証明書が必要になります。TLS証明書は、ドメインに対して証明書が発行されます。
少し具体的に見ていきましょう。Global Accelerator の 固定IPアドレス が xxx.xxx.xxx.xxx だとします。ここにブラウザで https://xxx.xxx.xxx.xxx にアクセスした場合、TLS証明書はドメイン名に紐付いているため、IPアドレスではその証明書が正当であるかを判断できません。その結果、セキュアな通信は確立できず、ブラウザにはセキュリティ警告が表示されることになります。そのため、Global Accelerator 経由で https 通信を行う際は、以下のマネージドサービスと組み合わせが想定されます。
▼Global Accelerator 利用時に、合わせて利用が想定される項目とマネージドサービス
| 項目$\hspace{3em}$ | 内容 | マネージド サービス |
| TLS証明書 | ドメイン名に対して TLS証明書 を取得、 AWS Certificate Manager (ACM)へインポートし、 ALB のリスナーに設定します。 |
AWS Certificate Manager |
| ドメイン名 | Webアプリケーションに https でアクセスするために
TLS証明書 が必要です。TLS証明書の発行では、 ドメイン名(例: www.sample.org)が必要です。
Route 53 ホストゾーンは、特定のドメインを設定し、 そのドメインに DNS レコードを登録する機能を 提供します。 |
Amazon Route 53 Hosted Zone |
|
DNS レコード |
Global Accelerator の 固定IPアドレス を指すように、
ドメインと、DNSレコード(Aレコード)を 設定します。 |
これにより、ユーザーが上記の https://www.sample.org にアクセスすると、DNS によってGlobal Accelerator の IPアドレス に解決され、Global Accelerator を経由して ALB にトラフィックが到達します。ALB は、TLS証明書に紐付いたドメイン名でアクセスを受け付けるため、正常に https ハンドシェイクが完了し、セキュアな通信が確立されるわけです。
また、接続元の IPアドレス を制限したい、という要件も想定されます。その場合には、AWS WAFv2 で 接続元IPアドレス制限をかけることになるでしょう。
なお、AWS WAFv2 は、Global Accelerator には直接紐づけることはできません。Global Accelerator からアクセスする、ALB に AWS WAFv2 を紐づけることで、接続元IPアドレス を制限できるようになります。
それでは、実際の設定例を、AWS CLI のスクリプトを通して見ていきましょう。
3. Global Acceleratorの作成と設定
3.1 Global Acceleratorの作成
以下の赤枠の Global Accelerator から作成していきます。
本稿では、以下のようにマネージドサービスやそのリソースの関連付けを図示しながら解説を記載していきます。
それでは、AWS CLI で Global Accelerator を作成しましょう。
以下のコマンドで作成します。
export GA_ARN=$(aws globalaccelerator create-accelerator \
--name "${GA_NAME}" \
--ip-address-type IPV4 \
--no-enabled \
--region us-west-2 \
--tags Key=Name,Value="${GA_NAME}" \
--query 'Accelerator.AcceleratorArn' \
--output text)
ここでは、作成コマンド実行時に、後工程で使う Global Accelerator の ARN (Amazon Resource Name)を取得し、環境変数に設定しています。
上記コマンドで使用しているオプションを解説します。
| オプション | 内容 |
| $\textsf{--name}$ | Global Accelerator の名称を設定します。 |
| $\textsf{--ip-address-type}$ | IPアドレスのバージョンを指定します。以下が選べます。 ・IPV4 ・IPV6 ・DUAL_STACK ※IPV4とIPV6の両方 |
| $\textsf{--no-enabled}$ | 作成時にすぐに有効化しない指定です。 様々な準備が整ったら、aws globalaccelerator update-accelerator で有効化します。 ※作成時に有効化することもできます。 その場合は、--enabled を指定します。 |
| $\textsf{--region}$ |
Global Accelerator はグローバルのマネージドサービスですが、 作成時にはリージョンとして us-west-2 を指定します。 (us-west-2 固定です) |
|
$\textsf{--query}$、 $\textsf{--output text}$ |
後続の処理で、Global Accelerator の ARN(Amazon Resource Name)を使います。 そのため、作成時に ARN を抽出しています。 |
Global Accelerator を作成したら、Global Accelerator の IPアドレス が設定されます。
以下のコマンドで IPアドレス を取得することが可能です。
export GA_IP_1=$(aws globalaccelerator describe-accelerator \
--region us-west-2 \
--accelerator-arn "${GA_ARN}" \
--query 'Accelerator.IpSets[0].IpAddresses[0]' \
--output text)
export GA_IP_2=$(aws globalaccelerator describe-accelerator \
--region us-west-2 \
--accelerator-arn "${GA_ARN}" \
--query 'Accelerator.IpSets[0].IpAddresses[1]' \
--output text)
3.2. Global Acceleratorのログ保存設定
Global Accelerator のログ取得の設定を行います。S3バケットと、S3バケットポリシーの json ファイルは作成済とします。S3バケットポリシーの詳細については、『ログ保存用S3バケットポリシーの記載のばらつきと修正例について』のブログをご参照ください。
以下のコマンドで、S3バケットポリシーの json ファイルを S3バケット に適用します。
aws s3api put-bucket-policy \
--bucket "${S3_LOGS_GA}" \
--policy file://"s3_bucket_policy.${S3_LOGS_GA}.json"
次に、Global Accelerator でログ出力の設定を行います。
aws globalaccelerator update-accelerator-attributes \
--region us-west-2 \
--accelerator-arn "${GA_ARN}" \
--flow-logs-enabled \
--flow-logs-s3-bucket "${S3_LOGS_GA}" \
--flow-logs-s3-prefix "${S3_PREFIX_GA_1}"
| オプション | 内容 |
| $\textsf{--region}$ |
変更時にもリージョンとして us-west-2 を指定します。 (us-west-2 固定です) |
| $\textsf{--accelerator-arn}$ | Global Accelerator の ARN を設定します。$\Huge{ }$ |
| $\textsf{--flow-logs-enabled}$ | ログ出力を有効化する指定をしています。$\Huge{ }$ |
|
$\textsf{--flow-logs-s3-bucket}$、 $\textsf{--flow-logs-s3-prefix}$ |
ログ出力をする S3バケット と プレフィックス(パス)を 指定しています。$\Huge{ }$ |
3.3. Global Acceleratorのリスナー/エンドポイントの作成
次に、Global Accelerator で https アクセスを受け付けるための リスナー と、Global Accelerator のリスナーを ALB に紐づける エンドポイント を作成します。
まず、リスナーを作成します。以下の赤枠の部分を作成します。
ここでは、作成時に、後工程で使う Global Accelerator のリスナー ARN (Amazon Resource Name)を取得し、環境変数に設定しています。
export GA_LISTENER_ARN=$(aws globalaccelerator create-listener \
--region us-west-2 \
--accelerator-arn "${GA_ARN}" \
--protocol TCP \
--port-ranges FromPort=443,ToPort=443 \
--client-affinity SOURCE_IP \
--query 'Listener.ListenerArn' \
--output text)
上記コマンドで使用しているオプションを解説します。
| オプション | 内容 |
| $\textsf{--region}$ |
Global Accelerator はグローバルのマネージドサービスですが、 作成時にはリージョンとして us-west-2 を指定します。 (us-west-2 固定です) |
| $\textsf{--accelerator-arn}$ | Global Accelerator の ARN を設定します。 |
| $\textsf{--protocol}$ |
クライアントから接続される際のプロトコルです。 TCP、または UDP です。 |
| $\textsf{--port-ranges}$ | 接続を受け付けるポートの範囲です。 |
| $\textsf{--client-affinity}$ |
同じクライアントからの接続を常に同じエンドポイントにルーティングするかどうかを制御するオプションです。 SOURCE_IP、NONE という設定値があります。
|
次に、エンドポイントを作成します。
Global Accelerator のエンドポイントグループで、Global Accelerator のリスナーと ALB を紐づけます。
以下のコマンドで作成し、Global Accelerator のリスナーと ALB を紐づけます。
export GA_ENDPOINT_GROUP_ARN=$(aws globalaccelerator create-endpoint-group \
--region us-west-2 \
--listener-arn "${GA_LISTENER_ARN}" \
--endpoint-group-region "${AWS_REGION}" \
--endpoint-configurations EndpointId="${ALB_PRIVATE_ARN}",Weight=128 \
--query 'EndpointGroup.EndpointGroupArn' \
--output text)
ここでは、作成時に、後工程で使う Global Accelerator のエンドポイントグループの ARN (Amazon Resource Name)を取得し、環境変数に設定しています。
上記コマンドで使用しているオプションを解説します。
| オプション | 内容 |
| $\textsf{--region}$ |
Global Accelerator はグローバルのマネージドサービスですが、
作成時にはリージョンとして us-west-2 を指定します。 (us-west-2 固定です) |
| $\textsf{--listener-arn}$ | Global Accelerator のリスナーの ARN です。 |
| $\textsf{--endpoint-group-region}$ | エンドポイントグループを配置するリージョンを指定します。 |
| $\textsf{--endpoint-configurations}$ |
エンドポイントの設定を指定します。
|
ここまで作成して、その後しばらく時間が経過すると、VPC内部に Global Accelerator のセキュリティグループが自動で作成されます。
3.4. Global AcceleratorをALBに紐づけ
次は、自動で作成されたセキュリティグループの ID を取得し、ALB 用のセキュリティグループに、Global Accelerator のセキュリティグループからの https 接続を許可するルールを設定します。
まず、新しく作成されたセキュリティグループの ID を取得します。
*GlobalAccelerator* という名称で、セキュリティグループを絞り込んで ID を取得し、取得した ID を環境変数に設定しています。
SG_ID_GA=$(aws ec2 describe-security-groups \
--region "${AWS_REGION}" \
--filters "Name=vpc-id,Values=${VPC_ID}" "Name=group-name,Values=*GlobalAccelerator*" \
--query 'SecurityGroups[0].GroupId' \
--output text 2>/dev/null || true)
次に、取得したセキュリティグループのIDを使って、Global Accelerator のセキュリティグループからの https 接続を許可するルールを設定します。これにより、Global Accelerator から ALB への通信経路が確保されます。
以下の赤枠の部分、ALB に設定しているセキュリティグループに、インバウンドのルールを追加します。
ALB 用のセキュリティグループのインバウンドのルールに、Global Accelerator のセキュリティグループからの https(443/tcp)接続を許可するルールを設定します。
以下のコマンドで設定します。
aws ec2 authorize-security-group-ingress \
--region "${AWS_REGION}" \
--group-id "${SG_ID_ALB_Private}" \
--protocol tcp \
--port 443 \
--source-group "${SG_ID_GA}"
上記コマンドで使用しているオプションを解説します。
| オプション$\hspace{1em}$ | 内容 |
| $\textsf{--region}$ | セキュリティグループが存在するリージョンを指定します。 |
| $\textsf{--group-id}$ | ルールを追加するセキュリティグループの ID を指定します。 |
| $\textsf{--protocol}$ |
プロトコルを指定します。 tcp、udp、icmp があります。 上記では tcp を指定しています。 |
| $\textsf{--port}$ |
ポート番号を指定します。
上記では 443 を指定しています。 プロトコルと合わせて、443/tcp で https を示します。 |
なお、Global Accelerator から ALB への通信経路は、AWSの内部通信になります。
そのため、ALB は内部接続用(internalスキーマ指定)の ALB で接続が可能です。
4. プライベートホストゾーン作成と設定
Global Accelerator の固定IPアドレスは、TLS証明書を使って https でアクセスされる場合は、DNS に登録されたドメイン名でアクセスされることが想定されます。
本来はこの用途ではパブリックホストゾーンで定義されることが想定されますが、本稿のサンプルスクリプトでは、動作イメージを確認するためだけの意図(※)でプライベートホストゾーンを作成し、そこに Global Accelerator の固定IPアドレスを Aレコード に登録します。
- ※$\hspace{0.3em}$動作確認の意図
- テスト用のドメインに接続すると、
そのドメインに対して Aレコード で定義された IPアドレス を取得し、
取得した IPアドレス に https でアクセスするという一連の流れを確認します。
その動きを理解する目的で、DNS でプライベートホストゾーンを設定します。
4.1 プライベートホストゾーンの作成
プライベートホストゾーンを作成します。
プライベートホストゾーンを作成する際には、リージョンと VPC の ID を指定します。
以下のコマンドで設定します。
作成時に、後工程で使う ホストゾーンのIDを取得し、環境変数に設定しています。
export HOSTED_ZONE_ID=$(aws route53 create-hosted-zone \
--name "${DOMAIN_PRIVATE}.local" \
--vpc VPCRegion="${AWS_REGION}",VPCId="${VPC_ID}" \
--caller-reference $(date +%s) \
--query 'HostedZone.Id' \
--output text | sed 's|/hostedzone/||')
上記コマンドで使用しているオプションを解説します。
| オプション | 内容 |
| $\textsf{--name}$ | ホストゾーンの名称を指定します。 |
| $\textsf{--vpc}$ |
ホストゾーンを関連付ける VPC を指定します。 リージョンと VPC ID で指定します。 |
| $\textsf{--caller-reference}$ |
リクエストを一意に識別するための文字列です。 値は 任意の文字列(通常はUUIDやタイムスタンプ)を指定します。 |
4.2 プライベートホストゾーンにAレコード登録
以下では Global Accelerator が提供する2つの 固定IPアドレス それぞれに対して、
www.${DOMAIN}.local と www2.${DOMAIN}.local の Aレコード を作成しています。
IPアドレスは、Global Accelerator に設定された IPアドレス を指定しています。
# DNSレコード操作
ACTION="UPSERT"
# DNSレコード作成
cat > dns-records.json << EOF
{
"Changes": [
{
"Action": "${ACTION}",
"ResourceRecordSet": {
"Name": "www.${DOMAIN_PRIVATE}.local",
"Type": "A",
"TTL": 300,
"ResourceRecords": [
{
"Value": "${GA_IP_1}"
}
]
}
},
{
"Action": "${ACTION}",
"ResourceRecordSet": {
"Name": "www2.${DOMAIN_PRIVATE}.local",
"Type": "A",
"TTL": 300,
"ResourceRecords": [
{
"Value": "${GA_IP_2}"
}
]
}
}
]
}
EOF
以下では、作成した jsonファイルを使って、ホストゾーンに Aレコード を登録しています。
export HOSTED_ZONE_CHANGE_ID=$(aws route53 change-resource-record-sets \
--hosted-zone-id "${HOSTED_ZONE_ID}" \
--change-batch file://dns-records.json \
--query "ChangeInfo.Id" \
--output text)
5. 動作確認①VPC内外のインスタンスから確認
5.1 Global Acceleratorの有効化
以下のコマンドで、Global Accelerator を有効化します。(有効化/無効化の操作には多少時間がかかります。)
aws globalaccelerator update-accelerator \
--accelerator-arn "${GA_ARN}" --enabled --region us-west-2
注意
本稿では、危険性を説明する目的で、アクセス制御をしていないこの段階で Global Accelerator を有効化していますが、実際の構築においてはセキュリティを考慮して、WAFv2 等でセキュリティを対策の上、有効化してください。
Global Accelerator の有効化中/無効化中は、以下のコマンドの出力は IN_PROGRESS になります。 IN_PROGRESS が、DEPLOYED に変われば設定完了です。
aws globalaccelerator describe-accelerator \
--accelerator-arn "${GA_ARN}" --region us-west-2 \
--query 'Accelerator.Status' --output text
設定完了後、VPC 内のインスタンス(例えば動作確認用のEC2)から以下で作成した https://www.${DOMAIN}.local へ何らかの Webクライアント(curlコマンドやブラウザ)でアクセスすると、Webクライアントは内部で VPC の設定に基づいて www.${DOMAIN}.local ドメインの DNS問合せ を行います。
$\hspace{1em}\textsf{※}\hspace{0.5em}$構成図では水色の線です。
$\hspace{2.5em}$動作確認用サーバが、Route 53 Hosted Zone に DNS問合せ を行っています。
問い合わされたドメインは、VPC 内のプライベートホストゾーンによって Aコード から Global Accelerator の 固定IPアドレス に解決されます。Webクライアントは、この名前解決された IPアドレス(=Global Accelerator)にアクセスします。
$\hspace{1em}\textsf{※}\hspace{0.5em}$構成図では緑色の線です。
$\hspace{2.5em}$動作確認用サーバが、NAT Gateway、Internet Gateway を経由して、
$\hspace{2.5em}$Global Accelerator にアクセスしています。
そして、Global Accelerator から AWS の内部通信を経由して ALB へトラフィックがルーティングされます。 ALB では、TLS証明書 に一致するドメイン名でのアクセスを受けるため、正常な https 通信 が確立されます。
以下では、セッションマネージャーで動作確認用のインスタンスにログインして、curl コマンドで Global Accelerator 用のドメインにアクセスしています。${DOMAIN} は、以下では test-static-ip1 としています。
$ aws ssm start-session --region "${AWS_REGION}" --target "${CHECK_INSTANCE_ID}"
Starting session with SessionId: Participant-***************************
sh-5.2$
sh-5.2$ nslookup www.test-static-ip1.local
Server: 10.0.0.2
Address: 10.0.0.2#53
Non-authoritative answer:
Name: www.test-static-ip1.local
Address: 166.117.13.41
sh-5.2$
sh-5.2$ curl -k https://www.test-static-ip1.local
<h1>Hello </h1>
sh-5.2$
本稿の環境では、TLS証明書として、自己署名の証明書を使って動作確認しています。そのため、動作確認上は TLS証明書 が自己署名の証明書でも可とする、証明書の正しさをチェックしないオプション -k を付けて、curl -kコマンドで https アクセスしています。
公のドメインに対して発行された TLS証明書 を設定した Webサイトへアクセスする際は、curl コマンドのみで https アクセスできます。
ここまでで、Global Accelerator から ALB を通じて、起動テンプレートで設定されたWebサーバにアクセスする経路ができました。
しかしながらここまでの設定では、Global Accelerator を有効化した場合、VPC 内のインスタンスからではなく、どこからでも Global Accelerator にアクセスできる状態です。ドメインは VPC 内部に閉じられていますが、Global Accelerator の IPアドレスはパブリックに公開です。TLS証明書 のエラーを無視すれば、IPアドレス で直接 Global Accelerator の IPアドレス(上記では 166.117.13.41) に接続することは可能です。
具体的には、インターネット上のどこからでも以下のコマンドで、Global Accelerator 経由で内部のリソースにアクセスできてしまいます。
$ curl -k https://166.117.13.41
<h1>Hello </h1>
$
このコマンドは、Global Accelerator で作成された IPアドレス が 166.117.13.41 の場合ですが、実際にはアクセス制御をしていない Webサーバ は常に探索されています。そのため、作成された IPアドレス が外部に知られる/知られないというレベルではなく、アクセス制御がない設定は危険です。
注意
本稿では、危険性を説明する目的で、アクセス制御をしていないこの段階で Global Accelerator を有効化していますが、実際の構築においてはセキュリティを考慮して、WAFv2等でセキュリティを対策の上、有効化してください。
そこで、次に、Global Accelerator へのアクセスを制限する仕組みを設定します。
以下のコマンドで、Global Accelerator を無効化します。(有効化/無効化の操作には多少時間がかかります。)
aws globalaccelerator update-accelerator \
--accelerator-arn "${GA_ARN}" --no-enabled --region us-west-2
6. WAFv2の作成と設定
Web アプリケーションを外部からの脅威から保護するために、AWS WAFv2 を導入します。WAFv2 は、SQLインジェクション、クロスサイトスクリプティング(XSS)などの一般的な Web 攻撃からアプリケーションを保護します。AWS では、WAFv2 に設定できるマネージドルールも多数用意されています。
本稿の構成では、特定の IPアドレス からのアクセスのみを許可するというルールを設定します。
具体的には、VPC内のプライベートサブネットからインターネットにアクセスする際に経由する NAT Gateway の パブリックIPアドレス を許可リストに登録します。これにより、NAT Gateway を経由しない外部からのアクセスをブロックし、Web アプリケーションへの攻撃経路を制限することができます。
それでは、WAFv2 で設定に使う IPアドレス群を定義する IPセット を作成していきます。IPセット は、許可用でも、禁止用でも使えます。本稿では許可用で使います。
6.1. IPアドレス制限用にNAT GatewayのIPアドレスを取得
IPセット に登録する IPアドレスとして、NAT Gateway で使用している IPアドレス を取得します。
IPアドレスの取得 CLI のオプションでは、NAT Gateway の ID を設定し、NAT Gateway の パブリックIPアドレス の配列をクエリしています。
NAT Gateway は、2025年11月20日にアップデートがあった リージョナル NAT Gateway を使いつつ、WAFv2 でのアクセス制御で使用できるよう、固定の パブリックIPアドレス を手動で 2 つ付与している前提とします。
export NAT_IP_1=$(aws ec2 describe-nat-gateways \
--region "${AWS_REGION}" \
--nat-gateway-ids "${NATGW_ID}" \
--query 'NatGateways[0].NatGatewayAddresses[0].PublicIp' \
--output text)
export NAT_IP_2=$(aws ec2 describe-nat-gateways \
--region "${AWS_REGION}" \
--nat-gateway-ids "${NATGW_ID}" \
--query 'NatGateways[0].NatGatewayAddresses[1].PublicIp' \
--output text)
6.2. IPアドレス制限の対象をIPセットとして登録
次に、WAFv2 で IPアドレス制限に用いる IPアドレス群 の IPセット を作成します。
ここでは、取得した NAT Gateway の IPアドレス を定義しています。
以下のコマンドで設定します。
IPセット の作成時に、後工程で使う ARN (Amazon Resource Name)を取得し、環境変数に設定しています。
export IP_SET1_ARN=$(aws wafv2 create-ip-set \
--name "${IP_SET1_NAME}" \
--scope ${WAF_SCOPE} \
--region ${AWS_REGION} \
--ip-address-version IPV4 \
--addresses "${NAT_IP_1}/32" "${NAT_IP_2}/32" \
--description "Allow only NAT Gateway EIPs" \
--tags Key=Name,Value="${SID}-waf-ipset" \
--query "Summary.ARN" \
--output text)
上記コマンドで使用しているオプションを解説します。
| オプション | 内容 |
| $\textsf{--name}$ | IPセット の名称を設定しています。 |
| $\textsf{--scope}$ |
IPセット をどの範囲で使うかを指定します。
REGIONAL、CLOUDFRONT があります。
|
| $\textsf{--region}$ | リージョンを指定します。 |
| $\textsf{--ip-address-version}$ |
IPアドレスのバージョンを指定します。以下が選べます。 ・IPV4 ・IPV6 |
| $\textsf{--addresses}$ | 登録する IP アドレスまたは CIDR ブロックのリストを指定します。 |
| $\textsf{--tags}$ | タグを設定します。 |
| $\textsf{--description}$ | IPセット についての説明を記載します。 |
6.3. WAFv2のアクセスコントロールリスト(ACL)を設定
上記で作成した IPセット を使って、WAFv2のアクセス制御を設定します。
以下のコマンドで、アクセスコントロールリストが設定された WAFv2 を作成します。
作成時に、後工程で使う Web ACL の ARN (Amazon Resource Name)を取得し、環境変数に設定しています。
export WEB_ACL_ARN=$(aws wafv2 create-web-acl \
--name "${WAF_NAME}" \
--scope "${WAF_SCOPE}" \
--region "${AWS_REGION}" \
--default-action '{
"Block": {
"CustomResponse": {
"ResponseCode": 403,
"CustomResponseBodyKey": "AccessDeniedMessage"
}
}
}' \
--rules '[{
"Name": "'"$IP_SET1_NAME"'",
"Priority": 0,
"Action": {"Allow": {}},
"Statement": {
"IPSetReferenceStatement": {
"ARN": "'"$IP_SET1_ARN"'"
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AllowNATIPs"
}
}]' \
--custom-response-bodies '{
"AccessDeniedMessage": {
"ContentType": "TEXT_HTML",
"Content": "<html><head><title>アクセス拒否</title></head><body><h1>アクセスが拒否されました</h1><p>このリソースへのアクセスは許可されていません。<br>管理者にお問い合わせください。</p></body></html>"
}
}' \
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName="${WAF_NAME}" \
--query "Summary.ARN" \
--output text)
上記コマンドで使用しているオプションを解説します。
| オプション | 内容 |
| $\textsf{--name}$ | Web ACL の名称を設定しています。 |
| $\textsf{--scope}$ |
Web ACL をどの範囲で使うかを指定します。
REGIONAL、CLOUDFRONT があります。
|
| $\textsf{--default-action}$ |
デフォルトの動作として、ルールに一致しない場合の 設定をします。 上記では、ルールと不一致は Block する動作で、 その場合は HTTP のレスポンスコード 403 と、 カスタムレスポンスを返す設定をしています。 |
| $\textsf{--rules}$ |
Web ACL に含めるルールを配列で設定します。 上記では、IPSetReferenceStatement パラメータを 使って、IPセット を指定しています。 |
| $\textsf{Priority}$ | 優先度の指定です。数字が小さいほど優先になります。 |
| $\textsf{Statement}$ | ルールの内容を記載します。 |
| $\textsf{IPSetReferenceStatement}$ |
事前に設定した IPセット を参照する指定です。 ARN で指定します。 |
| $\textsf{Action}$ |
条件に一致した場合の動作を指定します。 上記では、Allow(許可)を指定しています。 |
| $\textsf{VisibilityConfig}$ |
監視や、ログ設定に関わる項目です。 ここでは、IPセット に関わる設定を行います。 |
| $\textsf{SampledRequestsEnabled}$ |
リクエストサンプリングを有効にします。 リクエストサンプルは、リクエストの一部を記録します。記録は、AWS WAFv2 のコンソールで参照できます。最大 100 件程度が表示されます。長期間保存用ではなく、最近の傾向を把握する用途で使えます。 |
| $\textsf{CloudWatchMetricsEnabled}$ | CloudWatchメトリクスを有効にします。 |
| $\textsf{MetricName}$ | CloudWatchのメトリクス名を指定します。 |
| $\textsf{--custom-response-bodies}$ |
--default-action で指定したカスタムレスポンスの 本文を設定します。
|
| $\textsf{--visibility-config}$ |
監視や、ログ設定に関わる項目です。 ここでは、Web ACL 全体に関わる設定を行います。 |
| $\textsf{SampledRequestsEnabled}$ |
リクエストサンプリングを有効にします。 リクエストサンプルは、リクエストの一部を記録します。記録は、AWS WAFv2 のコンソールで参照できます。最大 100 件程度が表示されます。長期間保存用ではなく、最近の傾向を把握する用途で使えます。 |
| $\textsf{CloudWatchMetricsEnabled}$ | CloudWatchメトリクスを有効にします。 |
| $\textsf{MetricName}$ | CloudWatchのメトリクス名を指定します。 |
上記のコマンドで、IPセット と Web ACL 全体で、それぞれ監視の設定があります。
以下のように役割が異なります。
両方設定することで、全体の傾向と、ルールごとの詳細を合わせて把握可能になります。
ACL 全体のメトリクスでトラフィック量を把握しつつ、ルール固有のメトリクスで、どのルールが効いているかを分析する、といった使い方ができます。
| 項目 | Web ACL 全体 | ルール固有 |
| メトリクス範囲 | 全リクエスト | そのルールに一致したリクエスト |
| MetricName | ACL 名 | ルール名 |
| サンプルリクエスト | 全体の一部 | ルールに一致したもの |
| CloudWatch | ACL単位の統計 | ルール単位の統計 |
6.4 WAFv2のログ保存設定
WAFv2 のログ取得の設定を行います。S3バケットと、S3バケットポリシーの json ファイルは作成済とします。S3バケットポリシーの詳細については、『ログ保存用S3バケットポリシーの記載のばらつきと修正例について』のブログをご参照ください。
以下のコマンドで、S3バケットポリシーの json ファイルを S3バケット に適用します。
aws s3api put-bucket-policy \
--bucket "${S3_LOGS_WAF}" \
--policy file://"s3_bucket_policy.${S3_LOGS_WAF}.json"
次に、WAFv2 でログ出力の設定を行います。
ログを記録する Web ACL を ARN で指定し、出力先 S3バケットとパスを指定します。
aws wafv2 put-logging-configuration \
--logging-configuration ResourceArn="${WEB_ACL_ARN}",LogDestinationConfigs="arn:aws:s3:::${S3_LOGS_WAF}/${S3_PREFIX_WAF_1}/"
6.5 WAFv2をALBに関連付け
アクセスコントロールリストが設定された WAFv2 が作成できましたら、WAFv2 を ALB とを紐づけます。
以下のコマンドで、WAFv2 と ALB とを紐づけます。
aws wafv2 associate-web-acl \
--region "${AWS_REGION}" \
--web-acl-arn "${WEB_ACL_ARN}" \
--resource-arn "${ALB_ARN}"
なお、WAFv2 は様々なマネージドサービスと紐づけができますが、Global Accelerator は紐づけできません。
Global Accelerator を使う場合は、WAFv2 は Global Accelerator と連携するマネージドサービスに紐づけます。
そのため、ここでは WAFv2 と ALB を紐づけています。
7. 動作確認②VPC内外のインスタンスから確認
5.1 Global Acceleratorの有効化 の状態では、VPC外のどこからでも Global Accelerator にアクセスできてしまいましたが、WAFv2 と ALB とを紐づけることで、許可したアクセス元以外からはアクセスを拒否する設定にすることができているはずです。
そこで、以下のコマンドで、Global Acceleratorを有効化し、動作確認を行います。(有効化/無効化の操作には多少時間がかかります。)
aws globalaccelerator update-accelerator \
--accelerator-arn "${GA_ARN}" --enabled --region us-west-2
VPC 外のインスタンスからのアクセスは、以下のように拒否されるようになっています。
$ curl -k https://166.117.13.41
<html><head><title>アクセス拒否</title></head><body><h1>アクセスが拒否されました</h1><p>このリソースへのアクセスは許可されていません。<br>管理者にお問い合わせください。</p></body></html>20251020a $
$
VPC 内のインスタンスからのアクセスは、以下のようにアクセスできます。
$ aws ssm start-session --region "${AWS_REGION}" --target "${CHECK_INSTANCE_ID}"
Starting session with SessionId: Participant-***************************
sh-5.2$
sh-5.2$ nslookup www.test-static-ip1.local
Server: 10.0.0.2
Address: 10.0.0.2#53
Non-authoritative answer:
Name: www.test-static-ip1.local
Address: 166.117.13.41
sh-5.2$
sh-5.2$ curl -k https://www.test-static-ip1.local
<h1>Hello </h1>
sh-5.2$
まとめ
本稿では、Global Accelerator で固定の パブリックIPアドレス でアクセスする際に必要と想定されるマネージドサービスの作成について説明してきました。このようなマネージドサービスを設定することで、パブリックIPアドレス を固定化することが可能になることと、実際の構築の流れをご理解いただけたかと思います。
なお本稿では、マネージドサービスやそのリソースの関連付けを図示しながら解説を記載してきました。
一見複雑に見えますが、どのマネージドサービスのどのリソースが何に依存しているのかについて、1つ1つ AWS CLI や設定ファイルを見ていくと、オプションや定義に依存関係が含まれていますので理解できるか思います。
AWS CLI は、同じ構成を何度も繰り返して構築するというような用途には不向きです(そういった用途でしたらIaCが有効です)が、AWS の中身の動きを理解したい場合や、最初に手探りで環境を作っていきたい場合にはとても有効と考えます。そのため今後も、AWS の中身の動きを理解できるよう、AWS CLI を用いた解説ブログを記載していきたいと考えています。
この投稿が皆様のご参考になれば幸いです。













