![]() |
こんにちは、広野です。
ちょうど書いていた記事が夏休みシーズンだったので、会社の自由研究扱いにしてしまいました。w
さて。
2025 年 3 月に AWS Amplify Hosting でホストされたサイトに AWS WAF の Web ACL をアタッチすることができるようになりました。
少々使ってみたい要件があったので、やってみて気付いた点を書き残しておこうと思います。
やりたいこと
あえて簡単にひとことで言うと、以下をやりたかったです。
- 指定した IPv4 アドレス (またはサブネット) からのみサイトへのアクセスを許可したい。
結論から言うと、特定の条件が引っかかって実現できなかったのですが。
従来のソリューションとの比較
冒頭の新機能がリリースされるまでは、以下のソリューションがありました。
- AWS Amplify に Amazon CloudFront をかぶせて、AWS WAF をアタッチします。
Amplify Hosting で Wrapping された Amazon CloudFront には AWS WAF をアタッチできなかったので、二重に Amazon CloudFront が存在します。
- もう 1 つは、AWS Amplify を使用せず、Amazon CloudFront を組み込んだアプリ基盤を構築し、AWS WAF をアタッチします。
私の過去のブログで紹介した方法です。
新しいソリューションでは、以下の図のように AWS Amplify Hosting で Wrapping された Amazon CloudFront に直接 AWS WAF をアタッチできるようになったわけです。おそらく、多くの要件はこの構成を活用して実現できると思います。
ソース IP アドレス制限をかけるときの注意
実は、ソース IP アドレス制限をかけるときには注意事項があります。
まず、IP アドレスには IPv4 と IPv6 があります。ソース IP アドレス制限をかけるときには IPv4 で設定するのが一般的かつ現実的です。IPv6 でも設定はできるのですが、IPv6 はソース IP アドレスが頻繁に変わることがあり、レンジ設定も難しく、実質制御できないと思った方がよいです。
そのため、AWS Amplify Hosting のサイトに IPv4 のみでアクセスできるようにしたいのですが、条件によってはそれができません。
仕様上、AWS Amplify は IPv4 と IPv6 を同時に利用可能とする デュアルスタック をサポートしており、いろいろと確認したところカスタムドメインを使用していると IPv4 通信のみを利用可能とする構成がサポートされていませんでした。
「いや、うちの会社のインターネットは IPv4 しか使ってないから問題ないよ」
このケースであれば問題ありません。素直に最初から最後まで IPv4 通信をしてきてくれますので。
ですが、世の中には IPoE なる IPv6 ネイティブの通信が既に普及してきており、IPoE ユーザーは IPv4 網を経由せずダイレクトに IPv6 の AWS Amplify Hosting サイトに到達してしまいます。このとき、ソース IP アドレスは IPv6 アドレスになり、Web ACL で 100% 拒否されてしまうのです。つまり、IPoE ユーザーは全くサイトにアクセスできないということです。
この通信のイメージは以下です。
もしも AWS Amplify Hosting が IPv6 を無効にできるなら、以下の図のように Web ACL が成り立ちます。
本当はこうしたいのです。※できません。
結論
結局、IPv4 ベースのソース IP アドレス制限は AWS Amplify + AWS WAF では完全にはできません。アクセス元が必ず IPv4 で通信してきてくれるなら、という条件付きで実現可能です。
純粋 Amazon CloudFront であれば IPv6 を無効にできるので、完全に実現できるのは従来のソリューションのままです。
Amazon Route 53 で別のレコードをかぶせればいけるか?とも思ったのですが、難しいと思いました。いずれにしてももう少し手を加えればできる方法はあるのかもしれません。
AWS Amplify に限らず、他の AWS サービスでもデュアルスタックのみしかサポートしていないリソースに AWS WAF をアタッチする場合は同じことが発生します。
補足すると、IPv4 over IPv6 を経由したソース IPv4 アドレスは一般的には別契約の他者と共有されているので、それだけを完全に信用したソース IP アドレス制限は危険です。ただし、プロバイダーのオプションで専用ソース IPv4 アドレスを提供してくれる IPoE 接続サービスもあるので、その場合は問題ないと思います。ネイティブな IPv4 でも、クラウドのセキュリティプロキシサービスを経由しているとソース IP アドレスを別契約の他者と共有するケースがあるので、その場合も信用はできません。もはやソース IP アドレス安全神話は崩れてきているなぁと思っています。
おまけ AWS CloudFormation テンプレート
AWS Amplify Hosting に AWS WAF をアタッチする AWS CloudFormation テンプレートを参考までに貼り付けます。
今回検証した構成なので実用的ではありませんが、AWS CloudFormation だとこう書けばデプロイできるというのがわかるぐらいのものと思っていただければ。
AWS Amplify のリージョンに関わらず、バージニア北部リージョンでデプロイする必要があります。AWS Amplify Hosting アプリケーションの ARN がインプットとして必要です。テンプレート内に記入している IP アドレスは例のために書いたもので、実際には有り得ない値です。
AWSTemplateFormatVersion: 2010-09-09 Description: The CloudFormation template that creates a WAF web acl for Amplify hosting. This template must be deployed in us-east-1 region only. # ------------------------------------------------------------# # Input Parameters # ------------------------------------------------------------# Parameters: SystemName: Type: String Description: System name. use lower case only. (e.g. example) Default: example MaxLength: 10 MinLength: 1 SubName: Type: String Description: System sub name. use lower case only. (e.g. prod or dev) Default: dev MaxLength: 10 MinLength: 1 AmplifyArn: Type: String Description: The target Amplify ARN. Default: arn:aws:amplify:xxxxxxxxxxxx:999999999999:apps/xxxxxxxxxxxx AllowedPattern: ^arn:aws:amplify:.+:\d{12}:apps\/.+$ SourceIpv4RangeList: Type: CommaDelimitedList Description: The comma delimited list of allowed source IPv4 address range (CIDR) except /0 to access this web site. (e.g. xxx.xxx.xxx.xxx/xx,yyy.yyy.yyy.yyy/yy) Default: "192.168.0.0/24,8.8.8.8/32" LogRetentionDays: Type: Number Description: The retention period (days) for AWS WAF logs. Enter an integer between 35 to 540. Default: 400 MaxValue: 540 MinValue: 35 Resources: # ------------------------------------------------------------# # WAF Web Acl for Amplify # ------------------------------------------------------------# WebAclAmplify: Type: AWS::WAFv2::WebACL Properties: Name: !Sub ${SystemName}-${SubName}-amplify Description: !Sub WAFv2 WebAcl for Amplify ${SystemName}-${SubName} Scope: CLOUDFRONT DefaultAction: Block: {} Rules: - Name: !Sub CustomRule-IpWhiteList-${SystemName}-${SubName} Action: Allow: {} Priority: 0 Statement: IPSetReferenceStatement: Arn: !GetAtt Ipv4WhiteList.Arn VisibilityConfig: CloudWatchMetricsEnabled: true MetricName: !Sub CustomRule-IpWhiteList-${SystemName}-${SubName} SampledRequestsEnabled: true VisibilityConfig: CloudWatchMetricsEnabled: true MetricName: !Sub WebAcl-${SystemName}-${SubName} SampledRequestsEnabled: true Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} DependsOn: - Ipv4WhiteList Ipv4WhiteList: Type: AWS::WAFv2::IPSet Properties: Name: !Sub Ipv4WhiteList-${SystemName}-${SubName} Description: WAF v2 IPv4 white list for the IP-based restricted access IPAddressVersion: IPV4 Addresses: !Ref SourceIpv4RangeList Scope: CLOUDFRONT Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} WebAclAssociationAmplify: Type: AWS::WAFv2::WebACLAssociation Properties: ResourceArn: !Ref AmplifyArn WebACLArn: !GetAtt WebAclAmplify.Arn DependsOn: - WebAclAmplify WebAclLoggingConfigurationAmplify: Type: AWS::WAFv2::LoggingConfiguration Properties: ResourceArn: !GetAtt WebAclAmplify.Arn LogDestinationConfigs: - !GetAtt S3BucketWafLogs.Arn LoggingFilter: DefaultBehavior: KEEP Filters: - Behavior: KEEP Conditions: - ActionCondition: Action: BLOCK Requirement: MEETS_ANY DependsOn: - S3BucketWafLogs - WebAclAmplify # ------------------------------------------------------------# # S3 # ------------------------------------------------------------# S3BucketWafLogs: Type: AWS::S3::Bucket Properties: BucketName: !Sub aws-waf-logs-${SystemName}-${SubName} LifecycleConfiguration: Rules: - Id: AutoDelete Status: Enabled ExpirationInDays: !Ref LogRetentionDays OwnershipControls: Rules: - ObjectOwnership: BucketOwnerEnforced PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName}
まとめ
いかがでしたでしょうか。
期待していた AWS Amplify Hosting への AWS WAF アタッチ機能でしたが、機能しないケースもあるという紹介でした。
本記事が皆様のお役に立てれば幸いです。