![什么是服务器名称指示?](https://linux22.com/image/505110/%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%90%8D%E7%A7%B0%E6%8C%87%E7%A4%BA%EF%BC%9F.png)
这是一个典型问题关于在同一个 IP 上托管多个 SSL 网站。
我以为每个 SSL 证书都需要自己独特的 IP 地址/端口组合。但回答我之前发过的一个问题与此说法相矛盾。
利用该问题中的信息,我能够让多个 SSL 证书在同一个 IP 地址和端口 443 上工作。鉴于上述假设并且得到其他人的支持,我非常困惑为什么这会起作用,即同一服务器上的每个 SSL 域网站都需要自己的 IP /端口。
我怀疑我做错了什么。这样可以使用多个 SSL 证书吗?
答案1
有关 Apache 和 SNI 的最新信息(包括其他 HTTP 特定 RFC),请参阅Apache 维基
仅供参考:“一个 IP 上多个(不同)SSL 证书”是 TLS 升级的魔力。它适用于较新的 Apache 服务器(2.2.x)和较新的浏览器(我记不清是什么版本了)。
RFC 2817(在 HTTP/1.1 中升级到 TLS)有详细的说明,但基本上它对很多人(如果不是大多数人)都有效。不过,
您可以使用 openssl 的命令(或任何“足够老”的浏览器)重现旧的古怪行为s_client
。
编辑以添加:显然curl
可以比 openssl 更好地向您展示这里发生的事情:
SSLv3
mikeg@flexo% curl -v -v -v -3 https://www.yummyskin.com
* About to connect() to www.yummyskin.com port 443 (#0)
* Trying 69.164.214.79... connected
* Connected to www.yummyskin.com (69.164.214.79) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: /usr/local/share/certs/ca-root-nss.crt
CApath: none
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using DHE-RSA-AES256-SHA
* Server certificate:
* subject: serialNumber=wq8O9mhOSp9fY9JcmaJUrFNWWrANURzJ; C=CA;
O=staging.bossystem.org; OU=GT07932874;
OU=See www.rapidssl.com/resources/cps (c)10;
OU=Domain Control Validated - RapidSSL(R);
CN=staging.bossystem.org
* start date: 2010-02-03 18:53:53 GMT
* expire date: 2011-02-06 13:21:08 GMT
* SSL: certificate subject name 'staging.bossystem.org'
does not match target host name 'www.yummyskin.com'
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):
curl: (51) SSL: certificate subject name 'staging.bossystem.org'
does not match target host name 'www.yummyskin.com'
TLSv1
mikeg@flexo% curl -v -v -v -1 https://www.yummyskin.com
* About to connect() to www.yummyskin.com port 443 (#0)
* Trying 69.164.214.79... connected
* Connected to www.yummyskin.com (69.164.214.79) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: /usr/local/share/certs/ca-root-nss.crt
CApath: none
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using DHE-RSA-AES256-SHA
* Server certificate:
* subject: C=CA; O=www.yummyskin.com; OU=GT13670640;
OU=See www.rapidssl.com/resources/cps (c)09;
OU=Domain Control Validated - RapidSSL(R);
CN=www.yummyskin.com
* start date: 2009-04-24 15:48:15 GMT
* expire date: 2010-04-25 15:48:15 GMT
* common name: www.yummyskin.com (matched)
* issuer: C=US; O=Equifax Secure Inc.; CN=Equifax Secure Global eBusiness CA-1
* SSL certificate verify ok.
答案2
是的,但是有一些注意事项。
这是通过服务器名称指示(传输层安全性的扩展)实现的。
什么是服务器名称指示?
服务器名称指示(RFC 6066;已过时RFC 4366,RFC 3546)是传输层安全性它允许客户端告诉服务器它正在尝试访问的主机的名称。
根据规范,SNI 与 TLS 1.0 及更高版本兼容,但实现可能有所不同(见下文)。它不能与 SSL 一起使用,因此连接必须协商 TLS(见RFC 4346 附录 E) 来使用 SNI。这通常会在受支持的软件中自动发生。
为什么需要 SNI?
在正常情况下HTTP连接时,浏览器会使用标头通知服务器它尝试访问的服务器的主机名Host:
。这允许单个 IP 地址上的 Web 服务器为多个主机名提供内容,这通常称为基于名称的虚拟主机。
另一种方法是为每个要提供服务的 Web 主机名分配唯一的 IP 地址。在 Web 发展的早期,人们普遍认为 IP 地址会用完,因此开始采取节约措施,现在 SSL 虚拟主机(不使用 SNI)仍然采用这种方式。
由于这种传输主机名的方法要求已建立连接,因此它不适用于 SSL/TLS 连接。在建立安全连接时,Web 服务器必须已经知道要向客户端提供哪个主机名,因为 Web 服务器本身正在设置安全连接。
SNI 通过让客户端在 TLS 协商过程中传输主机名来解决此问题,这样服务器就已经知道应该使用哪个虚拟主机来为连接提供服务。然后服务器可以使用证书和配置来选择正确的虚拟主机。
为什么不使用不同的 IP 地址?
由于 IPv4 地址短缺, HTTPHost:
标头被定义为允许从单个 IP 地址为多个 Web 主机提供服务,这早在 20 世纪 90 年代中期就已被视为一个问题。在共享 Web 托管环境中,数百个唯一、不相关的网站可以通过这种方式使用单个 IP 地址提供服务,从而节省地址空间。
共享托管环境随后发现,IP 地址空间的最大消耗者是需要安全网站拥有唯一 IP 地址,因此需要 SNI 作为 IPv6 过渡的权宜之计。如今,如果没有充分的理由,有时很难获得少至 5 个 IP 地址 (/29),这通常会导致部署延迟。
随着 IPv6 的出现,这种地址节省技术不再是必要的,因为单个主机可以分配到的 IPv6 地址比目前整个互联网包含的地址还要多,但这些技术在未来可能仍会用于服务于传统的 IPv4 连接。
注意事项
某些操作系统/浏览器组合不支持 SNI(见下文),因此使用 SNI 并不适合所有情况。针对此类系统/浏览器组合的网站必须放弃 SNI,并继续为每个虚拟主机使用唯一的 IP 地址。
特别值得注意的是,Windows XP 上没有任何版本的 Internet Explorer 支持 SNI。由于这种组合仍然占互联网流量的很大一部分(但稳步下降;根据 NetMarketShare 的数据,2012 年 12 月互联网流量约占 16%),因此 SNI 不适合针对这些用户群的网站。
支持
许多(但不是全部)常用的软件包都支持 SNI。
(此列表中的遗漏并不一定意味着缺乏支持;这意味着我输入的内容有限,或者我无法通过搜索快速找到信息。如果您的软件包未列出,则搜索其名称加号应该sni
会显示是否存在支持以及如何设置它。)
图书馆支持
大多数软件包依赖外部库来提供 SSL/TLS 支持。
- GNU TLS
- JSSE (Oracle Java) 7 或更高版本,仅作为客户
- libcurl 7.18.1 或更高版本
- NSS 3.1.1 或更高版本
- OpenSSL 0.9.8j 或更高版本
- OpenSSL 0.9.8f 或更高版本,带有配置标志
- Qt 4.8 或更高版本
服务器支持
大多数当前版本的流行服务器软件都支持 SNI。以下大多数软件的设置说明如下:
- 阿帕奇2.2.12 或更高版本
- Apache 流量服务器3.2.0 或更高版本
- 切诺基
- HAProxy1.5 或更高版本
- 互联网信息服务8.0 或更高版本
- lighttpd1.4.24 或更高版本
- LiteSpeed 4.1 或更高版本
- nginx0.5.32 或更高版本
客户支持
大多数当前的 Web 浏览器和命令行用户代理都支持 SNI。
桌面
- Chrome 5 或更高版本
- Windows XP 上的 Chrome 6 或更高版本
- Firefox 2 或更高版本
- Internet Explorer 7 或更高版本,在 Windows Vista/Server 2008 或更高版本上运行
- 无论 IE 版本如何,Windows XP 上的 Internet Explorer 均不支持 SNI
- Konqueror 4.7 或更高版本
- Opera 8 或更高版本(可能需要启用 TLS 1.1 才能运行)
- Windows Vista/Server 2008 或更高版本上的 Safari 3.0,或 Mac OS X 10.5.6 或更高版本
移动的
- Android 浏览器 3.0 Honeycomb 或更高版本
- iOS 4 或更高版本上的 iOS Safari
- Windows Phone 7 或更高版本
命令行
- cURL 7.18.1 或更高版本
- wget 1.14 或更高版本(发行版可能已反向移植修补用于 SNI 支持)
没有支持
- 黑莓浏览器
- Windows XP 上的 Internet Explorer(任何版本)
(注:本答案的部分信息来自维基百科。
答案3
问题:
当 Web 客户端和 Web 服务器通过 HTTPS 相互通信时,最先需要发生的事情是安全握手。
以下是此类握手的简化示例:
如果这是 HTTP 而不是 HTTPS,那么客户端发送的第一件事应该是这样的:
GET /index.html HTTP/1.1
Host: example.com
这使得单个 IP 地址上存在多个虚拟主机成为可能,因为服务器确切地知道客户端想要访问哪个域,即 example.com。
HTTPS 则不同。就像我之前说的,握手是最重要的。如果你看一下上面所示的握手的第三步(证书),你会发现服务器需要在握手过程中向客户端出示证书,但不知道客户端试图访问哪个域名。服务器唯一的选择就是每次都发送相同的证书,即其默认证书。
您仍然可以在 Web 服务器上设置虚拟主机,但服务器将始终向每个客户端发送相同的证书。如果您尝试在服务器上同时托管 example.com 和 example.org 网站,则当客户端请求 HTTPS 连接时,服务器将始终发送 example.com 的证书。因此,当客户端通过已建立的 HTTPS 连接请求 example.org 时,将发生以下情况:
该问题实际上限制了您可以通过 HTTPS 服务的域名数量为每个 IP 地址一个。
解决方案:
解决这个问题最简单的方法是让客户端告诉服务器它想要访问哪个域握手时. 这样服务器就可以提供正确的证书。
这正是信噪比或服务器名称指示。
使用 SNI,客户端将其想要访问的服务器名称作为第一条消息的一部分发送,即上面握手图中的“客户端 Hello”步骤。
一些较旧的 Web 浏览器不支持 SNI。例如,在 Windows XP 上不是 Internet Explorer 的单一版本支持 SNI。在使用 SNI 虚拟主机的服务器上通过 HTTPS 访问资源时,您将看到通用证书,这可能会导致浏览器显示警告或错误。
我在这里简化了内容,仅解释问题背后的原理和解决方案。如果你想要更技术性的解释,维基百科页面或RFC 6066可能是很好的起点。您还可以找到支持 SNI 的服务器和浏览器的最新列表维基百科
答案4
基于名称的虚拟主机需要服务器名称指示 (RFC6066) TLS 扩展才能通过 HTTPS 运行。
该扩展已被广泛实施,我尚未遇到当前软件的任何问题,但如果您依赖 SNI,则有可能某些客户端(不支持它的客户端)将被路由到您的默认站点。