HaProxy 动态 lists/maps

HaProxy dynamic lists/maps

我正在尝试让 CORS 与基于我们系统中存在的客户的域白名单一起工作。我们有一个带有白色标签的产品,让公司 CNAME 一个自定义域到我们的系统。我们需要能够 即时 通过添加 Access-Control-Allow-Origin: http://some.custom.domain header 来允许来自任何这些自定义域的 Origin来自 HaProxy 的响应。

我一直在阅读有关从 haproxy 加载 lists/maps 的不同方式,但我只是没有确定最佳实施方式。我想出了大约 3 种可能的方法来做到这一点,但我想看看是否还有其他人有一些见解。到目前为止我的选择:

  1. 存储 map 个可用域,我可以在添加 header 时查找这些域。这个地图文件如何被填充是目前的问题。我想我可以在启动时通过 LUA 调用 API 来创建文件吗?或者它可能是一个 NFS 挂载文件?每次将新域添加到我们的系统时,我们都必须重新加载,要么通过相同的 api 调用,要么直接到套接字上的映射 api。

  2. 使用 LUA 通过 haproxy 在每个任务上向 api 发出实时请求,以验证在 Origin 上传入的域是否合法并添加header 中。假设我们可以为 memcached 找到 LUA 客户端库,则可能会使用 Memcached 以实现最小开销。

  3. 可能实施某种基于 DNS 的解决方案,我们 运行 我们自己的 DNS 服务器解析这些自定义域并让 HaProxy 对其进行查找。我不知道这是否可能,我只知道 haproxy 具有 DNS 功能。奇怪的是,我们实际上并不想解析到 IP,我们只想要 "yes" 或 "no" 答案。

还有其他人知道这个问题的明显解决方案吗?我正在寻找易于实施的方法,但最终请求本身的开销最小,因为这需要在每个带有 Origin header 的请求上发生。

任何见解表示赞赏!

1/图解:
我认为最简单和最有效的解决方案是将可用域存储在地图中。 然后,您可以使用 set map, add map 通过 HAProxy 套接字更新地图,.. 每当域发生变化时,无需在此处重新加载。

2/LUA解法:
也可以用 LUA 使用这样的函数来做到这一点:

core.register_action("validate_origin", {"http-req"}, function(txn)
   local origin= txn.http:req_get_headers()headers["origin"][0]
   local sock = core.tcp()
   sock:connect("<API-IP>", <API-PORT>)
   sock:send("GET /api?validate=".. origin .. " HTTP/1.1\r\n Host:www\r\n ")
   domain = sock:receive("*a")
   sock:close()
   txn:set_var("txn.allow_origin", domain)
end)

有问题的前端中的 HAProxy conf:

http-request capture hdr("Origin") len 128
http-request lua.validate_origin if  { capture.req.hdr(0) -m found }
http-response add-header Access-Control-Allow-Origin %[var(txn.allow_origin)] if  { capture.req.hdr(0) -m found }

此解决方案引入了更多开销,因为 HAProxy 必须为每个 CORS 请求依赖外部资源(并可能等待它)。