Route 53别名DNS记录:别名目标名称不在目标区域内

时间:2018-03-25 04:49:05

标签: amazon-web-services dns amazon-route53

我正在尝试为通过路线53购买的域设置别名。别名将指向我网站中的网页,其网址如下:

http://example.com/website/:id

我的api设置了一个带有以下参数的hostsZone:

  var params = {
    CallerReference: req.body.projectId,
    Name: req.body.domain, 
    HostedZoneConfig: {
      Comment: `the zone created on ${today} for ${req.body.domain}`,
      PrivateZone: false
    }
  };

在下一步中,我使用以下参数设置DNS记录:

var params = {
   ChangeBatch: {
    Changes: [
       {
      Action: "CREATE",
      ResourceRecordSet: {
       AliasTarget: {
        DNSName: `http://example.com/website/${req.body.projectId}`,
        EvaluateTargetHealth: false,
        HostedZoneId:  hostedZone.HostedZone.Id
       },
       Name: "example.com",
       Type: "A"
      }
     }
    ],
   },
   HostedZoneId: hostedZone.HostedZone.Id
  };

我收到错误,我的别名目标名称不在目标区域内。我错过了哪一步来正确设置?

1 个答案:

答案 0 :(得分:1)

DNS没有处理路径的机制,因此在这里尝试的是DNS中无法实现的。但似乎这是尝试解决不同的问题。

  

有没有办法路由到通用s3存储桶而不是具有匹配名称的存储桶?

不......是的。

S3依赖于浏览器认为主机名应该是什么,由传入的Host标头表示,以便将请求发送到正确的存储桶。

因此,当S3本身使用时,如果DNS条目指向存储桶,则存储桶名称必须与主机名完全匹配。

对于不同的行为,例如http://bucket.example.com指向名为example-bucket的存储桶,您需要一个反向代理来处理标头重写,以便在浏览器指定Host: bucket.example.com时,S3接收请求与Host: example-bucket.s3.amazonaws.com

CloudFront提供了这样的反向代理功能。

配置CloudFront分配时,您可以指定源域名(指向存储桶)和备用域名,它指定您希望CloudFront从浏览器中获得的内容。 CloudFront会在运行中重写请求,以便S3看到的内容与浏览器发送的内容不同。

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/MigrateS3ToCloudFront.html

正如该页面所述,S3和CloudFront的定价结构使得S3本身或S3 + CloudFront之间的成本差异实际上可以采用任何一种方式 - 实际使用两者的成本相差实际,在存储桶位置,查看器位置,对象大小和缓存命中率(假设您不禁用CloudFront缓存)。

如果您希望https://website-1.example.comexample-bucket的根路径提供website/1/,您也可以这样做,但它会变得有点棘手。

您可以通过在CloudFront中的Origin配置上设置Origin Path来一次性静态地执行此操作,因为此字段表示在将每个请求发送到每个请求之前预先添加到其中的路径前缀。原点。

或者您可以使用带有Lambda @ Edge触发器的CloudFront动态修改它。这可能是什么样的。

'use strict';

// if the end of incoming Host header matches this string, 
// strip this part and prepend the remaining characters onto the request path,
// along with a new leading slash (otherwise, the request will be handled
// with an unmodified path, at the root of the bucket)

const remove_suffix = '.example.com';

// provide the correct origin hostname here so that we send the correct 
// Host header to the S3 website endpoint

const origin_hostname = 'example-bucket.s3-website-us-east-1.amazonaws.com';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const host_header = headers.host[0].value;

    if(host_header.endsWith(remove_suffix))
    {
        // prepend '/' + the subdomain onto the existing request path ("uri")
        request.uri = '/' + host_header.substring(0,host_header.length - remove_suffix.length) + request.uri;
    }

    // fix the host header so that S3 understands the request
    headers.host[0].value = origin_hostname;

    // return control to CloudFront with the modified request
    return callback(null,request);
};

以上是我在the official AWS forum上撰写并发布的示例。它仅适用于S3网站托管功能(不是REST端点),因为这是主机头使用转发的头白名单向Lambda @ Edge公开所必需的。

它从传入的主机名获取前缀,并将其重写为路径前缀,同时将所有请求发送到同一个存储桶。

请注意,您需要在Origin Response触发器中使用补充函数来处理响应,检查HTTP 30x重定向。由于我们正在进行路径前缀,因此需要在反向路径上完成相反的操作,以便正确锚定Location标头的路径。

或者只为每个站点创建一个CloudFront分配 - AWS不会为分发本身收费,仅针对它处理的请求。可以通过自动化轻松创建分发 - 使用aws-cli或CloudFormation编写脚本。每个帐户的CloudFront分配的默认限制为200,但AWS Support会根据请求增加此值。