Varnish client.ip 显示 127.0.0.1

Varnish client.ip 显示 127.0.0.1

因此,我有一个类似 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.ip127.0.0.1因为nginx是客户端。Varnish 屏蔽这个值是没有意义的——即使在像您这样的 Varnish 位于前端代理后面的情况下,您也经常希望根据实际连接到 Varnish 的设备的 IP 地址来做出决定。

您真正想要做的是将nginx远程客户端 IP 地址放入专用标头(您已经使用 执行此操作X-Real-IP),并使用它来做出连接决策。我们在我们的环境中正是这样做的,其中 Apache 在 前面提供了 SSL 连接varnish,然后我们使用此标头做出访问决策。

它不如使用那么好client.ip(你不能使用acls 来匹配它),但它可以工作。我们这样做:

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

相关内容