

# 限制访问应用程序负载均衡器
<a name="restrict-access-to-load-balancer"></a>

您可以在 Amazon CloudFront 上同时使用内部和面向互联网的应用程序负载均衡器。您可以通过使用 VPC 源在 CloudFront 的私有子网内使用内部应用程序负载均衡器。CloudFront VPC 源可让您提供来自私有 VPC 子网中托管的应用程序的内容，而无需将其暴露于公共互联网上。有关更多信息，请参阅 [通过 VPC 源限制访问](private-content-vpc-origins.md)。

如果您在 CloudFront 中使用面向互联网的应用程序负载均衡器，则可以使用以下安全缓解措施来防止用户直接访问应用程序负载均衡器，并仅支持通过 CloudFront 进行访问。

1. 将 CloudFront 配置为将自定义 HTTP 标头添加到向应用程序负载均衡器发送的请求中。

1. 将应用程序负载均衡器配置为仅转发包含自定义 HTTP 标头的请求。

1. 需要 HTTPS 来提高此解决方案的安全性。

CloudFront 还可以帮助减少延迟，甚至吸收一些分布式拒绝服务 (DDoS) 攻击。

如果您的使用案例需要直接通过互联网从 CloudFront 和应用程序负载均衡器双重访问 Web 应用程序，请考虑按如下方式拆分 Web 应用程序 API：
+ 必须通过 CloudFront 访问的 API。在这种情况下，考虑使用单独的私有应用程序负载均衡器作为源。
+ 需要通过应用程序负载均衡器访问的 API。在这种情况下，可以绕过 CloudFront。

或者，对于 Web 应用程序或由弹性负载均衡中面向互联网的应用程序负载均衡器提供的其他内容，CloudFront 可以缓存对象并将它们直接提供给用户（查看器），从而减轻应用程序负载均衡器的负载。面向互联网的负载均衡器具有可公开解析的 DNS 名称，并通过互联网将来自客户端的请求路由到目标。

有关更多信息，请参阅以下主题。完成这些步骤后，用户只能通过 CloudFront 访问您的应用程序负载均衡器。

**Topics**
+ [配置 CloudFront 以便向请求添加自定义 HTTP 标头](#restrict-alb-add-custom-header)
+ [将应用程序负载均衡器配置为仅转发包含特定标头的请求](#restrict-alb-route-based-on-header)
+ [（可选）提高此解决方案的安全性](#restrict-alb-improve-security)
+ [（可选）使用 CloudFront 的 AWS 托管前缀列表限制对源的访问](#limit-access-to-origin-using-aws-managed-prefixes)

## 配置 CloudFront 以便向请求添加自定义 HTTP 标头
<a name="restrict-alb-add-custom-header"></a>

您可以将 CloudFront 配置为将自定义 HTTP 标头添加到向您的源（在本例中为应用程序负载均衡器）发送的请求中。

**重要**  
此使用案例依赖于对自定义标头名称和值保密。如果标头名称和值没有保密，其他 HTTP 客户端可能会将它们包含在直接发送到应用程序负载均衡器的请求中。这可能会导致应用程序负载均衡器的行为看起来就好像请求来自 CloudFront，但实际上请求并非来自 CloudFront。为防止这种情况，请将自定义标头名称和值保密。

您可以使用 CloudFront 控制台、CloudFormation 或 CloudFront API，配置 CloudFront 来向源请求添加自定义 HTTP 标头。

**要添加自定义 HTTP 标头（CloudFront 控制台）**  
在 CloudFront 控制台中，使用**源设置**中的**源自定义标题**设置。输入**标头名称**及其**值**。  
在生产中，使用随机生成的标头名称和值。将标头名称和值视为安全凭证，如用户名和密码。
当您为现有的 CloudFront 分配创建或编辑源时，以及当您创建新分配时，您可以编辑**源自定义标头**设置。有关更多信息，请参阅[更新分配](HowToUpdateDistribution.md)和[创建分配](distribution-web-creating-console.md)。

**要添加自定义 HTTP 标头 (CloudFormation)**  
在 CloudFormation 模板中，使用 `OriginCustomHeaders` 属性，如以下示例所示。  
本示例中的标头名称和值仅用于演示。在生产中，使用随机生成的值。将标题名称和值视为安全凭证，如用户名和密码。

```
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  TestDistribution:
    Type: 'AWS::CloudFront::Distribution'
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: app-load-balancer.example.com
            Id: Example-ALB
            CustomOriginConfig:
              OriginProtocolPolicy: https-only
              OriginSSLProtocols:
                - TLSv1.2
            OriginCustomHeaders:
               - HeaderName: X-Custom-Header
                 HeaderValue: random-value-1234567890
        Enabled: 'true'
        DefaultCacheBehavior:
          TargetOriginId: Example-ALB
          ViewerProtocolPolicy: allow-all
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
        PriceClass: PriceClass_All
        ViewerCertificate:
          CloudFrontDefaultCertificate: 'true'
```
有关更多信息，请参阅《AWS CloudFormation 用户指南》**中的 [Origin](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-origin.html) 和 [OriginCustomHeader](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-origincustomheader.html) 属性。

**添加自定义 HTTP 标头（CloudFront API）**  
在 CloudFront API 中，使用 `CustomHeaders` 中的 `Origin` 对象。有关更多信息，请参阅《Amazon CloudFront API 参考》**中的 [CreateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateDistribution.html) 和 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)，以及有关您的 SDK 或其他 API 客户端的文档。

有些标头名称不能指定为源自定义标头。有关更多信息，请参阅 [CloudFront 无法添加到源请求的自定义标头](add-origin-custom-headers.md#add-origin-custom-headers-denylist)。

## 将应用程序负载均衡器配置为仅转发包含特定标头的请求
<a name="restrict-alb-route-based-on-header"></a>

将 CloudFront 配置为将自定义 HTTP 标头添加到向应用程序负载均衡器发送的请求中后（请参阅[上一部分](#restrict-alb-add-custom-header)），您可以将负载均衡器配置为仅转发包含此自定义标头的请求。您可以通过添加新规则并在负载均衡器的侦听器中修改默认规则来完成此操作。

**先决条件**  
要使用以下过程，您需要至少具有一个侦听器的应用程序负载均衡器。如果您尚未创建应用程序负载均衡器，请参阅《应用程序负载均衡器用户指南》**中的[创建应用程序负载均衡器](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html)。

以下过程将修改 HTTPS 侦听器。您可以使用相同的过程来修改 HTTP 侦听器。

**在应用程序负载均衡器侦听器中更新规则**

1. 添加新规则。按照[添加规则](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-update-rules.html#add-rule)中的说明进行以下修改：
   + 将规则添加到作为 CloudFront 分配源的负载均衡器。
   + 对于**添加条件**，选择 **HTTP 标头**。在 CloudFront 中指定作为源自定义标头添加的 HTTP 标头名称和值。
   + 对于**添加操作**，选择**转发至**。选择要转发请求的目标组。

1. 在负载均衡器的侦听器中编辑默认规则。按照[编辑规则](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-update-rules.html#edit-rule)中的说明进行以下修改：
   + 编辑作为 CloudFront 分配源的负载均衡器的默认规则。
   + 删除默认操作，对于**添加操作**，选择**返回固定响应**。
   + 对于**响应代码**，输入 **403**。
   + 对于**响应正文**，输入 **Access denied**。

完成这些步骤后，负载均衡器侦听器会有两条规则。一条规则转发包含 HTTP 标头的请求（来自 CloudFront 的请求）。另一条规则向所有其他请求（并非来自 CloudFront 的请求）发送固定响应。

您可以通过向 CloudFront 分配发送请求和向应用程序负载均衡器发送一个请求来验证该解决方案是否有效。对 CloudFront 的请求将返回您的 Web 应用程序或内容，直接发送到应用程序负载均衡器的请求将返回`403`带有纯文本消息的响应`Access denied`。

## （可选）提高此解决方案的安全性
<a name="restrict-alb-improve-security"></a>

为了提高此解决方案的安全性，您可以将 CloudFront 分配配置为在向应用程序负载均衡器发送请求时始终使用 HTTPS。请记住，此解决方案仅在您对自定义标头名称和值保密时才有效。使用 HTTPS 可以帮助防止窃听者发现标头名称和值。我们还建议定期轮换标头名称和值。

**使用 HTTPS 进行源请求**  
要将 CloudFront 配置为使用 HTTPS 处理源请求，请将**源协议策略**设置设为**仅限 HTTPS**。此设置可在 CloudFront 控制台、CloudFormation 和 CloudFront API 中使用。有关更多信息，请参阅 [协议（仅自定义源）](DownloadDistValuesOrigin.md#DownloadDistValuesOriginProtocolPolicy)。

当您将 CloudFront 配置为使用 HTTPS 处理源请求时，以下规则也适用：
+ 您必须将 CloudFront 配置为使用源请求策略将 `Host` 标头转发到源。您可以使用 [AllViewer 托管源请求策略](using-managed-origin-request-policies.md#managed-origin-request-policy-all-viewer)。
+ 确保应用程序负载均衡器具有 HTTPS 侦听器（如[上一节](#restrict-alb-route-based-on-header)中所示）。有关更多信息，请参阅《应用程序负载均衡器用户指南》**中的[创建 HTTPS 侦听器](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html)。使用 HTTPS 侦听器要求您拥有与路由到应用程序负载均衡器的域名匹配的 SSL/TLS 证书。
+ 只能在 AWS Certificate Manager（ACM）中的 `us-east-1` AWS 区域 中请求（或导入）CloudFront 的 SSL/TLS 证书。由于 CloudFront 是一项全球服务，因此它会自动将证书从 `us-east-1` 区域分发到与您的 CloudFront 分配关联的所有区域。
  + 例如，如果您在 `ap-southeast-2` 区域拥有应用程序负载均衡器（ALB），则必须在 `ap-southeast-2` 区域（用于在 CloudFront 和 ALB 源之间使用 HTTPS）和 `us-east-1` 区域（用于在查看器和 CloudFront 之间使用 HTTPS）中配置 SSL/TLS 证书。这两个证书都应与路由到应用程序负载均衡器的域名匹配。有关更多信息，请参阅 [用于 AWS Certificate Manager 的 AWS 区域](cnames-and-https-requirements.md#https-requirements-aws-region)。
+ 如果 Web 应用程序的最终用户（也称为*查看器*或*客户端*）可以使用 HTTPS，则还可以将 CloudFront 配置为首选（甚至需要）来自最终用户的 HTTPS 连接。为此，请使用**查看器协议策略**设置。您可以将其设置为将最终用户从 HTTP 重定向到 HTTPS，或拒绝使用 HTTP 的请求。此设置可在 CloudFront 控制台、CloudFormation 和 CloudFront API 中使用。有关更多信息，请参阅 [查看器协议策略](DownloadDistValuesCacheBehavior.md#DownloadDistValuesViewerProtocolPolicy)。

**轮换标头名称和值**  
除了使用 HTTPS 之外，还建议定期轮换标头名称和值。执行此操作的高级步骤如下：

1. 将 CloudFront 配置为将另一个自定义 HTTP 标头添加到向应用程序负载均衡器发送的请求中。

1. 更新应用程序负载均衡器侦听器规则，以转发包含另一个自定义 HTTP 标头的请求。

1. 配置 CloudFront 以停止将原始自定义 HTTP 标头添加到向应用程序负载均衡器发送的请求中。

1. 更新应用程序负载均衡器侦听器规则，以停止转发包含原始自定义 HTTP 标头的请求。

有关完成这些步骤的更多信息，请参阅前面的部分。

## （可选）使用 CloudFront 的 AWS 托管前缀列表限制对源的访问
<a name="limit-access-to-origin-using-aws-managed-prefixes"></a>

要进一步限制对应用程序负载均衡器的访问，您可以配置与应用程序负载均衡器关联的安全组，使其在服务使用 AWS 托管前缀列表时仅接受来自 CloudFront 的流量。这可以防止来自 CloudFront 以外的流量到达应用程序负载均衡器的网络层（第 3 层）或传输层（第 4 层）。

有关更多信息，请参阅 [Limit access to your origins using the AWS-managed prefix list for Amazon CloudFront](https://aws.amazon.com//blogs/networking-and-content-delivery/limit-access-to-your-origins-using-the-aws-managed-prefix-list-for-amazon-cloudfront/) 博客文章。