如何克服根域CNAME限制?

128
我们为多位客户托管许多Web应用程序。显然,他们想要使用自己的域名来引用这些应用程序,通常他们希望任何输入http://www.customer1.examplehttp://customer1.example的用户都进入他们的Web应用程序。
我们面临的问题是,我们需要在不久的将来灵活地更改IP地址。我们不想依赖客户对其域名进行A记录更改。因此,我们认为使用CNAME记录可以解决问题,但我们发现CNAME记录无法用于根域名。
基本上:
customer1.example IN CNAME customer1.mycompanydomain.example //this is invalid as the RFC
www.customer1.example IN CNAME customer1.mycompanydomain.example //this is valid and will work
我们希望能够更改customer1.mycompanydomain.example的IP地址或A记录,并且我们的客户将遵循我们可以控制的这个记录。
在我们的DNS中,它将如下所示:
customer1.mycompanydomain.example IN A 192.0.2.1
任何想法?

3
好的,以下是需要翻译的内容:根据DNS RFC,将根域名CNAME到其他域名是无效的。请阅读以下问题和答案。 - Geo
2
我不理解问题的标题。 "root"(根)在哪里涉及? - bortzmeyer
2
他的意思是区域的根,而不是“根”。 - Alnitak
2
好的,这不是通常的DNS词汇。 难道“apex”是正确的词吗? 还是对于Lisp程序员来说“top-level”更合适? :-) - bortzmeyer
有一件事要补充:我在大学时为我管理的一个网站做了这个,但由于违反规范,大学网络的DNS拒绝解析该域名。我建议您避免尝试这样做,因为这可能会切断您的一些用户 :) - wjdp
显示剩余3条评论
10个回答

68
这个问题经常出现的原因是,正如你所提到的,某个被认为很重要的人写过RFC规定没有子域名的域名是无效的。然而,如果你仔细阅读RFC,你会发现它并不完全是那么说的。实际上,RFC 1912规定:
“不要过度使用CNAME。在重命名主机时使用它们,但是计划摆脱它们(并告知用户)。 ”
一些DNS主机提供了一种在区域顶级(裸域名)使用类似于CNAME的功能的方法,使用自定义记录类型。这些记录包括:
- DNSimple的ALIAS - DNS Made Easy的ANAME - easyDNS的ANAME - CloudFlare的CNAME
对于每个提供商,设置类似:将您的顶级域名的ALIAS或ANAME条目指向example.domain.com,就像使用CNAME记录一样。 根据DNS提供商的不同,空值或@ Name值标识区域顶级。

ALIAS,ANAME或@,例如example.domain.com。

如果您的DNS提供商不支持此记录类型,并且您无法切换到支持该记录类型的DNS提供商,则需要使用子域重定向。这并不难,取决于需要执行它的协议或服务器软件。

我强烈反对这种说法,认为只有“业余管理员”才会这样做。这是一个简单的“名称和其服务需要做什么?”问题,然后调整您的DNS配置以满足这些要求;如果您的主要服务是Web和电子邮件,则我不认为放弃CNAME会有任何有效的原因。毕竟,谁会喜欢@subdomain.domain.org而不是@domain.org?如果您已经设置了协议本身,谁需要“www”?假设使用根域名无效是不合逻辑的。


1
这个特定的答案对我非常有帮助,因为我想将根级域名指向CDN。大多数CDN都必须是FQDN,因为它在不同的位置或时间可能会解析到不同的IP。我使用DNS Made Easy,并能够使用ANAME记录类型。 - Rubix
3
我完全同意。希望使用“裸”域名来托管网站是一件常见且合理的事情。它使用的字符更少,看起来更好等等。URL自己的协议标识符(www)是URL中的一个残留部分,如果一开始不需要它的话(实际上并不需要)。 - Ed Bishop
3
可以使用免费的301重定向服务将非www网址全部重定向到www网址,这样做很好。http://198.251.86.133 - Jacob Evans

57

CNAME记录根节点在技术上并不违反RFC,但是有限制条件,这意味着这种做法并不被推荐。

通常情况下,您的根记录将有多个条目。例如,3个用于您的名称服务器,然后一个用于IP地址。

根据RFC:

如果节点上存在CNAME RR,则不应存在其他数据;

根据IETF“常见DNS操作和配置错误”文档:

这通常是由经验不足的管理员尝试的一种明显的方法,以允许您的域名也成为主机。 但是,像BIND这样的DNS服务器会看到CNAME并拒绝添加该名称的任何其他资源。 由于不允许与CNAME共存的其他记录,因此NS条目将被忽略。 因此,podunk.xx域中的所有主机也将被忽略!

参考资料:


19
为什么不能与CNAME同时存在其他记录?这是RFC的作者添加的限制还是有技术原因?如果没有技术原因,那么可以轻松提出一个扩展RFC。 - Sven
那么,如果它对我起作用(使用CNAME用于根记录,该域的其他子域仍在工作),这意味着我只是幸运的,并且我的提供者DNS实现不会忽略那些额外的记录,尽管它可能会?这也意味着只要DNS服务器像这样处理它,我就不需要担心客户端方面的任何问题了吗? - didi_X8
这是为了回答另一个问题而尝试的,即“为什么不允许在顶级域名使用CNAME”,而实际问题是“如何克服这个限制”。-1。 - rustyx
1
请参见 https://serverfault.com/questions/613829/why-cant-a-cname-record-be-used-at-the-apex-aka-root-of-a-domain#613830 了解原因。 - rhand
“CNAME”根记录在技术上不违反RFC,您需要解释它如何不违反RFC1034第3.6.2节:“如果节点上存在CNAME RR,则不应存在其他数据;这确保规范名称及其别名的数据不能不同。”当然,“根”(在这种情况下精确地是顶点)已经具有“NS”和“SOA”记录,因此不能具有“CNAME”记录。 - Patrick Mevzek

4

我不知道他们是如何做到的,或者可能有什么负面影响,但我正在使用Hover.com来托管我的一些域名,并最近在那里设置了我的域的顶级CNAME。

他们的DNS编辑工具完全没有抱怨,并且我的域通过分配的CNAME愉快地解析。

以下是Dig为此域显示给我的内容(实际域名已隐去,替换为mydomain.com):

; <<>> DiG 9.8.3-P1 <<>> mydomain.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2056
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;mydomain.com.          IN  A

;; ANSWER SECTION:
mydomain.com.       394 IN  CNAME   myapp.parseapp.com.
myapp.parseapp.com. 300 IN  CNAME   parseapp.com.
parseapp.com.       60  IN  A   54.243.93.102

如果确实需要混淆(DNS是公开的...),应使用RFC2606指南。对于IP地址,可以使用RFC5737或3849。 - Patrick Mevzek

3

你需要在外部域名的结尾加上一个句号,以便系统不会将其解释为 customer1.mycompanydomain.com.localdomain;

所以只需更改:

customer1.com IN CNAME customer1.mycompanydomain.com

To

customer1.com IN CNAME customer1.mycompanydomain.com.

对于我(BIND 9.8.2),如果记录是针对域名customer1.com,这个可以工作...但被解释为指定子域名customer1.com.customer1.com的CNAMe。如果我在第一项中添加一个点,记录将被正确解释,但它不再起作用。我在这里看不到解决方案。 - Jussi Hirvi

3

我的公司为多个客户提供类似的服务,我们为他们托管网站,尽管在我们的情况下,它是xyz.company.com而不是www.company.com。我们要求他们将A记录设置为指向我们分配给他们的IP地址。

至于如何应对IP地址的更改,我认为没有完美的解决方案。以下是一些想法:

  • 使用NAT或IP负载均衡器,并为您的客户提供属于它的IP地址。如果Web服务器的IP地址需要更改,您可以在NAT或负载均衡器上进行更新。

  • 还可以提供DNS托管服务,并让您的客户将其域名托管给您,这样您就可以更新A记录。

  • 让您的客户将其A记录设置为一个主Web服务器,并为每个客户的Web请求使用HTTP重定向。


3
Sipwiz是正确的,唯一正确的方法是采用HTTP和DNS混合方法。我的注册商是Tucows的转售商,他们提供根域名转发作为免费增值服务。
如果您的域名是blah.com,他们会问您要将域名转发到哪里,然后您输入www.blah.com。他们将A记录分配给他们的Apache服务器,并自动将blah.com添加为DNS vhost。vhost使用HTTP 302错误响应并将其重定向到正确的URL。这很容易进行脚本/设置,并且可以由低端硬件处理。
运行以下命令以获取示例: curl -v eclecticengineers.com

1

0
  • 如果您的域名注册商支持ANAME,则可以使用ANAME记录重定向您的根域名。

  • 如果不支持ANAME,但支持DNS转发,例如Google Domain,则可以:

  1. 添加CNAME记录以将http://www.customer1.example重定向到您想要的域名。
  2. 在转发DNS设置中,将http://customer1.example设置为URL:http://www.customer1.example

然后就完成了。通常情况下,您可能需要等待几分钟才能生效。


-2

我看到readytocloud.com是托管在Apache 2.2上。

在Apache中,有一种更简单、更高效的方法将非www站点重定向到www站点。

将以下重写规则添加到Apache配置文件中(无论是在虚拟主机内部还是外部都可以):

RewriteCond %{HTTP_HOST} ^readytocloud.com [NC]
RewriteRule ^/$ http://www.readytocloud.com/ [R=301,L]

或者,如果您想要将非 www 网站的 URL 与 www 网站进行一对一映射,则可以使用以下重写规则:

RewriteCond %{HTTP_HOST} ^readytocloud.com [NC]
RewriteRule (.*) http://www.readytocloud.com$1 [R=301,L]

注意,mod_rewrite模块需要被加载才能正常工作。幸运的是readytocloud.com运行在一个CentOS服务器上,默认加载了mod_rewrite。
我们有一个客户端运行Apache 2.2服务器,管理着将近3,000个域名和近4,000个重定向,然而,服务器的负载仅维持在0.10-0.20之间。

问题是关于DNS的,不是关于Apache Web服务器的。 - SamTzu

-8
感谢sipwiz和MrEvil的帮助。我们开发了一个PHP脚本,可以解析用户输入的URL并在其顶部粘贴www。(例如,如果客户输入kiragiannis.com,则会重定向到www.kiragiannis.com)。因此,我们的客户将其根目录(例如customer1.com)指向我们的Web重定向器的A记录,然后将wwwCNAME指向我们管理的真实A记录。
以下是代码,以备将来参考。
<?php
$url = strtolower($_SERVER["HTTP_HOST"]);

if(strpos($url, "//") !== false) { // remove http://
  $url = substr($url, strpos($url, "//") + 2);
}

$urlPagePath = "";
if(strpos($url, "/") !== false) { // store post-domain page path to append later
  $urlPagePath = substr($url, strpos($url, "/"));
  $url = substr($url, 0, strpos($url,"/"));
}


$urlLast = substr($url, strrpos($url, "."));
$url = substr($url, 0, strrpos($url, "."));


if(strpos($url, ".") !== false) { // get rid of subdomain(s)
  $url = substr($url, strrpos($url, ".") + 1);
}


$url = "http://www." . $url . $urlLast . $urlPagePath;

header( "Location:{$url}");
?>

10
这实际上并没有回答69,000多人来到该帖子寻找的问题。这个问题与DNS有关,与PHP无关。 - Matt Clark
1
问题是关于DNS的,不是关于PHP编码的。 - SamTzu
1
HTTP_HOST是主机名,正如其名称所示,不是URL。因此,不会有任何http://需要删除,也不会有/($urlPagePath将始终为空)。请参见https://httpd.apache.org/docs/2.4/expr.html。由于代码尝试摆脱子域的方式,它也无法处理像`www.example.co.uk`这样的东西,其中`co.uk`必须被视为一个整体。它也不能处理HTTPS。最后,仅使用PHP进行HTTP重定向,在任何Web服务器都可以在配置中完成,这是过于复杂的。因此,简而言之,这肯定不应该是此问题的验证答案。 - Patrick Mevzek
如果这个规则应该适用于所有主机,那么它应该作为 Apache 配置完成。 - Svetoslav Marinov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接