因此,我有一个类似 Nginx -> varnish -> apache2 的设置,如果我收到一个带有静态文件的请求,它将通过 nginx 发送到 varnish,然后再返回到 nginx,因为这比让 apache2 服务它要快得多。我的问题是,当我执行
sub vcl_fetch {
set beresp.http.X-Tabulex-Client = client.ip;
要查看客户端的 IP 地址,我被告知它是 127.0.0.1 (X-Tabulex-Client 127.0.0.1) 在 vcl_recv 中我有:
sub vcl_recv {
if ((!req.url ~"^/typo3temp/*" && !req.url ~"^/typo3/*") &&req.url ~"\.(jpg|css|gif|png|js)(\?.*|)$"){
set req.backend = aurum;
set client.identity = req.http.X - Forwarded - For;
} elseif(client.ip == "192.168.3.189") {
/* Traffic from the other Varnish server, serve using real backends */
set req.backend = balance;
/* Set client.identity to the X-Forwarded-For (the real IP) */
set client.identity = req.http.X - Forwarded - For;
} else{
/* Traffic coming from internet, use the other Varnish as backend */
set req.backend = iridium;
}
}
nginx 配置包含
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_intercept_errors on;
第一次发送到 varnish 时,再次从 varnish 接收时没有任何反应。
我不确定问题出在哪里。我希望 client.ip 包含外部 ip 地址,这样我就可以将其用于 acl。有什么想法吗?
答案1
的值client.ip
是127.0.0.1
因为nginx
是客户端。Varnish 屏蔽这个值是没有意义的——即使在像您这样的 Varnish 位于前端代理后面的情况下,您也经常希望根据实际连接到 Varnish 的设备的 IP 地址来做出决定。
您真正想要做的是将nginx
远程客户端 IP 地址放入专用标头(您已经使用 执行此操作X-Real-IP
),并使用它来做出连接决策。我们在我们的环境中正是这样做的,其中 Apache 在 前面提供了 SSL 连接varnish
,然后我们使用此标头做出访问决策。
它不如使用那么好client.ip
(你不能使用acl
s 来匹配它),但它可以工作。我们这样做:
if (! (
req.http.X-Real-IP ~ "^10\." ||
req.http.X-Real-IP ~ "^100\.100\." ||
req.http.X-Real-IP ~ "^200\.200\."
)) {
error 403 "Forbidden";
}
Varnish 不提供client.ip
使用自定义标头覆盖的本机机制,但它可能的无论如何都可以解决问题,因为您可以在配置中插入任意 C 代码。
这里是一个与您的情况完全相似的示例,其中包括用另一个值替换的示例,client.ip
以便可以在 Varnish ACL 中使用。
答案2
如果您使用 Varnish 作为 Rackspace Cloud Load Balancer 后面的前端 Web 服务器(我们的后端是 NGINX),那么您需要使用如下模式:
if (!(
req.http.X-Forwarded-For ~ "1\.2\.3\.4" ||
req.http.X-Forwarded-For ~ "2\.3\.4\.5"
)) {
# IP-based Rules
}
Rackspace Cloud Load Balancer 不会将任何东西传递127.0.0.1
给 Varnish,而是将其作为client.ip
。此外,我尝试使用更严格的模式,如 ,^2\.3\.4\.5$
但它不匹配。我认为负载均衡器正在向X-Forwarded-For
标头添加额外的字符。
答案3
如果您的请求中包含 req.http.X-Real-IP,则可以使用 std 模块的函数 ip() 将字符串(如 req.http.X-Real-IP)转换为 IP 类型,然后使用 ~ 运算符将其与 ACL 列表进行比较。这比多次比较某些 IP 字符串更有效率。
acl aclRestricted { "1.1.1.1"; "2.2.2.2"; } if (std.ip(req.http.X-Real-IP, "0.0.0.0") ~ aclRestricted ) { ... }
参考Varnish V4.1:https://varnish-cache.org/docs/4.1/reference/vmod_std.generated.html#func-ip