具有多个域的 Apache 虚拟主机

Apache virtual hosts with multiple domains

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

目前我有 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-乐-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-乐-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/ [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

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

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

是什么导致我的第四个条目最终出现 404?

现在我还希望我的第二个域 (domain2.com) 指向这个 server/files。这个域托管在不同的位置(我从朋友那里得到的)并且使用不同的名称服务器。我不能简单地更改名称服务器(我认为?),因为第二个域有电子邮件托管链接到它,它使用其他提供商的名称服务器。目前,该域也有自己的 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/ [R=301,L]

我是否也应该出于 SEO 目的实施此操作?我是否也应该为我的其他 IP 地址实施此操作?

这么多问题...

当然,如果您有其他建议,欢迎交流!

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

  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 仅在 [=71] 时使用=].domain1.com 名称被显式使用。

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

  4. 主要是把http重定向到https。 HSTS 主要是一种安全功能,它会在浏览器发出请求 之前自动将 http 重定向到 https。这很有用,因为默认值为 http(例如,如果您想阅读更多关于 HSTS 的信息,在浏览器地址栏中输入 www.example.com 默认情况下会将您转到 http://www.example.com rather than https://www.example.com), and this can be intercepted to prevent an upgrade to https (which is more difficult to then intercept). It has some downsides though: Not all browsers support it, you need to visit the website at least once to load the HSTS setting (though some browsers allow pre-loading of this), and the setting will expire if the site is not visited in the maxAge time (again assuming it's not preloaded). So it should not be used as a replacement to redirects but more as an enforcement of it for browsers that support HSTS. Blogged about it here

我还想说你有几种不同的重定向方法(api:80 有重写,domain1:80 有重定向,domain1:443 有重写 - 但限制性很强且不正确重写条件)。就个人而言,我更喜欢使用一种方法,因为它不那么令人困惑,但这是个人问题(重定向也稍快一些,但重写给你更多的力量,所以我更喜欢那种方法)。所以我倾向于这样配置:

<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 [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 [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 [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 域,您还可以添加到同一个证书,或者为此获得一个单独的证书,因为您有单独的配置(上面的配置不清楚您在做什么)因为它看起来像相同的配置,但不确定这是不是错字)。

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

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