HAProxy ACL 多个 OR 条件

jer*_*yjr 12 access-control-list haproxy

使用在 Ubuntu 12.04 上运行的 Haproxy 1.5.12

我需要将访问我的网站的权限限制为来自某些 IP 或在请求中具有已定义参数的请求。

因此,例如,以下请求应仅适用于授权 IP:

http://www-test.example.com/page.php
Run Code Online (Sandbox Code Playgroud)

并且应该从任何 IP(包括允许的 IP)满足此请求:

http://www-test.example.com/page.php?devtool=1
Run Code Online (Sandbox Code Playgroud)

我的 ACL 是:

acl is_test hdr(host) -m sub test
acl is_allowed src -f /etc/haproxy/allowed_ips
acl is_devtool urlp(devtool) 1
acl is_devtool hdr_sub(Referer) devtool=1
Run Code Online (Sandbox Code Playgroud)

如果专门使用,它们可以正常工作:

http-request deny if is_test ! is_allowed
Run Code Online (Sandbox Code Playgroud)

或者

http-request deny if is_test ! is_devtool
Run Code Online (Sandbox Code Playgroud)

但是,如果我将它们与 OR 结合使用,我将无法从允许的 IP 访问 URL(反转测试无济于事):

http-request deny if is_test ! is_allowed || is_test ! is_devtool
Run Code Online (Sandbox Code Playgroud)

知道如何做到这一点吗?

谢谢

Mic*_*bot 22

您似乎想要强加的测试是这样的:

A && !(B || C)
Run Code Online (Sandbox Code Playgroud)

……但这在逻辑上并不等同于您所写的内容,本质上就是这样……

(A && !B) || (A && !C)
Run Code Online (Sandbox Code Playgroud)

A && !(B || C)不使用括号作为优先级的逻辑等价物实际上是这样的:

A && !B && !C
Run Code Online (Sandbox Code Playgroud)

所以你要找的应该是这样的:

http-request deny if is_test !is_allowed !is_devtool
Run Code Online (Sandbox Code Playgroud)

或者,重申一下:在以下情况下拒绝该请求——

  • 它匹配is_test并且
  • 它不匹配is_allowed并且
  • 它不匹配 is_devtool

只要这些条件中的任何一个是错误的(不是测试,被允许,是开发工具),您的规则就不匹配,并且不会拒绝请求。

  • 顺便说一句,如果你好奇,这里有一个逻辑概念的名字——[德摩根定律](https://en.m.wikipedia.org/wiki/De_Morgan%27s_laws)。*“连词的否定是否定的析取。析取的否定是否定的结合。”* (4认同)