View a markdown version of this page

访问 AWS Transform 来自 VPC 的 Web 应用程序 - AWS 转换

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

访问 AWS Transform 来自 VPC 的 Web 应用程序

当您使用 AWS PrivateLink 从 VPC 私下访问 AWS Transform API 时,Web 应用程序需要额外的网络配置。它通过提供静态内容(HTML JavaScript、、CSS) CloudFront,这需要互联网连接。来自 Web 应用程序的 API 调用将通过您的 VPC 终端节点进行并保持完全私密状态。

本指南向您介绍如何配置来自您的 VPC 的受控互联网出口,这样 Web 应用程序就可以加载,同时将 VPC 锁定到所需的域。

工作原理

AWS Transform Web 应用程序使用两条网络路径:

  • API 调用 — 当您与 Web 应用程序交互(启动作业、查看工作区等)时,浏览器会向发送 API 请求。api.transform.region.on.aws启用 com.amazonaws.region.api.transform VPC 终端节点和私有 DNS 后,这些请求将解析到您的 VPC 中的私有 IP 地址,并且永远不会离开 AWS 网络。

  • 静态内容 — CloudFront 通过提供 Web 应用程序的 HTML 和 CSS 文件tenant-id.transform.region.on.aws。 JavaScript加载这些文件需要互联网连接,因为 CloudFront 内容交付只能通过公共互联网进行。

  • 身份验证 — AWS IAM Identity Center 登录流程使用region.signin.aws,这也需要互联网连接。

要在维护安全的同时启用 Web 应用程序,您可以使用带有基于域的筛选的 Network Fire AWS wall 创建受控的出口路径。这允许您的 VPC 访问 Web 应用程序所需的特定域,同时阻止所有其他互联网流量。

架构

下图显示了 Web 应用程序流量的网络路径:

EC2 Instance / Workspace (Private Subnet) | | Route: 0.0.0.0/0 → Network Firewall Endpoint v AWS Network Firewall (Firewall Subnet) | Allows: *.cloudfront.net, *.transform.<region>.on.aws, | <region>.signin.aws, SSO domains, S3 presigned URLs | Blocks: everything else (TLS SNI inspection) | | Route: 0.0.0.0/0 → NAT Gateway v NAT Gateway (Public Subnet) | | Route: 0.0.0.0/0 → Internet Gateway v Internet Gateway → CloudFront Edge Locations
重要

Network Firewall 必须看到流量的两个方向(对称路由)才能执行 TLS SNI 检查。您必须在 NAT Gateway 子网中配置一条返回路由,以便通过防火墙将发往私有子网的流量发送回去。否则,基于域的过滤规则将无法运行。

先决条件

在开始之前,请确保您满足以下条件:

  • 有权创建 VPC 资源、Network Firewall 和 NAT 网关的 AWS 账户。

  • 带有私有子网的 VPC,您的实例或工作负载可以在其中运行。

  • 连接到 VPC 的互联网网关(或创建网关的权限)。

  • 启用了 AWS Transform 私有 DNS 的 com.amazonaws.region.api.transform VPC 终端节点。这是 Web 应用程序浏览器客户端使用的端点。有关创建端点的说明,请参阅AWS Transform 和接口端点 (AWS PrivateLink)

配置 VPC 终端节点策略

如果您的 com.amazonaws.region.api.transform VPC 终端节点具有自定义终端节点策略,则必须添加允许 AWS Transform 操作的声明。否则,Web 应用程序将无法通过端点进行 API 调用。

将以下声明添加到您的 VPC 终端节点策略中。AWS_TRANSFORM_PROFILE_ARN替换为您的 AWS Transform 服务配置文件 ARN,您可以在 AWS Transform 控制台的 “设置” 页面上找到该配置文件。

{ "Statement": [ { "Sid": "AllowAWSTransform", "Effect": "Allow", "Principal": "*", "Action": "*", "Resource": "*", "Condition": { "StringEquals": { "aws:PrincipalArn": [ "AWS_TRANSFORM_PROFILE_ARN" ] } } } ] }
注意

如果您的 VPC 终端节点使用默认策略(完全访问权限),则无需进行任何更改,您可以跳过此步骤。

设置受控的互联网出口

完成以下步骤,为 AWS Transform Web 应用程序配置 Network Firewall 使用基于域的筛选。

步骤 1:创建防火墙子网

创建一个专用 Network Firewall 端点的小型 /28 子网。该子网必须与您的私有子网位于同一个可用区。

aws ec2 create-subnet \ --vpc-id your-vpc-id \ --cidr-block firewall-subnet-cidr \ --availability-zone your-az \ --region region

步骤 2:为 NAT 网关创建公有子网

aws ec2 create-subnet \ --vpc-id your-vpc-id \ --cidr-block public-subnet-cidr \ --availability-zone your-az \ --region region

步骤 3:配置公有子网路由表

为将互联网流量路由到互联网网关的公有子网创建路由表。

# Create route table PUB_RTB=$(aws ec2 create-route-table \ --vpc-id your-vpc-id \ --region region \ --query 'RouteTable.RouteTableId' --output text) # Add default route to internet gateway aws ec2 create-route \ --route-table-id $PUB_RTB \ --destination-cidr-block 0.0.0.0/0 \ --gateway-id your-igw-id \ --region region # Associate with public subnet aws ec2 associate-route-table \ --route-table-id $PUB_RTB \ --subnet-id public-subnet-id \ --region region

步骤 4:创建 NAT 网关

# Allocate an Elastic IP EIP=$(aws ec2 allocate-address --domain vpc \ --region region --query 'AllocationId' --output text) # Create NAT Gateway in the public subnet NAT_ID=$(aws ec2 create-nat-gateway \ --subnet-id public-subnet-id \ --allocation-id $EIP \ --region region \ --query 'NatGateway.NatGatewayId' --output text) # Wait for NAT Gateway to become available (~2 minutes) aws ec2 wait nat-gateway-available \ --nat-gateway-ids $NAT_ID --region region

步骤 5:创建 Network Firewall 规则组

创建一个状态规则组,该组仅允许流向 AWS Transform Web 应用程序所需的域的流量。

aws network-firewall create-rule-group \ --rule-group-name transform-webapp-domains \ --type STATEFUL \ --capacity 100 \ --rule-group '{ "StatefulRuleOptions": { "RuleOrder": "STRICT_ORDER" }, "RulesSource": { "RulesSourceList": { "Targets": [ ".cloudfront.net", ".transform.region.on.aws", "region.signin.aws", ".s3.region.amazonaws.com", "oidc.region.amazonaws.com", "portal.sso.region.amazonaws.com", "assets.sso-portal.region.amazonaws.com", "directory-id.awsapps.com" ], "TargetTypes": ["TLS_SNI", "HTTP_HOST"], "GeneratedRulesType": "ALLOWLIST" } } }' \ --region region

region替换为安装您的 AWS Transform 配置文件的地 AWS 区(例如,us-east-1)。directory-id替换为您的 IAM 身份中心目录 ID(例如,d-1234567890)。您可以在 IAM 身份中心控制台中找到您的目录 ID。

下表说明了允许的域。

域: 用途
.cloudfront.net CloudFront CDN — 提供 Web 应用程序静态资产(JavaScript、CSS、图像)
.transform.region.on.aws Web 应用程序租户 URL — 浏览器通过以下方式从该域加载初始页面 CloudFront
region.signin.aws SSO 登录重定向页面
.s3.region.amazonaws.com S3 预签名 URL-工件上传和下载
oidc.region.amazonaws.com 用于 SSO 身份验证的 OIDC 令牌交换
portal.sso.region.amazonaws.com SSO 门户登录页面
assets.sso-portal.region.amazonaws.com SSO 门户网站静态资产 (CSS、 JavaScript)
directory-id.awsapps.com 适用于您的组织的 IAM 身份中心门户
注意

.cloudfront.net通配符允许任何 CloudFront分发的流量,而不仅仅是 AWS Transform Web 应用程序的流量。不可能使用更窄的域过滤器,因为 CloudFront 边缘 IP 是跨分布共享的,而且 TLS SNI 检查无法区分同一域下的各个分布。

注意

API 调用api.transform.region.on.aws可以通过 AWS PrivateLink ,不需要互联网出口。它们不受防火墙的影响。

步骤 6:创建防火墙策略

策略必须使用STRICT_ORDER规则评估drop_established作为默认操作。这样可以确保丢弃所有与许可名单不匹配的流量。

# Get the rule group ARN RG_ARN=$(aws network-firewall describe-rule-group \ --rule-group-name transform-webapp-domains \ --type STATEFUL --region region \ --query 'RuleGroupResponse.RuleGroupArn' --output text) # Create the firewall policy aws network-firewall create-firewall-policy \ --firewall-policy-name transform-webapp-policy \ --firewall-policy "{ \"StatelessDefaultActions\": [\"aws:forward_to_sfe\"], \"StatelessFragmentDefaultActions\": [\"aws:forward_to_sfe\"], \"StatefulRuleGroupReferences\": [ { \"ResourceArn\": \"$RG_ARN\", \"Priority\": 1 } ], \"StatefulEngineOptions\": { \"RuleOrder\": \"STRICT_ORDER\" }, \"StatefulDefaultActions\": [\"aws:drop_established\", \"aws:alert_established\"] }" \ --region region

步骤 7:创建 Network Firewall

# Get the policy ARN FW_POLICY_ARN=$(aws network-firewall describe-firewall-policy \ --firewall-policy-name transform-webapp-policy \ --region region \ --query 'FirewallPolicyResponse.FirewallPolicyArn' --output text) # Create the firewall aws network-firewall create-firewall \ --firewall-name transform-webapp-firewall \ --firewall-policy-arn $FW_POLICY_ARN \ --vpc-id your-vpc-id \ --subnet-mappings SubnetId=firewall-subnet-id \ --region region # Wait for the firewall to become READY (3-5 minutes) while true; do STATUS=$(aws network-firewall describe-firewall \ --firewall-name transform-webapp-firewall \ --region region \ --query 'FirewallStatus.Status' --output text) echo "Status: $STATUS" if [ "$STATUS" = "READY" ]; then break; fi sleep 15 done

步骤 8:获取防火墙端点 ID

FW_ENDPOINT=$(aws network-firewall describe-firewall \ --firewall-name transform-webapp-firewall \ --region region \ --query "FirewallStatus.SyncStates.\"your-az\".Attachment.EndpointId" \ --output text) echo "Firewall endpoint: $FW_ENDPOINT"

步骤 9:配置防火墙子网路由表

将互联网流量从防火墙子网路由到 NAT 网关。

FW_RTB=$(aws ec2 create-route-table \ --vpc-id your-vpc-id \ --region region \ --query 'RouteTable.RouteTableId' --output text) aws ec2 create-route \ --route-table-id $FW_RTB \ --destination-cidr-block 0.0.0.0/0 \ --nat-gateway-id $NAT_ID \ --region region aws ec2 associate-route-table \ --route-table-id $FW_RTB \ --subnet-id firewall-subnet-id \ --region region

步骤 10:更新私有子网路由表

将来自私有子网的所有互联网流量路由到防火墙。

aws ec2 create-route \ --route-table-id private-subnet-route-table-id \ --destination-cidr-block 0.0.0.0/0 \ --vpc-endpoint-id $FW_ENDPOINT \ --region region

如果已存在默认路由,请使用replace-route而不是create-route

步骤 11:添加对称回程路由(必填)

重要

这一步至关重要。Network Firewall 使用 TLS SNI 检查,并且必须看到 TCP 连接的两个方向。在 NAT Gateway 子网的路由表中添加一条路由,该路由将发往私有子网的返回流量通过防火墙发送回去。

aws ec2 create-route \ --route-table-id $PUB_RTB \ --destination-cidr-block private-subnet-cidr \ --vpc-endpoint-id $FW_ENDPOINT \ --region region

private-subnet-cidr替换为私有子网的 CIDR 块(例如10.0.144.0/20)。

如果没有对称路由,防火墙只能看到一个方向的流量。TLS 检查引擎无法从 TLS 握手中提取服务器名称指示 (SNI),并且所有基于域的规则都将静默失败。

步骤 12:删除 IPv6 默认路由(如果存在)

如果私有子网路由表有直接指向互联网网关的 IPv6 默认路由 (::/0),它将绕过防火墙 IPv6-capable 前往目的地。将其删除:

aws ec2 delete-route \ --route-table-id private-subnet-route-table-id \ --destination-ipv6-cidr-block ::/0 \ --region region

验证

在私有子网中的实例中,验证配置:

# Should SUCCEED - web application content via CloudFront (allowed) curl -vL --connect-timeout 15 \ 'https://tenant-id.transform.region.on.aws' # Should SUCCEED - API via PrivateLink (does not use firewall) curl -v --connect-timeout 15 \ 'https://api.transform.region.on.aws/' # Should FAIL - non-allowlisted domain (blocked by firewall) curl -v --connect-timeout 15 'https://www.example.com' # Expected: TLS connection error (firewall drops after SNI inspection)

问题排查

你的防火墙阻止了对 api.transform 的 API 调用

该域api.transform.region.on.aws应通过 VPC 终端节点解析为私有 IP 地址,并且不应到达您的互联网防火墙。

  • 确认您已创建com.amazonaws.region.api.transform终端节点。

  • 验证终端节点上是否启用了私有 DNS:

    aws ec2 describe-vpc-endpoints \ --filters "Name=service-name,Values=com.amazonaws.region.api.transform" \ --query 'VpcEndpoints[*].[State,PrivateDnsEnabled]' \ --output table

    预期输出:available | True

Web 应用程序无法加载(连接超时)
  • 验证私有子网路由表中是否有指向防火墙端点的0.0.0.0/0路由。

  • 验证防火墙子网路由表中是否有指向 NAT 网关的0.0.0.0/0路由。

  • 验证 NAT 网关是否处于available状态。

Non-allowlisted 域名未被屏蔽
  • 检查是否有指向互联网网关的 IPv6 ::/0 路由。这会绕过防火墙。将其删除(步骤 12)。

  • 验证是否配置了对称路由。NAT 网关子网路由表必须有穿过防火墙的私有子网 CIDR 的返回路由(步骤 11)。

  • 验证防火墙策略是否STRICT_ORDER使用drop_establishedalert_established作为默认操作。

成本注意事项

资源 大概成本
Network Firewall ~0 美元。 395/hr 每个可用区 (~$288/month)
NAT 网关 ~0 美元。 045/hr (~$33/month) + 数据处理费
弹性 IP(公有 IPv4) ~0 美元。 005/hr (大约 3 美元。 60/month)
Network Firewall 数据处理 0 美元。 065/GB
NAT 网关数据处理 0 美元。 045/GB

单个可用区部署325/month 的估计基本成本约为 $。对于生产部署,请在存在私有子网的每个可用区中部署防火墙、NAT 网关和关联子网。

资源清理

要删除本指南创建的所有资源,请按相反顺序运行以下命令。将占位符替换为部署中的资源 ID。您可以在 AWS 管理控制台中找到这些值,也可以使用设置步骤中的describe命令来找到。

# Remove return route from NAT Gateway subnet aws ec2 delete-route --route-table-id pub-rtb-id \ --destination-cidr-block private-subnet-cidr \ --region region # Remove route from private subnet aws ec2 delete-route \ --route-table-id private-subnet-route-table-id \ --destination-cidr-block 0.0.0.0/0 --region region # Delete Network Firewall (takes ~5 minutes) aws network-firewall delete-firewall \ --firewall-name transform-webapp-firewall \ --region region # Delete firewall policy and rule group aws network-firewall delete-firewall-policy \ --firewall-policy-name transform-webapp-policy \ --region region aws network-firewall delete-rule-group \ --rule-group-name transform-webapp-domains \ --type STATEFUL --region region # Delete NAT Gateway (wait ~5 minutes for full deletion) aws ec2 delete-nat-gateway --nat-gateway-id nat-gateway-id \ --region region # Release Elastic IP aws ec2 release-address --allocation-id eip-allocation-id \ --region region # Delete subnets aws ec2 delete-subnet --subnet-id firewall-subnet-id \ --region region aws ec2 delete-subnet --subnet-id public-subnet-id \ --region region