我有一个公共网站,其中包含一些仅供私人/内部使用的 URL/目录。这些私人区域只能通过某些 IP 地址或已知的用户名/密码访问。
目前我通过这样的 .htaccess 文件实现此目的:
AuthType Basic
AuthName "Protected Area"
AuthUserFile /path/to/.htpasswd
SetEnvIf Remote_Addr 1.2.3.4 trusted
SetEnvIf X-Forwarded-For 1.2.3.4 trusted
# (Note I am aware X-Forwarded-For can be spoofed)
<RequireAny>
Require env trusted
Require valid-user
</RequireAny>
问题是我想在服务器前面添加 Varnish 来提供缓存。显然现有设置不适用于 Varnish,因为它无法以这种方式缓存受 .htaccess 文件限制的内容。
有没有什么方法可以让我继续使用我的 .htaccess 文件来保护我的内部页面,或者有没有类似的方法可以将安全责任放在 Varnish 本身上,而不需要每次我想要添加或修改限制时都更改 Varnish 的 VCL 文件?
答案1
您可以通过编写以下 VCL 在 Varnish 中完成此操作:
vcl 4.0;
acl allowed {
"1.2.3.4";
}
sub vcl_recv {
if(!client.ip ~ allowed && req.http.Authorization != "YWRtaW46YWRtaW4K") {
return (synth(401, "Restricted"));
}
return (hash);
}
sub vcl_synth {
if (resp.status == 401) {
set resp.http.WWW-Authenticate =
{"Basic realm="Restricted area""};
}
}
限制
虽然这可以正常工作,但用户名/密码检查是手动完成的。如果您有多个用户名/密码,则必须在 if 语句中添加每个用户。
确保绕过默认的 VCL 行为
在 Varnish 中处理Authorization
标题时,重要的是不要回到默认行为。Authorization
默认情况下,当存在标头时,Varnish 不会在缓存中查找项目。
因此,在您的逻辑中,您必须执行return (hash);
,正如我在示例中所做的那样。否则,您将回到默认行为,并且不会在缓存中查找项目。
Vmod_basicauth 作为替代方案
如果这成为一个交易破坏者,您可以编译以下 Varnish 模块,该模块允许您加载文件.htpasswd
并为您执行身份验证。
仍然在 Apache 中完成所有工作
如果您决定继续在 Apache 中执行此操作,您还需要更改 VCL。我解释说,当Authorization
存在标头时,默认行为将阻止 Varnish 在缓存中查找项目。
如果你再看看默认行为再次强调,你必须确保return (hash);
在达到默认行为之前执行,否则你必须自己重新实现其中的一部分,添加必要的if 语句