当位于一个或多个反向代理之后时,通过 X-Forwarded-For 检查 Varnish ACL

当位于一个或多个反向代理之后时,通过 X-Forwarded-For 检查 Varnish ACL

我在反向代理后面运行 Varnish(在本地主机上运行,​​用于 SSL 卸载)。代理设置 X-Forwarded-For 标头,如果标头已存在,则将自身添加到标头中。

当我进行 ACL 检查时,我当然希望检查原始客户端的 IP,而不是我的代理的 IP,所以我不能使用该client.ip字段。使用stdvmod 我可以执行以下操作:

vcl 4.0;
import std;
sub vcl_recv {
    if (std.ip(regsub(req.http.X-Forwarded-For, ", 127.0.0.1$", ""), "0.0.0.0") ~ my_acl) {
        ...do stuff...
    }
}

换句话说,我在运行代理 IP (127.0.0.1) 并将std.ip其与我的 ACL 进行比较之前,先从标头中修剪代理的 IP (127.0.0.1)。这很有效,除了...

如果在到达我的代理之前已经设置了 X-Forwarded-For 标头,则此操作会失败。在这种情况下,XFF 标头包含三个或更多 IP 地址。修剪最后一个 IP 地址后,仍会留下多个 IP 地址,并std.ip因此而受阻,导致请求延迟几秒钟,当然也无法检查 ACL。

我需要确保在删除代理后,XFF 标头仅包含一个 IP(IPv4 或 IPv6)。这应该是客户端的 IP。

例如:

X-Forwarded-For: 10.10.1.1, 10.10.2.2, 2001:a031:100a:dead:beef:1234:1234:1234, 127.0.0.1

应该成为

X-Forwarded-For: 2001:a031:100a:dead:beef:1234:1234:1234, 127.0.0.1

由于我无法信任来自外部的任何 XFF 标头,因此我想丢弃代理看到的客户端 IP 以外的任何内容。我的代理不支持修改 XFF 标头,因此我需要在 Varnish 中执行此操作。

当我可以与标题进行交互时,Varnish 流程中的第一个点是在vcl_recv(),此时 Varnish 已将其添加client.ip到列表末尾。

我希望使用正则表达式将最后两项(IPv4 或 IPv6)捕获到编号的捕获组 ($1) 中,然后简单地用捕获组替换标头。如下所示:

vcl 4.0;
import std;
sub vcl_recv {
    set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "([a-f0-9:.]+, [a-f0-9:.]+)$", "\1");
}

第三个参数(替换正则表达式匹配的字符的字符串)不起作用。即使正则表达式仅捕获最后两个 IP 地址,生成的标头也与之前完全相同。

我怎样才能丢弃 XFF 标头中最后两个 IP 地址以外的任何内容?

答案1

您的正则表达式似乎没问题。我唯一看到的是您请求单独替换组。

如果你 ^(.*)在正则表达式的开头添加并将第二个参数替换为\2

set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^(.*)([a-f0-9:.]+, [a-f0-9:.]+)$", "\2");

}

话虽如此,我认为更改 XFF 标头不是一个好主意。添加标头应该比更改和删除已通过中间代理传输的信息更标准。

相关内容