我已设置并运行 Apache HTTP 服务器,其中包含一组使用 Let's Encrypt 证书的虚拟主机。但是,我无法确定所有 VHost 是否都继承了全局 SSL 选项。
在主配置文件(/etc/httpd/conf/httpd.conf
)中我包含以下内容:
...
Include conf/extra/httpd-mpm.conf
Include conf/extra/httpd-autoindex.conf
Include conf/extra/httpd-languages.conf
Include conf/extra/httpd-default.conf
Include conf/extra/httpd-ssl.conf
Include conf/extra/httpd-vhosts.conf
Include conf/extra/php-fpm.conf
...
(未显示其余配置)。所以你可以看到它httpd-ssl.conf
包含在之前httpd-vhosts.conf
。在每个 VHost 配置指令下,我仅引用了有效的密钥/证书对和SSLEngine On
选项。我想知道全局包含的httpd-ssl.conf
选项是否对每个 VHost 都有效,换句话说,VHost 是否继承了全局定义的选项?我找不到任何直接的线索。或者我应该httpd-ssl.conf
在每个 VHost 指令中明确包含(或改为 Let's Encrypt SSL 选项文件)吗?
这里出现了相关问题:是否有任何辅助实用程序可以显示指定 VHost 的当前配置,包括全局选项和默认值?
答案1
您是否需要为每个单独的虚拟主机设置/包含 SSL 设置?
不. 当服务器上的所有站点都应该总是具有相同的现代安全要求和相同的 TLS 设置,然后在“服务器配置” 上下文应该足够了。
否则:是的。当(将来)需要在其中一个虚拟主机的 TLS 设置中进行自定义以覆盖服务器配置上下文中的全局默认值时;该覆盖可能会无意中成为所有其他虚拟主机的新默认值。
总结
您看到的行为在一定程度上取决于 Apache 和 openssl 版本,但对于(某些)mod_ssl SSL/TLS 指令,行为并不是完全直观的。
大多数 Apache mod_ssl 设置和指令确实可以在“服务器配置” 背景和 “虚拟主机” 语境,有些甚至在“目录”和“.htaccess”上下文中有效。手动的列出每个可以设置指令的位置。
将使用在服务器配置上下文中设置的指令值,除非它们(也)在“虚拟主机”语境。
违反直觉的部分是,对于某些设置,当它们在“基本虚拟主机”中获得分配的值时,该值将覆盖其他虚拟主机的服务器配置。换句话说:对于虚拟主机中定义的某些设置,范围(效果)不限于该特定虚拟主机。
它只在手册部分中“解释”SSLProtocol
指令。(我不确定我是否记得正确,这也可能(或曾经)适用于其他指令,例如SSLCipherSuite
):
基于名称的虚拟主机的 SSL 协议
在 OpenSSL 1.1.1 之前,尽管服务器名称指示 (SNI) 允许在 TLS 握手早期确定目标虚拟主机,但此时无法切换连接的 TLS 协议版本,因此协商
SSLProtocol
始终基于基本虚拟主机之一(在连接的监听 IP:端口上声明的第一个虚拟主机)。从 Apache HTTP 服务器版本 2.4.42 开始,当针对 OpenSSL 1.1.1 或更高版本构建/链接时,并且当客户端在 TLS 握手中提供 SNI 时,每个
SSLProtocol
(基于名称的)虚拟主机都可以并且将被遵守。为了与以前的版本兼容,如果
SSLProtocol
在基于名称的虚拟主机中未配置,则仍然适用基本虚拟主机中的配置,除非SSLProtocol
全局配置,在这种情况下将应用全局值(尽管后一种例外比兼容更合理)。
例如
具有三个虚拟主机块的主服务器配置:
#/etc/httpd/conf/httpd.conf
...
LoadModule ssl_module modules/mod_ssl.so
SSLProtocol All -SSLv2 -SSLv3 -TLSv1
Listen 443
<VirtualHost *:443>
ServerName insecure.example.com
SSLEngine on
SSLCertificateFile "/path/to/insecure.example.com.cert"
SSLCertificateKeyFile "/path/to/insecure.example.com.key"
SSLProtocol All
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.com
SSLEngine on
SSLCertificateFile "/path/to/www.example.com.cert"
SSLCertificateKeyFile "/path/to/www.example.com.key"
</VirtualHost>
<VirtualHost *:443>
ServerName secure.example.com
SSLEngine on
SSLCertificateFile "/path/to/www.example.com.cert"
SSLCertificateKeyFile "/path/to/www.example.com.key"
SSLProtocol TLSv1.2
</VirtualHost>
在我的旧 RHEL 7 上安装了 openssl 1.0.2 和 apache 2.4.6 ;旧版 apache / openssl 版本手册发出了警告:
其效果是:对于
www.example.com
;虚拟主机块没有明确定义 SSLProtocol:将使用All
默认主机的值insecure.example.com
,而不是主服务器上下文的值SSLProtocol All -SSLv2 -SSLv3 -TLSv1
。此外,
secure.example.com
明确定义的值也会被忽略,而 改用 默认主机的SSLProtocol TLSv1.2
值。All
insecure.example.com
将该配置复制到具有最新 Apache httpd 版本和 openssl 的现代主机,该主机现在还支持 TLS 版本 1.3:
其效果是:对于
www.example.com
;虚拟主机块没有明确定义 SSLProtocol 的情况:SSLProtocol All -SSLv2 -SSLv3 -TLSv1
将使用主服务器上下文中的值。换句话说,在扩展 之后All
:SSLProtocol TLSv1.3 TLSv1.2
此外,
secure.example.com
明确定义的配置SSLProtocol TLSv1.2
也会被使用,但该配置不是最安全的,因为它不支持较新的 TLSv1.3