Apache 中的 Anubis 实现真的需要3个虚拟主机吗?
我正在尝试在Linux Debian + Apache服务器上配置Anubis,以满足我的需求。
具体来说,我希望能够快速为每个虚拟主机启用或禁用Anubis,同时尽可能减少与先前配置的改动。
文档中有关于Apache配置的说明页面:
https://anubis.techaro.lol/docs/admin/environments/apache
该页面提及在原有两个虚拟主机基础上新增了专用于3001端口的第三个虚拟主机。
由于我不喜欢这种做法,尝试了在保留两个虚拟主机的前提下实现的方法。
我认为通过以下方式可实现:
- 将首个虚拟主机定义为
<VirtualHost *:80 *:3001>替代<VirtualHost *:80>。 - 在该虚拟主机的RewriteRule规则中添加条件,当远程主机为
::1时触发规则。
由此重写序列呈现如下形式:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{REMOTE_ADDR} !^::1$
RewriteRule (.*) https://%{SERVER_NAME}$1 [R,L]
关于启停控制,我仅添加了如下代理指令:
<IfFile /etc/anubis/mysite.env>
Include /etc/apache2/anubis_proxy.conf
</IfFile>
…其中/etc/apache2/anubis_proxy.conf包含标准指令:
# 这些头部必须设置,否则Anubis将抛出“管理员配置错误”。
RequestHeader set "X-Real-Ip" expr=%{REMOTE_ADDR}
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set "X-Http-Version" "%{SERVER_PROTOCOL}s"
ProxyPreserveHost On
ProxyRequests Off
ProxyVia Off
ProxyPass / http://[::1]:8923/
ProxyPassReverse / http://[::1]:8923/
通过这种方式,只需添加、重命名或删除/etc/anubis/mysite.env文件即可启用或禁用Anubis(若所有配置通用,该文件甚至可仅作为通用文件的符号链接)。
显然,该方案可行。
进一步思考时我产生疑问:
既然现已存在规则条件进行区分,是否真的必须使用3001端口?
我尝试取消端口限制,将TARGET值定义为TARGET=http://localhost:80而非TARGET=http://localhost:3001。
同时将配置简化为<VirtualHost *:80>。
显然,至少在我的测试服务器上,这种配置依然有效。
是否有理由不验证这种方案?是否应该避免将测试环境中看似有效的配置直接复制到生产环境?
damienvancouver:
是的,您说得对,可以跳过 :3001 虚拟主机,改用 :80 虚拟主机。
但关键点在于:在实际生产环境中,该 :80 虚拟主机正用于 HTTP 到 HTTPS 的实时重定向。当访客通过 http://example.com 访问时,需将其重定向至 https://example.com。但当 Anubis 访问 http://example.com 时,既不能重定向,还需输出所有链接(如 CSS/JS 文件及其他静态资源)均包含 “https://” 的 HTML 内容。
借助Apache的mod_rewrite和mod_setenvif模块,这很容易实现。以下是我的实现方法:
Apache模块:启用rewrite和setenvif
Apache 80端口配置:
<VirtualHost *:80>
ServerName example.com
Serveralias www.example.com
RewriteEngine On
# 将除LetsEncrypt外的所有HTTP流量转发至HTTPS,保持相同URL
RewriteCond %{REQUEST_URI} !^/.well-known [NC]
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
####/CTAR002 force SSL
# 否则,若此请求来自Anubis的代理请求,请设置HTTPS=on以获取HTTP链接输出:
SetEnvIf X-Forwarded-Proto https HTTPS=on
# ... 其余虚拟主机配置内容在此处,包括日志记录、PHP设置等。操作方式与您在*:443端口上的常规配置完全相同!
</VirtualHost>
apache port 443 configuration:
<Virtualhost *:443>
ServerName example.com
Serveralias www.example.com
# Proxy via anubis at 127.0.0.1:8923
RequestHeader set "X-Real-Ip" expr=%{REMOTE_ADDR}
RequestHeader set "X-Forwarded-For" expr=%{REMOTE_ADDR}
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set "X-Http-Version" "%{SERVER_PROTOCOL}s"
ProxyPreserveHost On
ProxyRequests Off
ProxyVia Off
ProxyPass / http://127.0.0.1:8923/ nocanon
ProxyPassReverse / http://127.0.0.1:8923/ nocanon
因此端口80虚拟主机有两种处理方式:
- 若未检测到
X-Forwarded-Proto=https且非LetsEncrypt证书,则将所有流量转发至SSL - 否则,它会启用HTTPS并通过
http://localhost:80端口提供服务
端口443虚拟主机仅将所有请求代理至Anubis。若移除Anubis配置,则会恢复直接提供网站服务。
此配置的唯一缺陷在于:若配置有误,极易引发301重定向循环。虽然采用:3001方案更易部署,但我更倾向于仅使用两个虚拟主机。
GingkoFr:
这就是为什么我不使用条件语句 RewriteCond %{HTTP:X-Forwarded-Proto} !https。
我采用的是 RewriteCond %{REMOTE_ADDR} !^::1$。
原始请求从 ::1 地址发出的可能性极低,即便发生这种情况,通常也不需要将其重定向到 https 或 Anubis。
damienvancouver:
是的,这样应该没问题!任何能将Anubis与真实/外部80端口流量区分开的方法都可行。外部流量不可能来自本地主机。
但这仍需处理当请求来自Anubis时启用HTTPS的设置。因此您可能仍需在:80虚拟主机配置中至少添加SetEnv HTTPS=on指令。由于您已通过RewriteRule规则处理所有非Anubis流量,可能无需像我之前那样使用SetEnvIf条件语句。
?????同样的道理,是否可以直接使用 :443 端口替代:3001端口?
