HAProxy ACL 与文件

问题描述

我正在尝试设置 HAProxy 以拒绝来自用户代理黑名单的请求,但它不起作用。

我正在按照答案中的说明进行操作:https://serverfault.com/a/616974/415429(这是官方 HAProxy 文档中给出的示例:http://cbonte.github.io/haproxy-dconv/1.8/configuration.html#7

官方文档中的例子是:acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test

我创建了一个演示来模拟用户代理在某种情况下无法工作的问题:

defaults
    timeout connect 5s
    timeout client 30s
    timeout server 30s

frontend frontend
    mode http
    bind :80

    acl  is_blacklisted_ua  hdr(User-Agent) -f /path/to/ua-blacklist.lst
    http-request deny deny_status 403 if is_blacklisted_ua

    http-request deny deny_status 404

然后,如果我在 localhost:8080 处访问浏览器,它会返回状态 404 而不是 403(haproxy 位于将端口 8080 转发到 {{1 }})

文件 80 只是:

/path/to/ua-blacklist.lst

其中第一行是我的用户代理(第二行是使用 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/89.0.4389.82 Safari/537.36 localhost:8080 标头进行测试,如下所述)。我可以在 Chrome 检查器中看到它,如果我在 haproxy 中捕获 Host 标头并记录它,我也可以看到它(完全相同)。

但如果我改变(仅用于测试目的):

user-agent

致:

acl  is_blacklisted_ua  hdr(User-Agent) -f /path/to/ua-blacklist.lst

使用 acl is_blacklisted_ua hdr(Host) -f /path/to/ua-blacklist.lst 标头。然后它给出 Host 状态代码(它有效,因为它与第二行匹配)。

然后,如果我将文件中的第 2 行 403 更改为 localhost:8080,它会给出 localhost:8081(如预期)。

因此,似乎用户代理标头未正确检索,或者无法匹配提供的值(我什至尝试捕获它以查看是否存在差异,但无济于事)。 404 标头很有效。

我还尝试使用 Host(小写),以及一些组合,例如 hdr(user-agent) 而不是 hdr_sub,以及不区分大小写的 hdr 选项,但是所有这些尝试也没有奏效。我确定文件中的 -i 值是正确的。

更新 (2021-03-12)

我能够定义用户代理字符串并使用该用户代理运行 curl:

user-agent

我还尝试了一个带有空格 $ curl -o /dev/null -s -w "%{http_code}\n" -H "user-agent: test-ua" http://localhost:8080 403 用户代理,它也能工作,但是使用用户代理 test-ua space 没有返回 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/89.0.4389.82 Safari/537.36

我会努力挖掘更多,看看我能不能解决

有什么建议吗?

解决方法

我尝试用curl挖掘问题,看到在我测试的情况下达到了返回403的预期效果。

然后我尝试使用整个用户代理但它不起作用,所以我尝试只使用用户代理的开头并包含其他部分,直到我包含 (KHTML,like Gecko) 并且它停止工作.

所以我最终发现逗号不起作用(使用 curl 和一个非常简单的 test,comma 用户代理测试)。然后我发现 HAProxy 以不同的方式处理列表文件中的逗号,如下所示:

https://discourse.haproxy.org/t/comma-in-acl-list-file/2333/2

我能够使用上述答案中提供的解决方案解决它,使用 req.fhdr: req.fhdr(User-Agent) 而不是 hdr(User-Agent)

根据docs

[...] 它与 req.hdr() 的不同之处在于任何逗号出现在 返回值并且不用作分隔符。这是有时 对 User-Agent 等标头很有用。

(奇怪的是,列表文件的官方示例使用带有 hdr 的用户代理标头而不是 req.fhdr,这可能会产生误导,至少对我来说是这样)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...