我想设置两个 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 的名称的虚拟托管功能。