如何在 SSL 上设置 Apache NameVirtualHost?

如何在 SSL 上设置 Apache NameVirtualHost?

我想设置两个 DNS 的 A 记录以指向我的 Ubuntu 实例。然后 Apache 应该相应地读取域名并将传入请求指向正确的物理路径。

我已经设置好了一切 这是 /etc/apache2/ports.conf 的内容

根据下面的评论,我担心 WinXP 用户无法访问我的 SSL 站点,那么我应该怎么做呢?

NameVirtualHost *:80
Listen 80

<IfModule mod_ssl.c>
    # If you add NameVirtualHost *:443 here, you will also have to change
    # the VirtualHost statement in /etc/apache2/sites-available/default-ssl
    # to <VirtualHost *:443>
    # Server Name Indication for SSL named virtual hosts is currently not
    # supported by MSIE on Windows XP.
    NameVirtualHost *:443
    Listen 443
</IfModule>

<IfModule mod_gnutls.c>
    NameVirtualHost *:443
    Listen 443
</IfModule>

大多数人都使用 WinXP 和 Internet Explorer,所以这有点令人担忧。我该如何以不同的方式设置 SSL,以便它适用于所有人?

答案1

在同一个 Apache Httpd 服务器(以及任何 HTTPS 服务器)上使用多个主机名会带来两个问题:

  • 为了确保连接的安全,客户端必须首先验证服务器证书。
  • 如果服务器有多个可用的证书,则服务器必须能够从客户端请求中获取要选择哪个证书。

HTTPS 是基于 SSL/TLS 的 HTTP:建立安全隧道的 SSL/TLS 握手由客户端在创建 TCP 连接后立即启动,在进行任何 HTTP 交换之前。HTTPS 交换的所有后续 HTTP 流量都通过此 SSL/TLS 连接完成。

服务器证书由服务器作为 SSL/TLS 握手的一部分发送。验证过程依赖于 (a) 验证证书是否可信,以及 (b) 验证证书是否为客户端想要联系的服务器颁发。有关详细信息,请参阅StackOverflow 上的这个答案

在 HTTP 中,请求的主机名在 HTTP 标头中发送。基于名称的虚拟主机的工作方式如下:在 Apache Httpd 内部Host根据标头进行调度。Host

Host但是,在 SSL/TLS 成功完成之前,Apache Httpd 无法获取HTTP 标头。因此,在发送服务器证书之前,HTTP标头不可用。

有两种方法可以帮助 Apache Httpd 选择在握手期间使用哪个证书,而无需依赖任何 HTTP 流量:

  • 每个 IP 地址/端口组合使用一个证书。这是传统方式。
  • 使用SSL/TLS 的服务器名称指示扩展在 SSL/TLS 握手期间发送,从而建立安全隧道。此选项的问题在于并非所有浏览器都支持它。特别是,XP 上的任何版本的 IE 都不支持它(我认为还有一些移动浏览器)。

如果您无法使用 SNI 或服务器上有多个 IP 地址,则可以使用对要服务的所有主机名都有效的证书。这可以通过以下方式完成:

  • 颁发给通配符名称的证书(但不鼓励使用它们), 或者
  • 具有多个主题备用名称 DNS 条目的证书。这应该是您的首选。

如果您确实想尝试 SNI,它应该与足够新的 Apache Httpd 2 版本一起使用,并使用足够新的 OpenSSL 版本(如果使用mod_ssl主代码库提供的版本)。这记录在这里:http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI

答案2

SSL 警告是关于基于名称SSL 站点。如果我没记错的话,传统的 SSL 在发送 HTTP 流量之前加密连接,它会加密 TCP 连接而不是 HTTP 会话。由于虚拟主机是在 HTTP 协议中选择的,并且服务器需要在使用 http 之前建立安全连接,因此您只能为每个 IP/端口组合选择一个证书。默认情况下,默认的 SSL 站点。

这种情况发生了变化,因为您现在可以使用 TLS ( gnutls) 进行加密,这实际上是 SSL 的“新版本”,允许基于名称的加密。但是,Windows XP 等较旧的操作系统和浏览器不支持此功能。

如果您在 XP 上使用 Firefox 或 Chrome 而不是 IE,那么它可以正常工作。

如果您希望它随时工作,请为网站的 SSL 版本配置多个 IP 和/或端口。如果您只有一个网站需要 SSL,则无需进一步配置

编辑:问题也改变了

答案3

如果多个 SSL 域名只有一个 IP,另一种可能性是仅为默认文档根目录配置一个 <VirtualHost _default_:443>,并在其中对需要从不同文档根目录提供服务的每个域名使用 RewriteRule。例如:

<VirtualHost _default_:443>

    DocumentRoot /var/www/https_one

    ... 

    RewriteEngine On

    RewriteCond %{HTTP_HOST} ^https_two\.example\.com$
    RewriteRule (.*) /var/www/https_two/$1

    RewriteCond %{HTTP_HOST} ^https_three\.example\.com$
    RewriteRule (.*) /var/www/https_three/$1
</VirtualHost>

由于 mod_rewrite 在标头已发送时运行,因此这几乎可以避免在 SSL 握手阶段识别 HTTP 主机的问题。不过,您仍然需要一个对所有域名都有效的证书,假设您不希望您的访问者通过浏览器提示接受安全例外。

答案4

尽管上面@Bruno 提供的答案确实解决了如何和为什么的问题,但它留下了一个问题,即如何设置启用 SSL/TLS 的基于名称的虚拟主机,而解决方案不太可行 - 而是推迟给某人绑定(或从其托管服务提供商处购买)其机器的额外 IP 地址,并且还更改 httpd.conf 的监听参数

换句话说,@Bruno 的答案中没有解决方案 - 您必须使用基于 IP 的虚拟主机。

另一方面,@ocsarjd 确实解决了如何提供对基于名称的虚拟 SSL 主机的支持,此外还为坚持在 XP 上运行 IE 的人提供了解决方法。

使用:

<VirtualHost _default_:443>

然后 mod_rewrite 为无法利用 SNI 的浏览器提供支持,因此,无需购买和/或将额外的 IP 地址绑定到服务器,以便 Apache 以基于 IP 的虚拟主机方法监听连接。

具有讽刺意味的是,@Bruno 的回答确实涵盖了这些谈判发生的方式和原因的所有原因,以及过时的浏览器如何无法协商在 Apache 服务器上正确合并基于名称的 SSL 虚拟托管。

由于距离 OP 提出这个问题已经有一段时间了,我建议不要适应这些过时的浏览器,因为这是客户端人员选择操作不安全的软件,在我看来,这只是一个可以忽略的人......

话虽如此,默认 SSL 虚拟主机包含类似于自定义 404 页面的信息,告诉访问者他们正在操作不安全的浏览器客户端,实际上在未来几年内都会适用,因为肯定会有人拒绝停止使用自 XP EOL 以来没有收到任何补丁的 IE 版本,并且所有(所谓的)“现代”浏览器(IE/Edge、Firefox、Chrome/Chromium、Opera、Safari)都将通过 SNI 适应基于 HTTPS 的名称的虚拟托管功能。

相关内容