据我了解,当 Apache 收到对其正在监听的 TCP 端口之一(例如 80、443)的请求时,它会通过查看 HTTP 标头来确定请求的是哪个主机Host
。然后,服务器将知道应将请求重定向到哪个虚拟主机。
但是对于通过 SSL/TLS 的 HTTP,它是如何工作的呢?由于整个 HTTP 请求都是加密的(至少我相信我在某处读到过),因此只有在服务器解密数据后才能读取标头信息。但为了解密,它需要知道要使用哪个密钥对,因为您可以在 Web 服务器上安装多个 SSL 证书。
那么服务器如何知道解密需要哪个密钥?
我猜:
我可以想象 TLS 握手提供了必要的信息。
关于“可能重复”旗帜:
虽然我同意答案尽管链接的问题和我自己的问题很相似,但我必须说这个问题是不同的。毫无疑问,是否可以或如何托管具有独立 SSL 证书的多个网站。相反,我的问题涉及底层技术方面。
答案1
最初,Web 服务器并不知道。这就是您需要为要在服务器上托管的每个 SSL 虚拟主机分配一个单独的 IP 地址的原因。这样,服务器就知道,当 IP X 上有连接时,它需要使用相关虚拟主机的配置(包括证书)。
这改变了服务器名称指示,这是一项 TLS 扩展,它确实允许客户端在握手过程中指示所需的主机名。此扩展在所有现代操作系统中都有使用,但旧版浏览器或服务器不支持它,因此如果您希望客户端仍在 WinXP 上使用 IE 6,那么您就没那么幸运了。
答案2
看来您对 TLS/SSL 有一些误解。HTTP 请求未通过服务器的公钥加密。它使用在之前的握手中协商的密钥通过对称密码加密。
TLS 握手的简要说明:服务器和客户端协商一些密码套件、对称密钥和其他一些细节。为了防止 MITM,服务器通常将其证书(链)发送给客户端,并使用证书中的密钥对握手进行身份验证。(还有一些其他变体,例如客户端身份验证或 TLS-PSK,但它们在 HTTP 中用得不多。)客户端可以验证证书(通常的方式)或忽略它。
虽然 SNI 在使用一个 IP 上的多个 TLS 证书时很重要,但它对于服务器解密请求而言并非必不可少。如果没有 SNI,服务器就不知道应该发送哪个证书链,因此服务器通常会选择一个(例如第一个 vhost),当然这可能是错误的。如果服务器选择了错误的证书链,客户端应该拒绝它(因此它不会继续发送 HTTP 请求)。但是,如果客户端忽略证书(或者如果无效证书被标记为此站点的可信证书),它可以成功继续。由于用于加密的对称密钥不依赖于证书(TLS 也可以在没有证书的情况下工作),因此服务器可以解密它。
在您询问 SSL 时,我只想说明一下我为什么要写 TLS:TLS 是 SSL 的新版本。所有版本的 SSL 都被认为对于一般用途而言是不安全的,因此我们现在主要使用 TLS(1.0、1.1、1.2)。