![Apache httpd2.4 - VirtualHost 和 _default_ 配置层次结构](https://linux22.com/image/688965/Apache%20httpd2.4%20-%20VirtualHost%20%E5%92%8C%20_default_%20%E9%85%8D%E7%BD%AE%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84.png)
<Virtualhost _default_:443>
我在 RHEL7 上安装了 httpd 2.4,并在将其应用到生产环境之前尝试了 SNI 集成。我遇到了一个有趣的行为。服务器始终使用指令内指定的证书(conf.d/ssl.conf
而不是)提供 www.example.org 的匹配虚拟主机内容conf.d/vhost.conf
。
但是,如果在指令中指定了具有不同位置的 DocumentRoot 指令<Virtualhost _default_:443>
,服务器仍会提供与使用错误证书指定的相同匹配的虚拟主机内容conf.d/vhosts.conf
。即使在 _default_ 部分中使用不同的DocumentRoot
位置和指令,服务器仍会像以前一样运行。ServerName www.example.org
这里的重点是全局配置中的 ServerName 指令未指定。因此在启动时,服务器将使用本地主机的当前活动主机名,该主机名也是 www.example.org。当主机名更改为其他主机名时,在重新启动 httpd 后,服务器将正常运行,这是预期的。
然而,据称这里_默认_配置永远不会覆盖来自另一个虚拟主机配置的已匹配的请求。
在我看来,由于 SNI&TLS 握手发生在通信开始时,httpd 服务器无法区分请求的内容是属于主全局服务器还是匹配的虚拟主机(具有相同的 ServerName)。最后,服务器提供全局配置中指定的证书,但内容是通过考虑虚拟主机配置 conf.d/vhosts.conf 中的 DocumentRoot 指令来提供的。
修复方法很简单;不要提供与任何其他虚拟主机相同的全局 ServerName。然而,这些问题让我很好奇:
- 为什么只有虚拟主机配置的 SSL 部分从全局配置中提取。为什么不包括其余部分,例如 DocumentRoot 和 Log* 指令?
- 这是一个错误还是预期的行为?
conf.d/ssl.conf相关内容:
Listen 443 https
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:!MEDIUM:!LOW:!SSLv2:!EXPORT
<VirtualHost _default_:443>
DocumentRoot "/var/www/html"
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
</VirtualHost>
conf.d/vhosts.conf 的内容:
<VirtualHost 192.168.1.1:443>
SSLEngine On
ServerName sni.example.org
DocumentRoot /var/www/html/sni.html/
SSLCertificateFile certs/sni.cer
SSLCertificateKeyFile certs/sni.key
</VirtualHost>