基于客户端 IP 的负载均衡器后面的 Varnish ACL

基于客户端 IP 的负载均衡器后面的 Varnish ACL

在以下设置中:

Client -> LB -> Varnish

我想配置 Varnish acls 以根据客户端的 IP 采取某些操作。LB 将客户端的 IP 发送到名为“ClientIP”的变量中,Varnish 可以通过该变量读取。req.httpd.ClientIP.我尝试了以下方法:

acl admin_net {
  "10.10.1.160"/27;
}

sub vcl_deliever {
  if (req.http.ClientIP ~ admin_net) {
  // do something ... 
  }  
}

但 VCL 编译失败,提示“Expected CSTR got 'admin_net'”(C 字符串?)。我可以通过 解决这个问题req.http.ClientIP ~ "10.10.1.*"),但我必须注释掉 ACL 行。

还有其他方法可以使其与 ACL 配合使用吗?我client.ip也看过了,这是一个只读变量。在上述设置中,它包含 LB 的 IP,而不是客户端的 IP。

答案1

实际上,Varnish 将 client.ip 作为不同的数据类型处理,因此您可以针对此值使用 ACL。这不适用于 req.http.ClientIP(或所有 req.http.* 参数)等文本值。因此,使用此文本值的正则表达式似乎是一个很好的解决方案。

或者,您可以使用特定模块来设置客户端 IP。例如,我发现了这个:http://lassekarstensen.wordpress.com/2013/07/22/setting-client-ip-in-varnish-vcl-with-libvmod-ipcast/

答案2

这可以使用标准网,假设 ClientIP 标头已在 vcl_recv() 中设置。例如:

vcl 4.0;
import std;

acl admin_net {
  "10.10.1.160/27";
}

sub vcl_deliver {
  if (std.ip(req.http.ClientIP,"0.0.0.0") ~ admin_net) {
  // do something ... 
  }  
}

答案3

如果您的负载均衡器支持此处概述的“PROXY”协议,那么 alexus 的答案实际上就是正确答案:https://info.varnish-software.com/blog/topic/proxy-protocol

使用 PROXY 协议,您的负载均衡器将会告知 Varnish 真实的客户端 IP 地址并相应地设置 client.ip。

Alexus 的代码工作原理:

acl e410 {
    "5.9.0.0"/16;
}

sub vcl_recv {
    ...
    if (client.ip ~ e410) {
        error 410;
    }
    ...
}

上述代码示例将完全按照您的要求执行。支持 PROXY 协议的负载均衡器包括:

  • HA代理
  • NginX
  • Apache HTTPD
  • 亚马逊的弹性负载均衡器

.. 仅举几个例子。下面是更完整的列表:https://www.haproxy.com/blog/haproxy/proxy-protocol/

答案4

以下是我在 varnish 中实现 acl 的方法:

acl e410 {
    "5.9.0.0"/16;
}

sub vcl_recv {
    ...
    if (client.ip ~ e410) {
        error 410;
    }
    ...
}

尝试查看内部varnishlog并发布输出,这样会更容易找出问题所在......

相关内容