我在理解为什么 HTTPS 协议以纯文本形式包含主机名时遇到了一些麻烦。我读过 HTTPS 数据包的主机名和 IP 地址未加密。
为什么主机名不能加密?我们不能只保留纯文本的目标 IP(因此数据包是可路由的),然后当数据包到达目标服务器时,数据包被解密并从标头中识别主机/索引?
也许问题在于一个特定的目标 IP 可能有不同的证书(不同的子域有不同的证书?),因此目标服务器无法解密数据包,直到它到达该服务器中的正确主机。这有什么意义吗,还是我离题了?
我在理解为什么 HTTPS 协议以纯文本形式包含主机名时遇到了一些麻烦。我读过 HTTPS 数据包的主机名和 IP 地址未加密。
为什么主机名不能加密?我们不能只保留纯文本的目标 IP(因此数据包是可路由的),然后当数据包到达目标服务器时,数据包被解密并从标头中识别主机/索引?
也许问题在于一个特定的目标 IP 可能有不同的证书(不同的子域有不同的证书?),因此目标服务器无法解密数据包,直到它到达该服务器中的正确主机。这有什么意义吗,还是我离题了?
主机名包含在初始 SSL 握手中,以支持在同一 IP 地址上具有多个主机名(具有不同证书)的服务器(SNI:服务器名称指示)。这类似于普通 HTTP 请求中的 Host-header。该名称包含在来自客户端的第一条消息 (ClientHello) 中,即在完成任何标识和密钥交换之前,以便服务器可以提供正确的证书进行标识。
虽然加密主机名会很好,但问题是使用哪个密钥进行加密。密钥交换仅在通过证书识别站点之后进行,否则您可能会与中间人交换密钥。但是证书识别已经需要主机名,以便服务器可以提供匹配的证书。因此,主机名的加密需要使用基于某种其他类型的标识的密钥或以不安全的方式对中间人进行加密。
可能有一些方法可以保护 SSL 握手中的主机名,但代价是握手和基础设施的额外开销。目前正在讨论是否以及如何将加密的 SNI 包含到 TLS 1.3 中。我建议您查看此演示文稿和IETF TLS 邮件列表。
除此之外,主机名的泄漏也可能通过其他方式发生,例如前面的 DNS 查找名称。当然,在服务器响应中发送的证书也没有加密(同样的问题,还没有密钥),因此可以从服务器响应中提取请求的目标。
有很多网站在没有 SNI 的情况下将无法运行,例如所有 Cloudflares 免费 SSL 产品。如果由不支持 SNI 的客户端(如 Windows XP 上的 IE8)访问,这将导致提供错误的证书或某些 SSL 握手错误,如“unknown_name”。
SNI用于虚拟主机(在同一个 IP 地址上具有不同名称的多个服务器)。当 SSL 客户端连接到 SSL 服务器时,它想知道它是否正在与正确的服务器通信。为此,它会在证书中查找预期服务器的名称。每个邪恶的黑客都可evilhacker.com
以为自己的服务器(honest-bank-inc.com
称为https://honest-bank-inc.com/
服务器证书的字符串honest-bank-inc.com
,当然不是evilhacker.com
。
到现在为止还挺好。然后成为技术部分。在“HTTPS”中,您将 HTTP 封装在 SSL 中。这意味着首先建立 SSL 隧道(“握手”过程),然后客户端才在该隧道内发送 HTTP 请求。在握手期间,服务器必须将其证书发送给客户端。但是,此时,客户端还没有告诉服务器它正在尝试与谁交谈。服务器可能会假设,因为它收到了连接,客户端想要访问的名称可能是服务器托管的站点名称之一。但是,如果服务器托管多个具有不同名称的站点,则这是猜测并且会失败。
解决这个难题的方法主要有以下三种:
每个站点一个 IP。由于服务器从连接一开始就知道目标 IP 地址,因此服务器可以使用该 IP 地址来知道哪个服务器是真正的目标。当然,IP 地址的相对短缺使得这种传统解决方案在如今变得不那么有吸引力了。
服务器证书中的多个名称。这是完全有效的。谷歌自己倾向于在他们的证书中加入 70 多个名字。一个变体是包含“*”的“通配符名称”,匹配许多名称。但是,这仅在颁发证书时知道所有名称的情况下才有效。对于网站托管服务,这意味着每当客户注册时都要购买新证书。
SNI。使用 SNI,客户端在握手的早期发送预期的名称,然后服务器发送其证书。这是现代的解决方案,现在 Windows XP 已经超越了边缘,它终于可以被广泛使用(Windows XP 上的 IE 是最后一个不支持 SNI 的浏览器)。
您正在与某些服务器通信的事实显然无法从 IP 中隐藏。数据包必须离开你的机器,进入网络,被路由到目的地,然后被传递。您正在联系从https://www.fred.com提供页面的服务器,这已经不是什么秘密了。
但是,URL 不包含 IP。相反,它包含不止一条信息。它不仅包含主机名(必须解析为 IP 地址),还包含有关特定请求的详细信息:将其路由到名为 www、search、mail 等地址的服务器,并沿着此目录路径名称。
托管服务利用这种间接方式通过服务器名称指示在单个 Web 服务器上支持多个站点。因此,https://www.fred.com和https://www.barney.com都可能托管在 127.0.0.1 的服务器上,它只是区分服务器如何在内部路由该消息的名称。出于安全原因,可能需要将其路由到单独的服务器,其中将存储实际密钥。该前端服务器上可能不存在解密该消息的密钥,因此在它到达托管 fred 站点的机器之前无法解密。
除了需要包含主机名来解析证书之外,还有一种与使用 SNI 相关的常见做法,了解这一点很重要:它允许通过 SSL/TLS实现https://en.wikipedia.org/wiki/Virtual_hosting 。
所有流行的 Web 服务器都使用 SNI: