使用 VirtualDocumentRoot 在 SSL 中进行虚拟主机

Posted

技术标签:

【中文标题】使用 VirtualDocumentRoot 在 SSL 中进行虚拟主机【英文标题】:Virtual Hosting in SSL with VirtualDocumentRoot 【发布时间】:2018-06-19 14:20:01 【问题描述】:

我在 ubuntu 16.04 虚拟机上进行开发工作

当我从事许多项目时,为了让我的生活更轻松,我使用 VirtualDocumentRoot 和 hosts 文件,使用 *.dev 域从我的主文件夹到服务器站点:

在 000-default.conf 我有:

<VirtualHost *:80>
  VirtualDocumentRoot  /home/steve/websites/%-2/%-2/public_html
  ServerAlias *.dev
</VirtualHost>

然后在主机中我有我正在处理的各种网站:

127.0.0.1   somesite.dev
127.0.0.1   another.dev
127.0.0.1   athirdone.dev
127.0.0.1   blog.athirdone.dev

这样,当我添加一个新项目时,我只需要在网站目录中创建正确的文件夹结构并向主机添加一行,例如,如果我想处理一个新项目 somecoolproject.dev,我只需添加一个文件夹:

/home/steve/websites/somecoolproject/somecoolproject/public_html

和主机中的一行:

127.0.0.1    somecoolproject.dev

我可以走了。

无论如何,我现在所做的几乎所有工作都通过 https 运行,并且许多项目都有代码来强制执行这一点,无论是在源代码还是 htaccess 等,这使得在开发副本上工作很痛苦。

我想在我的开发机器上创建一个自签名证书,理想情况下我不需要为每个项目生成一个新证书,所以某种通配符 *.dev 会很棒。

但即使我确实需要为每个项目创建一个新项目,我仍然无法确定如何使用我的设置进行安装 - 我发现的所有内容都假定一个固定的文档和硬编码的服务器名称。

【问题讨论】:

在我进入兔子洞之前,你试过SNI - Server Name Indication吗? 【参考方案1】:

如果我正确理解要求,您想知道:

如何为 *.dev 生成通配符 SSL 证书 如何使用允许服务器通过 SSL/TLS 的任何 *.dev 域的配置在本地配置 apache,而无需在创建新的 *.dev 域时更改配置。

如果我理解正确的话,这当然是可行的。

工作原理:SNI - 服务器名称指示,TLS 协议扩展,其中,在建立 TLS 连接时传递主机名,在 HTTP 数据(如主机头)可用之前.所有流行的网络浏览器,curl,所有流行的网络服务器都支持它。

步骤:

首先。生成证书:

mindaugas@mindaugas-ubuntu-14:/usr/local/apache2/conf$ sudo openssl req        -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.crt
Generating a 2048 bit RSA private key
.............+++
..................+++
writing new private key to 'domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:*.dev
Email Address []:

关键部分是:

Common Name (e.g. server FQDN or YOUR name) []:*.dev

第二个。

服务器配置:

Listen 443

<VirtualHost *:443>
  SSLEngine on
  SSLCertificateFile "/usr/local/apache2/conf/domain.crt"
  SSLCertificateKeyFile "/usr/local/apache2/conf/domain.key"

  VirtualDocumentRoot /home/mindaugas/websites/%-2/pubic/
  ServerAlias *.dev
  <Directory "/">
      Options Indexes FollowSymLinks MultiViews
      AllowOverride All
      Allow from All
      Require all granted
  </Directory>
</VirtualHost>

启用 ssl 并重启 apache:

sudo a2enmod ssl
sudo service apache2 restart

您可以通过以下方式进行测试:

创建两个文档文件结构; 用一个简单的 HTML 页面填充它们; 通过在 hosts 文件中提供域 - ip 映射来发出请求,或者,正如我所做的那样,使用“Modify headers”插件,在需要时发出不同的主机头:

【讨论】:

谢谢,回复晚了,我先看看 不用担心,如果需要其他帮助,请告诉我。 @Steve 请奖励承诺的赏金,因为答案已被接受并且明显有效。 我明白了。不幸的是,当答案被接受时,收到赏金的时间已经到期。从“元”论坛我看到你也失去了积分 - 如此松散 - 松散的情况。 meta.stackexchange.com/questions/95039/… 唯一可能的方法可能是联系支持人员:***.com/contact 并从您的 - 赏金提供者方面解释情况。让我知道您是否可以接受。 当然。感谢您认真对待赏金问题。我很感激。【参考方案2】:

我们喜欢赏金,因为为您编写解决方案有点长 :) 您问题的真正答案是如何使其工作,而 VirtualDocumentRoot 不能在 SSL 中工作。我建议将来自默认 SSL 虚拟主机的请求代理到动态非 SSL 虚拟主机。这可以通过保留请求的主机名来实现。

首先,做所有的准备工作:1/ 生成你的私钥和证书(如果你想要的话,一个通配符),这有很多教程,2/ 在你的主 httpd.conf 中你激活包含额外的/httpd-ssl.conf

在httpd-ssl.conf中,需要这个conf(我测试成功):

UseCanonicalName Off
ProxyPreserveHost  On

SetEnvIf  Server_Addr "(.*)"  sname=$1

RewriteEngine   On
RewriteCond     "%HTTPS" =on
RewriteRule     ^/(.*)$ "http://%ENV:sname:80/$1" [P]

我还建议自定义日志格式,然后您会更好地看到请求的内容。这将有助于以后的调试,这里有一些使用请求的主机名进行日志记录的指令,您可以通过日志行的长度来识别 SSL 或非 SSL 流量。 在httpd.conf中,找到定义LogFormat的地方,添加:

LogFormat "%V %h %l %u %t \"%r\" %>s %b \"%Refereri\" \"%User-Agenti\"" enhanced
LogFormat "%V %h %l %u %t \"%r\" %>s %b" enhancedSSL
CustomLog "logs/access_log" enhanced

在 httpd-ssl.conf 中,你只需要这个:

CustomLog "logs/access_log" enhancedSSL

告诉我们它是否按预期工作。 一旦工作,下一步可能是至少从远程禁用非 SSL 流量。为此,请将本地防火墙配置为阻止端口 80 上的请求,或者(更好地)将 VirtualHost 配置为仅在本地侦听(VirtualHost 127.0.0.1:80 而不是 *:80)。

【讨论】:

谢谢,回复晚了,我先看看 Mindaugas 的解决方案正在发挥作用。也许我在写代理之前尝试了类似的东西时弄错了,但无论如何他看起来更容易。

以上是关于使用 VirtualDocumentRoot 在 SSL 中进行虚拟主机的主要内容,如果未能解决你的问题,请参考以下文章

VirtualDocumentRoot 域和子域

Apache 2.2 忽略 VirtualDocumentRoot 虚拟主机?

VirtualDocumentRoot 和域总是路由到本地主机 - 为啥?

设置Laravel项目以使用多个域名

Xampp 虚拟主机

在 spark 上使用集群和在本地使用并行操作有啥区别?