Apache配置中Redirect与Rewrite规则优先级及Certbot改写重定向配置的疑问
嘿,最近我在配置Apache纯重定向域名的时候碰到个头疼的问题,跟大家唠唠:我本来想让redirect.example.info这个域名所有请求都直接跳转到https://example.com/,于是手动写了/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申请SSL证书之后,这个配置文件被Certbot自动改写了,变成了这样:
<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>
同时还自动生成了一个新的SSL配置文件/etc/apache2/sites-available/redirect.example.info-le-ssl.conf,开头内容是:
<IfModule mod_ssl.c> <VirtualHost *:443> ServerName redirect.example.info
这时候我就犯嘀咕了:
- 原来的
Redirect指令和Certbot新加的RewriteRule谁优先级更高啊?会不会两个规则冲突? - Certbot为啥要多此一举加这条Rewrite规则?我本来的配置已经是跳转到目标域名了啊?
后来查了Apache的模块运行机制才搞明白:Redirect属于mod_alias模块,而RewriteRule属于mod_rewrite模块,mod_rewrite的优先级比mod_alias高,也就是说现在这个配置里,所有HTTP请求会先触发Rewrite规则,跳转到https://redirect.example.info/(也就是这个域名自己的HTTPS地址),而不是我原本想要的https://example.com/,这完全偏离了最初的需求!
那Certbot为啥要加这条规则呢?其实这是Certbot的默认操作——它会自动给HTTP的虚拟主机加上强制跳转HTTPS的规则,不管你原来有没有配置其他重定向。它的逻辑是先确保用户能访问到HTTPS站点,至于HTTPS站点要跳转到哪里,就需要我们自己再配置了。
那怎么解决这个问题,让所有请求不管HTTP还是HTTPS都最终跳转到https://example.com/呢?给大家几个可行的思路:
思路一:修改HTTP虚拟主机配置
直接把Certbot自动加上的那几行Rewrite规则删掉,保留原来的Redirect / https://example.com/。这样所有HTTP请求会直接跳转到目标域名的HTTPS地址,绕开本站的HTTPS。思路二:完善HTTPS虚拟主机配置
打开自动生成的redirect.example.info-le-ssl.conf,在<VirtualHost *:443>区块里加上Redirect / https://example.com/,这样不管是HTTP跳转过来的本站HTTPS请求,还是用户直接访问的本站HTTPS请求,都会再跳转到目标域名。最终的HTTPS配置大概是这样:<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/redirect.example.info/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/redirect.example.info/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf </VirtualHost> </IfModule>思路三:统一用Rewrite规则配置
如果你更习惯用mod_rewrite的规则,也可以把HTTP虚拟主机里的Redirect指令删掉,直接修改Rewrite规则,让它一步到位跳转到目标域名:RewriteEngine on RewriteRule ^ https://example.com%{REQUEST_URI} [END,NE,R=permanent]这样就不用管优先级问题了,所有HTTP请求直接跳转到目标地址。
总之核心就是搞清楚Apache不同模块指令的优先级,以及Certbot的默认配置逻辑,再根据自己的需求调整就行。
备注:内容来源于stack exchange,提问作者TRiG

