【问题标题】:Apache virtual hosts with multiple domains具有多个域的 Apache 虚拟主机
【发布时间】:2016-03-31 01:29:24
【问题描述】:

我正在尝试找出我的虚拟主机文件的最佳配置,但我遇到了一些问题。

目前我有 2 个域:domain1.com 和 domain2.com

我在 IP 000.000.000.001 有 1 台服务器,它实际上托管了所有需要的文件。在这些文件中,您有一个 API (api.domain1.com) 和实际网站。

domain1.com 使用 Digital Ocean 的域名服务器并使用以下 DNS 记录:

A        @        000.000.000.001
CNAME    *        domain1.com.

出于 SEO 目的,我想将所有未发送到 api 子域的请求重定向到 www.domain1.com。 但是,我也只希望用户能够通过 SSL 连接浏览我的网站(和 API),我不希望用户能够通过 HTTP 使用它,所以我尝试将所有这些请求重定向到使用 HTTPS。证书由 LetsEncrypt! 提供。他们的自动安装对我的虚拟主机文件进行了更改,目前我有 4 个:

  1. api.domain1.com.conf

    <VirtualHost *:80>
        ServerName api.domain1.com
    
        DocumentRoot /var/www/api.domain1.com/web
    
        RewriteEngine on
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [L,QSA,R=permanent]
    </VirtualHost>
    
  2. api.domain1.com-le-ssl.conf

    <IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerName api.domain1.com
    
        DocumentRoot /var/www/api.domain1.com/web
    
        ExpiresActive On
        /* ... */
    
        <Directory /var/www/api.domain1.com/web>
            AllowOverride None
            Order Allow,Deny
            Allow from All
    
            <IfModule mod_rewrite.c>
                    Options -MultiViews
                    RewriteEngine On
                    RewriteCond %{REQUEST_FILENAME} !-f
                    RewriteRule ^(.*)$ app.php [QSA,L]
            </IfModule>
        </Directory>
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    
        SSLCertificateFile /etc/letsencrypt/live/domain1.com/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/domain1.com/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateChainFile /etc/letsencrypt/live/domain1.com/chain.pem
    </VirtualHost>
    </IfModule>
    
  3. domain1.com.conf

    <VirtualHost *:80>
        ServerName domain1.com
    
        Redirect 301 / https://www.domain1.com
    </VirtualHost>
    
  4. domain1.com-le-ssl.conf

    <IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerName www.domain1.com
        DocumentRoot /var/www/domain1.com
    
        ExpiresActive On
        /* ... */
    
        RewriteEngine On
        RewriteCond %{HTTP_HOST} ^https://domain1.com
        RewriteRule ^/(.*)$ https://www.domain1.com/$1 [L,R=301]
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    
        ErrorDocument 404 /404.html
    
        SSLCertificateFile /etc/letsencrypt/live/domain1.com/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/domain1.com/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateChainFile /etc/letsencrypt/live/domain1.com/chain.pem
    </VirtualHost>
    </IfModule>
    

当我尝试访问该网站时,会发生以下情况:

    http://test.domain1.com   -->    https://test.domain1.com   FAIL
    http://domain1.com        -->    https://www.domain1.com    SUCCESS
    http://www.domain1.com    -->    https://www.domain1.com    SUCCESS
    https://domain1.com       -->    https://domain1.com        FAIL
    https://www.domain1.com   -->    https://www.domain1.com    SUCCESS

如您所见,第一个和第四个条目都失败了。他们都向我的访客返回 404 Not Found,这对我来说是不可接受的。第一个甚至显示 SSL 警告(我认为 LetsEncrypt! 不支持通配符,所以我认为无法阻止此警告?)

是什么导致了我的测试。没有重定向到 www.?

是什么导致我的第四个条目最终服务于 404?

现在我还希望我的第二个域 (domain2.com) 指向此服务器/文件。该域托管在不同的位置(我从朋友那里得到的)并且使用不同的名称服务器。我不能简单地更改名称服务器(我认为?),因为第二个域具有链接到它的电子邮件托管,它使用其他提供商的名称服务器。目前,该域还拥有自己的 Web 服务器(但将来会消失),托管在 000.000.000.002。现在,它使用

 <meta http-equiv="refresh" content="0; url=https://www.domain1.com" />

在其 index.html 文件中添加标签以重定向到正确的服务器,但将来这必须在 DNS 记录中完成。

我应该怎么做?

总结一下:

  1. 我认为 CNAME * 是所有子域的通用名称?
  2. 我在虚拟主机文件中做错了什么?某些原因导致第四次重定向失败。
  3. 我应该如何处理指向我的第一个 IP 的第二个域?
  4. 还有其他方法只允许 HTTPS 连接吗? (这也应该在 API 虚拟主机上强制执行)。我听说过 HSTS,我应该实施吗?

一些 SEO 测试还指出,我需要 IP 重定向来进一步改善我的 SEO 结果。他们以此为例:

    RewriteCond %{HTTP_HOST} ^000\.000\.000\.001
    RewriteRule (.*) http://www.domain1.com/$1 [R=301,L]

我是否也应该出于 SEO 的目的而实施这个?我是否也应该为我的其他 IP 地址实现此功能?

这么多问题...

当然,如果您有任何其他建议,请分享您的意见!

【问题讨论】:

  • 如果表中的两个 URL 相同,您希望第四次重定向是什么?对于案例 1,是否有重定向?您可能有其他虚拟主机。每个 ip:port 组合列出的第一个是包罗万象的,我在任何地方都看不到 test1.domain.com。也许包括 apachectl -S 输出?

标签: redirect ssl dns apache2 virtualhost


【解决方案1】:

那里有很多问题!让我们尝试解决它们:

  1. 不确定您在这里问什么,也不是 CNAMES 专家,但会认为您至少需要 '*.domain1.com' 而不仅仅是 '*'

  2. 对于这两种情况,您都没有在 ServerName 或 ServerAlias 中明确注明您的备用服务器名称。在这种情况下,它将默认为配置中找到的第一台服务器。这是 api.domain.com 之一吗?如果是这样,那可能会解释 404,因为 SERVER_NAME 将(默认情况下)是客户端提供的名称,因此 api.domain1.com:80 设置只会重定向到他们发送的 https 版本(这似乎正在发生) ,然后它还会查看 api.domain1.com:443 配置,但找不到名称。您需要将备用名称添加到主 domain1.com 配置的 ServerAlias 设置中,或者将该配置移至第一个,使其成为默认配置,并且仅在显式使用 api.domain1.com 名称时使用 api 名称.

  3. 由于您似乎希望将其直接重定向到您的新站点,我将更新 DNS 以指向您的新 IP 地址,以节省您购买两台服务器的费用(在金钱和管理时间方面)。这可以在现有的 DNS 名称服务器上完成以保留电子邮件,但显然合并在一个上会更好。同时,在服务器配置中实施适当的 301 重定向,因为元重定向对搜索引擎的信号并不强,而且您似乎确实关心 SEO。

  4. 主要的方式是将http重定向到https。 HSTS 主要是一种安全功能,它在浏览器发出请求之前自动将 http 重定向到 https。这很有用,因为默认是 http(例如,在浏览器地址栏中键入 www.example.com,默认情况下会将您发送到 http://www.example.com 而不是 https://www.example.com),并且可以拦截它以防止升级到 https (这更难拦截)。但它有一些缺点:并非所有浏览器都支持它,您需要至少访问该网站一次以加载 HSTS 设置(尽管某些浏览器允许预加载此设置),如果未访问该网站,该设置将过期maxAge 时间(再次假设它没有预加载)。因此,它不应该被用作重定向的替代品,而更多的是作为支持 HSTS 的浏览器的强制执行。如果您想了解更多关于 HSTS 的信息,请在博客上 here

我还要说您有几种不同的重定向方法(api:80 具有 Rewrite,domain1:80 具有 Redirect,domain1:443 具有 Rewrite - 但具有非常严格且不正确的 RewriteCond)。就我个人而言,我更喜欢使用一种方法,因为它不太容易混淆,但这是个人问题(重定向也稍微快一些,但重写给你更多的权力,所以我更喜欢那个)。所以我倾向于有这样的配置:

<VirtualHost *:80>
    #This is the first host so is the default.
    #So although I've specified a ServerName and ServerAlias anything else not specified elsewhere will also end up here.
    ServerName www.domain1.com
    ServerAlias domain1.com

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    #Redirect everything to https:
    RewriteEngine on
    RewriteRule ^(.*)$ https://www.domain1.com$1 [R=301,L]
</VirtualHost>
<VirtualHost *:80>
    ServerName api.domain1.com

    ErrorLog ${APACHE_LOG_DIR}/api.error.log
    CustomLog ${APACHE_LOG_DIR}/api.access.log combined

    #Redirect everything to https:
    RewriteEngine on
    RewriteRule ^(.*)$ https://api.domain1.com$1 [R=301,L]
</VirtualHost>

然后对于 443 我会这样:

<VirtualHost *:443>
    #This is the first host so is the default.
    #So although I've specified a ServerName and ServerAlias anything else not specified elsewhere will also end up here.
    ServerName www.domain1.com
    ServerAlias domain1.com

    ErrorLog ${APACHE_LOG_DIR}/ssl.error.log
    CustomLog ${APACHE_LOG_DIR}/ssl.access.log combined

    #Redirect everything which is not already on the real www domain name to that:
    RewriteEngine on
    RewriteCond %{HTTP_HOST} !www.domain1.com
    RewriteRule ^(.*)$ https://www.domain1.com$1 [R=301,L]

    #all your other 443 config for www.domain1.com

</VirtualHost>
<VirtualHost *:443>
    ServerName api.domain1.com

    ErrorLog ${APACHE_LOG_DIR}/ssl.api.error.log
    CustomLog ${APACHE_LOG_DIR}/ssl.api.access.log combined

    #all your other 443 config for api.domain1.com

</VirtualHost>

请注意,我为每个虚拟主机添加了不同的日志文件,因此更明显的是哪个虚拟主机被击中。

还请注意,我重定向任何不是 www.domain1.com 的内容,而不是仅在人们键入 domain1.com 时才重定向的版本(我不确定是否会被用作可疑的 api.domain1.com 配置来首先)。

这也将照顾通过 IP 地址或任何其他名称访问您网站的任何人,因为它将始终重定向到您的真实 www.domain1.com 服务器名称。这对于 http 请求很容易,但对于 https 请求,如果您的证书不包含使用的服务器名,它们确实可能会收到证书错误。

LetsEncrypt 不支持通配符,但它们确实允许证书上有多个名称,因此您可以轻松获得 domain1.com 和 www.domain1.com 的证书,因为这通常被认为是最佳实践。您还可以添加您认为可能使用的任何其他域。对于您的 api.domain1.com 域,您还可以添加到同一个证书,或者为此获取单独的证书,因为您有单独的配置(您上面的配置不清楚您在做什么,因为它看起来一样config 但不确定这是否是一个错字)。

出于 SEO 的目的,最好只在一个 URL 下为您的网站提供服务,并使用重定向来强制执行该 URL,以上配置将执行此操作。这是为了防止如果您在 www.domain1.com/page1.html 和 https://www.domain1.com/page1.htmlhttps://domain1.com/page1.htmlhttp://000.000.000.001/page1.html ...等下提供相同的内容,Google 会认为您有重复的内容。

那里涵盖了很多内容,但希望为您指明正确的方向。

【讨论】:

  • 非常感谢。你回答了我所有的问题,并做了一个冗长的解释,这使得它更容易理解。您的提示确实为我指明了正确的方向,并且我设法将我的重写 :) 重写为实际有效的东西。我还实现了完美运行的 HSTS 标头。谢谢巴扎DP!你值得拥有一件斗篷。
猜你喜欢
  • 2018-11-21
  • 2017-01-02
  • 2023-04-10
  • 2011-02-26
  • 1970-01-01
  • 2014-12-29
  • 2013-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多