HAProxy ACL 与文件中的 user-agent 不匹配
HAProxy ACL not matching user-agent in file
我正在尝试设置 HAProxy 以拒绝来自 user-agent 黑名单的请求,但它不起作用。
我正在按照答案中的说明进行操作:https://serverfault.com/a/616974/415429 (that is the example given in the official HAProxy docs: 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
访问浏览器,它 return 的状态是 404
而不是 403
(haproxy 在 docker 容器中转发端口 8080
到 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
其中第一行是我的用户代理(第二行是用 Host
header 进行测试,如下所述)。我可以在 Chrome 检查器中看到它,如果我在 haproxy 中捕获 user-agent
header 并记录它,我也可以看到它(完全一样)。
但如果我更改(仅用于测试目的):
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
header。然后它给出 403
状态代码(它有效,因为它与第二行匹配)。
然后,如果我将文件中的第 2 行 localhost:8080
更改为 localhost:8081
,它就会给出 404
(如预期的那样)。
因此,用户代理 header 似乎未正确检索到,或者与提供的值不匹配(我什至尝试捕获它以查看是否存在差异,但无济于事)。 Host
header 工作,艰难。
我还尝试使用 hdr(user-agent)
(小写),以及一些组合,例如 hdr_sub
而不是 hdr
,以及不区分大小写的 -i
选项,但所有这些尝试都没有奏效。我确定文件中的 user-agent
值是正确的。
更新 (2021-03-12)
我能够定义用户代理字符串并运行使用该用户代理进行卷曲:
$ 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
没有 return 403
.
我会尝试更多地挖掘它,看看我是否可以解决。
有什么建议吗?
我尝试用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:
[...] It differs from req.hdr() in that any commas present in the
value are returned and are not used as delimiters. This is sometimes
useful with headers such as User-Agent.
(奇怪的是,列表文件的官方示例使用 user-agent header with hdr 而不是 req.fhdr,这可能会产生误导,它是,至少对我来说)
我正在尝试设置 HAProxy 以拒绝来自 user-agent 黑名单的请求,但它不起作用。
我正在按照答案中的说明进行操作:https://serverfault.com/a/616974/415429 (that is the example given in the official HAProxy docs: 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
访问浏览器,它 return 的状态是 404
而不是 403
(haproxy 在 docker 容器中转发端口 8080
到 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
其中第一行是我的用户代理(第二行是用 Host
header 进行测试,如下所述)。我可以在 Chrome 检查器中看到它,如果我在 haproxy 中捕获 user-agent
header 并记录它,我也可以看到它(完全一样)。
但如果我更改(仅用于测试目的):
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
header。然后它给出 403
状态代码(它有效,因为它与第二行匹配)。
然后,如果我将文件中的第 2 行 localhost:8080
更改为 localhost:8081
,它就会给出 404
(如预期的那样)。
因此,用户代理 header 似乎未正确检索到,或者与提供的值不匹配(我什至尝试捕获它以查看是否存在差异,但无济于事)。 Host
header 工作,艰难。
我还尝试使用 hdr(user-agent)
(小写),以及一些组合,例如 hdr_sub
而不是 hdr
,以及不区分大小写的 -i
选项,但所有这些尝试都没有奏效。我确定文件中的 user-agent
值是正确的。
更新 (2021-03-12)
我能够定义用户代理字符串并运行使用该用户代理进行卷曲:
$ 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
没有 return 403
.
我会尝试更多地挖掘它,看看我是否可以解决。
有什么建议吗?
我尝试用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:
[...] It differs from req.hdr() in that any commas present in the value are returned and are not used as delimiters. This is sometimes useful with headers such as User-Agent.
(奇怪的是,列表文件的官方示例使用 user-agent header with hdr 而不是 req.fhdr,这可能会产生误导,它是,至少对我来说)