Host header 如何帮助托管多个服务器的物理主机?

How does Host header help on a physical host hosting multiple Servers?

我有 1 台单机IP 1.2.3.4。这台机器有 2 个网络服务器和一个 ftp 服务器:

这是 DNS 映射的样子:

ws1.example.com CNAME example.com
ws2.example.com CNAME example.com
ftp.example.com CNAME example.com
example.com A 1.2.3.4

案例一:我在浏览器发起请求URLws1.example.com:82 并且 DNS 将我重定向到 example.com 但是 Host header: ws1.example.com

情况2:我在浏览器发起请求URLws2.example.com:83 并且 DNS 将我重定向到 example.com 但是 Host header: ws2.example.com

在这两种情况下:

Hostheader据我理解是用来通知接收主机识别哪个服务器(从多台服务器中这个 IP 已托管)是此请求的目的,因此将请求定向到适当的应用程序。

我的问题是:

没有 DNS 重定向

首先是一个重要的术语修复:

DNS 中没有 "redirects"。在您的情况下,DNS 仅用于将名称映射到 IP。有时,由于 CNAME,一个名称会映射到另一个名称,然后再映射到一个 IP。如果有这样的中间步骤也没关系,最后一个名字映射到一个IP(或者DNS解析失败)

这也意味着,如果 URL 有一个特定的端口,则不会更改,最终 IP 将通过 URL 中提到的端口查询。

重定向是一种 HTTP 级别的功能:当向网络服务器查询 https://www.mygreatsite.example/foo 时,它将使用 301、302、303、307 或 308 的 HTTP return 代码进行回复,并为您提供(HTTP客户端,又名浏览器)要转到的新 URL。

HTTP 虚拟主机

在过去的好日子里,IP 地址很多。如果您在同一个物理盒子上托管 www.site1.examplewww.site2.example,您可以为每个附加一个 不同的 IP 地址。 因此,在那种特定情况下,在某种程度上,HTTP host header 是无用的,仅连接到 192.0.2.37192.0.2.42 的事实已经让您知道哪个站点你要。 事实上 HTTP/0.9 中没有 host header,因为根本没有 header。

但是,随着大量虚拟主机的出现,IPv4 地址变得稀缺,您不能再为每个站点附加一个 IP 地址,因为这也是一种浪费。 因此,您通过 DNS 直接或间接地(CNAME 记录)将两个网站解析为相同的 IP。

因此当HTTP客户端连接到服务器时,服务器默认无法知道您要访问哪个网站。这就是为什么客户端填写的 HTTP host header 让服务器知道你想访问哪个网站, 与其 IP 地址无关 ,这是较早解决的通过 DNS。

默认情况下 HTTP 使用端口 80,因此在 URL 中通常不可见。 当然,如果您强迫您的客户在一侧使用 http://www.site1.example:4569 而在另一侧使用 http://www.anothersite2.com:9873,那么您是对的,实际上并不需要 host header。 除了因为很多原因计划落空:

  1. 端口号也不是无限的 space,其中许多通常已用于其他用途;所以即使你一次扩展这个方案,你也不能将新网站附加到同一个 IP
  2. 但比前面的技术点更重要的是,对于人类来说这将是一场噩梦,许多人会忘记端口号,然后无法访问相应的网站。

因此通常不会那样做,如果您想通过 HTTP 公开某些给定服务,但在非默认端口中,您通常会在它前面安装反向代理。或者您执行从 http://www.coolpublicname.example/http://www.complicatedinternalname.example:9713 的 HTTP 重定向,但随后客户端会看到这个赤裸裸的真相。

HTTPS 虚拟主机

顺便提一下,HTTPS 增加了一定程度的复杂性,因为 HTTPS 网络服务器需要将其证书发送给客户端,但由于每个网站都可以有不同的证书,因此它需要知道客户端想要使用哪个网站,哪个网站它可以通过 host HTTP header 学习,但随后会在 TLS 握手完成后出现,因此在服务器发送证书的早期阶段,这是不可用的。

所以在 HTTPS 的最早时期,由于 host header.

找到了带有 TLS 扩展的解决方案,即服务器名称指示 (SNI),这是客户端提前发送到服务器并提供网站名称的东西,以便服务器可以发送适当的证书,因此我们在 name-based 的情况下,您可以在理论上将无限数量的名称解析为同一 IP,以便它们由一个给定的网络服务器提供服务。