同一IP地址和同一端口上有多个SSL域?

这是一个关于在同一个IP上托pipe多个SSL网站的典型问题 。

我的印象是,每个SSL证书都要求它拥有自己独特的IP地址/端口组合。 但是, 我发布的前一个问题的答案与这个说法不一致。

使用这个问题的信息,我能够获得多个SSL证书在同一个IP地址和端口443上工作。我很困惑,为什么这个工作给了上面的假设,并被别人强化,每个SSL域名网站相同的服务器需要自己的IP /端口。

我怀疑我做错了什么。 可以使用多个SSL证书吗?

有关Apache和SNI的最新信息(包括其他特定于HTTP的RFC),请参阅Apache Wiki


FYsI:“TLS升级的魔力”为您带来“一个IP上的多个(不同的)SSL证书”。 它适用于较新的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. 

是的,但有一些警告。

这是通过服务器名称指示(Transport Name Security)的扩展来完成的。

什么是服务器名称指示?

服务器名称指示 ( RFC 6066 ;过时的RFC 4366 , RFC 3546 )是传输层安全性的扩展,它允许客户端告诉服务器它正试图访问的主机的名称。

根据规范,SNI与TLS 1.0和更高版本兼容,但实现可能会有所不同(见下文)。 它不能与SSL一起使用,因此连接必须协商TLS(参见RFC 4346附录E )以使用SNI。 这通常在支持的软件中自动发生。

为什么SNI需要?

在一个正常的HTTP连接中,浏览器通过Host:头向服务器通知它正试图访问的服务器的主机名。 这允许单个IP地址上的Web服务器为多个主机名提供内容,这通常被称为基于名称的虚拟主机 。

另一种方法是为每个要提供的Web主机名分配唯一的IP地址。 这通常是在networking的早期阶段完成的,在众所周知的IP地址将会耗尽并开始保护措施之前,SSL虚拟主机(不使用SNI)仍然以这种方式完成。

由于这种传输主机名的方法要求连接已经build立,所以它不适用于SSL / TLS连接。 在build立安全连接时,Web服务器必须已经知道将要为客户端提供哪个主机名,因为Web服务器本身正在build立安全连接。

SNI通过让客户端传输主机名作为TLS协商的一部分来解决这个问题,以便服务器已经知道应该使用哪个虚拟主机来为连接提供服务。 服务器可以使用正确的虚拟主机的证书和configuration。

为什么不使用不同的IP地址?

HTTP Host:头被定义为允许从一个IP地址服务多个Web主机,这是由于IPv4地址短缺,早在20世纪90年代中期就被认为是一个问题。 在共享虚拟主机环境中,可以通过这种方式使用单个IP地址提供数百个独立的无关网站,从而节省地址空间。

共享主机环境然后发现,最大的IP地址空间消费者需要安全的网站拥有唯一的IP地址,这就需要SNI作为通向IPv6的障碍。 今天,有时很难获得less至5个IP地址(/ 29)而没有明显的理由,往往导致部署延迟。

随着IPv6的出现,这样的地址保护技术不再是必要的,因为单个主机可以拥有比现在整个互联网更多的IPv6地址,但是这些技术可能仍将在未来用于传统IPv4连接。

注意事项

某些操作系统/浏览器组合不支持SNI(见下文),所以使用SNI并不适用于所有情况。 定位此类系统/浏览器组合的网站将不得不放弃SNI,并继续为每个虚拟主机使用唯一的IP地址。

特别值得注意的是,Windows XP上没有Internet Explorer版本支持SNI。 由于互联网stream量的这个组合仍然是一个显着的(但是稳步下降,根据NetMarketShare,2012年12月的互联网stream量的大约16%),SNI将不适合针对这些用户群体的网站。

支持

许多但不是全部的常用软件包都支持SNI。

(从这个清单中省略并不一定意味着缺乏支持,这意味着我可以打字的数量是有限的,或者我无法在search中快速find这些信息。如果您的软件包没有列出,因为它的名字加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或更高版本,带有configuration标志
  • Qt 4.8或更高

服务器支持

目前大多数stream行的服务器软件都支持SNI。 安装说明可用于其中的大多数:

  • Apache 2.2.12或更高版本
  • Apache Traffic Server 3.2.0或更高版本
  • 切诺基
  • HAProxy 1.5或更高
  • IIS 8.0或更高版本
  • lighttpd 1.4.24或更高
  • LiteSpeed 4.1或更高版本
  • nginx 0.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或更高版本

移动

  • 3.0 Honeycomb的Android Browser或更高
  • iOS 4或更高版本的iOS Safari
  • Windows Phone 7或更高版本

命令行

  • cURL 7.18.1或更高
  • wget 1.14或更高版本(分发可能已经支持SNI 补丁 )

没有支持

  • BlackBerry浏览器
  • Windows XP上的Internet Explorer(任何版本)

(注意:这个答案的一些信息是从维基百科获得的。)

问题:

当一个Web客户端和一个Web服务器通过HTTPS互相通信时, 首先需要做的就是安全握手。

这是一个简单的握手示例:

握手

如果这是HTTP而不是HTTPS,客户端发送的第一件事就是这样的:

 GET /index.html HTTP/1.1 Host: example.com 

这使得多个虚拟主机在一个IP地址上成为可能,因为服务器确切知道客户端要访问哪个域,即example.com。

HTTPS是不同的。 就像我刚才所说的那样,握手是在一切之前完成的。 如果您查看上面所示的握手的第三步(证书),服务器需要向客户端提交一个证书作为握手的一部分,但不知道客户端尝试访问哪个域名。 服务器唯一的select是每次发送相同的证书,即默authentication书。

您仍然可以在您的Web服务器上设置虚拟主机,但是服务器将始终将相同的证书发送给每个客户端。 如果您尝试在您的服务器上同时托pipeexample.com和example.org网站,则当客户端请求HTTPS连接时,服务器将始终为example.com发送证书。 所以当一个客户通过build立的HTTPS连接请求example.org时,会发生这样的情况:

在这里输入图像描述

此问题有效地将可以通过HTTPS服务的域数限制为每个IP地址一个。

解决scheme:

解决这个问题的最简单的方法是让客户端在握手期间告诉服务器哪个域要访问。 这样服务器可以提供正确的证书。

这正是SNI或服务器名称指示所要做的。

使用SNI,客户端发送它想要访问的服务器名称,作为第一条消息的一部分,即上面握手图中的“客户端Hello”步骤。

一些较旧的网页浏览器不支持SNI。 例如,在Windows XP上,没有支持SNI 的单一版本的Internet Explorer 。 在使用SNI虚拟主机的服务器上通过HTTPS访问资源时,将显示通用证书,这可能会导致浏览器显示警告或错误。

在这里输入图像描述

我在这里简化了一些事情,只是解释问题背后的原理和解决scheme。 如果您想要更多技术性的解释, 维基百科页面或RFC 6066可能是一个很好的起点。 您还可以在维基百科上find支持SNI的服务器和浏览器列表的最新信息

http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI

客户端浏览器也必须支持SNI。 这里有一些浏览器可以做到这一点:

 * Mozilla Firefox 2.0 or later * Opera 8.0 or later (with TLS 1.1 enabled) * Internet Explorer 7.0 or later (on Vista, not XP) * Google Chrome * Safari 3.2.1 on Mac OS X 10.5.6 

基于名称的虚拟主机通过HTTPS工作需要服务器名称指示(RFC6066)TLS扩展名。

扩展被广泛实现,我还没有遇到任何与当前软件有关的问题,但如果你依赖于SNI,有些客户(不支持它的那些客户)将被路由到默认站点。