为什么Nginx会忽略“主机”头中的尾随点?

我一直在Nginx上运行一个奇怪的行为,请求在主机名中有一个尾随点,即domain.com. 而不是单独的domain.com 。 我build立了一个简单的服务器configuration来testing,如下所示:

 server { listen 80; server_name example.com.; root /var/www/example; index server1.txt; } server { listen 80; server_name example.com; root /var/www/example; index server2.txt; } 

最初,我预料到对example.com.请求example.com. 将被发送到第一个块,对example.com请求将被发送到第二个块。 请求的Host头不匹配任何块,例如www.example.com ,我希望再次发送到第一个块,因为它是默认的隐式。

但是,经过testing,我发现对example.com.请求example.com. 被发送到第二块。 在用各种替代名称,正则expression式等搞乱了一阵子之后,我决定把$hostvariables写到一个自定义头文件中,这样我就可以查看它了。 事实certificate,Nginx实际上是从$host值中删除了尾部的点。 据我可以告诉在example.com.收到的请求example.com. 被认为与在example.com收到的相同,至less就服务器select而言。 这似乎是不可取的,因为尾随的点会导致各种错误。 。

为了使事情变得更加混乱,在一些Googlesearch之后,我发现了在0.1.29更新日志中的Nginx更新日志页面:

修正:nginx没有考虑到“主机”标题行中的尾部点。

然后,几年后,1.5.9更新日志说:

错误修复:parsing器不理解带有尾点的域名。 感谢伊春张。

虽然我不确定“parsing器”是否指的是Nginx组件在接收请求时正在播放。 (从阅读文档,这听起来也许parsing器不会做任何事情,除非一个请求被缠绕到其他主机,其名称必须解决。)

这里发生了什么? Nginx是否应该在评估服务器名称时丢弃最后的点? 如果这预期的行为,那么不应该从server_name参数中删除尾部点,以产生“冲突的服务器名称”错误?

我知道一个没有小点的域名在技术上是一个“相对的”域名,而不是“绝对的”,尽pipe现在大多数人似乎都把它们看作是相对的. 所以它没有实际的区别。 但是如果需要的话,Nginx是否应该至less能够做出这样的区分呢?

最后,是否有更好的方法来捕捉和redirect对example.com.请求example.com. 比添加if ($http_host = 'domain.com.') ? 我被告知这是低效的,因为它需要两次评估Host头。

TLDR;

这看起来像是一个Nginx的错误,可能是因为很less有人知道完全合格的域名以点为单位。

背景

我必须阅读你的陈述“完全合格的域名以一个圆点结尾”。 我发现这个有用的资源解释得非常好。 这里还有一个SF的问题和答案 。 似乎只有一小部分人(包括我自己到现在为止)知道一个领域甚至可能有一个尾随的点。

注意

请注意,“主机头”和“Nginx server_name”是完全不同的。 server_name定义了Nginx服务器将要回复的请求。 “主机头”是客户端发送给服务器的http头的一部分。

我尝试了你的示例服务器,将example.com映射到我的服务器上,结果和你在nginx 1.9.11上一样。 我也尝试了服务器“example.com”。 定义而不是“example.com”。 当我蜷缩那个configuration时,我得到了默认服务器的响应,而不是“example.com”。 服务器。

文档

Nginx server_name文档没有提到一个尾随点。 文档确实允许在点(example.com。*)之后使用通配符。 我想知道是谁写的文件知道完全合格的域名。

理论

我不得不怀疑,如果你定义“example.com”和“example.com”。 在Nginx中有什么区别? “example.com”必须被假定为来自DNS根目录的完整URL,所以假定“。 无论如何。

结论

我想你可能在技术上是正确的,Nginx的server_name应该迎合尾部点。 我不确定它应该如何处理它有任何不同或不同于没有尾点的server_name,出于上述原因。

这看起来可能是Nginx的一个漏洞。 这也可能是基于常规做法而不是RFC 。

在DNS级别, example.comexample.com. 是同一个名字。 这并不意味着他们应该被视为相同,这意味着他们都将编码到DNS数据包中完全相同的八位字节序列。 试图将它们视为使用DNS(例如HTTP)的协议中的不同,可以保证引起混淆和问题。

如果一个软件使用来自DNS的名称,并且将同名和不带尾随点视为不同,则该软件有一个错误。