我希望 Apache 上的域名纯粹作为重定向存在。为此,我创建了/etc/apache2/sites-available/redirect.example.info.conf
以下内容:
<VirtualHost *:80>
ServerName redirect.example.info
ServerAdmin webmaster@localhost
Redirect / https://example.com/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
当我运行的时候certbot --apache
,它被重写为:
<VirtualHost *:80>
ServerName redirect.example.info
ServerAdmin webmaster@localhost
Redirect / https://example.com/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =redirect.example.info
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
/etc/apache2/sites-available/redirect.example.info-le-ssl.conf
并创建一个新文件:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName redirect.example.info
ServerAdmin webmaster@localhost
Redirect / https://example.com/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLCertificateFile /etc/letsencrypt/live/ca-webs.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/ca-webs.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
这确实按预期工作。重定向运行http://redirect.example.info
→ https://redirect.example.info
→ https://example.com
。但我不清楚它是如何工作的。重写的文件既有Redirect
命令,又有RewriteRule
命令,我本以为Redirect
(先来)会优先。这个文件实际上是如何评估的?
据我所知,
certbot --apache
它不会对现有的 HTTP VirtualHost 进行严格检查,它只是复制所有现有指令并添加 TLS 指令以生成新的 HTTPS VirtualHost。然后修改普通的 HTTP VirtualHost 以包含条件 HTTP --> HTTPS 重定向(仅重定向 certbot 已为其配置证书的 URI)。
生成的配置适用于大多数用例,但对于您而言,结果并不理想,我建议您手动编辑纯 HTTP 虚拟主机。删除
Rewrite*
certbot 添加的指令并恢复到原始配置,将访问者直接从 发送到 ,http://redirect.example.info
以https://example.com
防止中间重复访问https://redirect.example.info
。至于为什么
Rewrite*
指令虽然出现在Redirect
指令之后却具有优先权:这是因为有效的 apache httpd 配置不仅仅是配置指令放置和分组的位置、顺序和容器的结果,还取决于指令属于哪个模块。该信息在手册https://httpd.apache.org/docs/current/sections.html#merging的“合并”部分中并不明显
对于 mod_rewrite 来说,微妙的细节可能在于这句话“每个模块都有机会运行并执行它们喜欢的任何任务”。
模块可以/必须通过请求处理钩子注册自己 ,以便能够在正确的时刻“做它们喜欢的事情”,mod_rewrite 使用它来首先(或至少提前)使用
APR_HOOK_FIRST
钩子https://github.com/apache/httpd/blob/c72b74ccef72fb56becd55888a3aa783c4ab5b6b/modules/mappers/mod_rewrite.c#L5702据我所知,这就是
Rewrite*
指令优先于其他指令的方式,无论其他指令的排序方式和位置如何。您可以通过启用mod_info来了解钩子和所有启用的模块及其顺序(不要忘记将 ACL 添加到服务器信息 URL)。