根据 IP 地理位置,将不同的来源作为 DNS CNAME 值

Posted

技术标签:

【中文标题】根据 IP 地理位置,将不同的来源作为 DNS CNAME 值【英文标题】:Serve different origin as DNS CNAME value, depending on the IP Geolocation 【发布时间】:2021-06-15 11:33:50 【问题描述】:

我有 Next.js 应用程序,它部署为 Lambda Edge 和 Cloudfront,它以 S3 静态文件作为源。 AWS Cloudfront URL 是 example-domain.com CNAME 的值。

现在我对应用程序进行了很多更改,我想部署这些更改。 我不希望这些更改覆盖当前部署,而是我想创建新环境,并且该环境应该在少数国家/地区可用。

所以在这种情况下,我将有 2 个不同的 Cloudfront URL:

oldfeatures.cloudfront.net newfeatures.cloudfront.net

应根据地理位置提供不同的来源网址。

我不确定这是不是正确的方法,但我愿意接受建议。

我在 Cloudflare 中管理域设置,其余的都是 AWS 环境。

如何在不更改应用程序代码的情况下实现这一点。

【问题讨论】:

您是否为您的域启用了 cloudflare 代理? 你在做某种金丝雀发布或 A/B 测试吗?或者您实际上每个县(组)都有单独的版本? 我想要单独的版本。旧版本将留在世界其他地方,新版本应可用于国家列表 您应该在代码中正确执行此操作,因为维护单独的版本很快就会变得非常混乱...... 【参考方案1】:

最简单(且具有成本效益)的选项是创建一个 Cloudflare (CF) Worker 并将其附加到您的子域。可能最好将其附加到两个子域,以确保它们在“不允许”时无法手动访问newfeatures.cloudfront.net URL。第二种选择是使用 CF 负载均衡器功能附带的CF Traffic Steering。此选项的成本很低,并且可能并不真正适合您的用例 - 它根据地区而不是国家/地区进行重定向 - 我相信您需要花更多的钱并获得一个企业帐户来进行基于国家/地区的转向。

也就是说,以下使用 CF Worker javascript 的选项将要求您打开 CF 代理(橙色云)。

这里有 3 个选项可以满足您的要求 - 根据我对您问题的理解推荐选项 1。

addEventListener('fetch', event => 
    event.respondWith(handleRequest(event.request))
)


async function handleRequest(request) 
    return setRedirect(request) //Change to appropriate function 



// Option 1
// Return same newfeatures URL for specific countries based on a country list
// Useful if single URL applies for many countries - I guess that's your case
async function setRedirect(request) 
    const country = request.cf.country
    var cSet = new Set(["US", 
                        "ES", 
                        "FR", 
                        "CA", 
                        "CZ"]);

    if (cSet.has(country))   
        return Response.redirect('https://newfeatures.cloudfront.net', 302);
    
    // Else return oldfeatures URL for all other countries
    else 
        return await fetch(request)
    


// Option 2
const countryMap = 
    US: "https://newfeatures1.cloudfront.net", //URL1
    CA: "https://newfeatures2.cloudfront.net", //URL2
    FR: "https://newfeatures3.cloudfront.net"  //URL3


// Return different newfeatures URL for specific countries based on a map 
// Useful if more than two URLs
async function mapRedirect(request) 
    const country = request.cf.country
    
    if (country != null && country in countryMap) 
      const url = countryMap[country]
      return Response.redirect(url, 302)
    
    // Else return old features for all other countries
    else 
      return await fetch(request)
    


// Option 3
// Return single newfeatures URL for a single country.
// Much simpler one if you only have one specific country to redirect.
async function singleRedirect(request)  
    const country = request.cf.country
    if (country == 'US')
        return Response.redirect('https://newfeatures.cloudfront.net', 302)
    
    // Else return oldfeatures URL for all other countries
    else 
        return await fetch(request)
    

【讨论】:

所有 DNS 记录都应该保持不变吗?例如:类型:CNAME 名称:example-domain.com 内容:oldfeatures.cloudfront.net 我不确定我是否正确理解了您的问题 - 新旧功能域的情况如何?

以上是关于根据 IP 地理位置,将不同的来源作为 DNS CNAME 值的主要内容,如果未能解决你的问题,请参考以下文章

服务器负载均衡-文章整理

Linux服务器作为网关的DNS分离解析服务(CentOS 7版本)

DNS Doctoring

DNS分离解析

是否可以在C ++中以编程方式查询不同的DNS名称服务器,忽略系统设置?

实现dns视图