Add geo routing to different backends for same domain

This commit is contained in:
Thomas Lynch
2025-03-15 12:45:22 +11:00
parent c0a2f77f8b
commit 84ddfbc719
9 changed files with 74 additions and 27 deletions

View File

@ -47,11 +47,17 @@ services:
nginx:
ports:
- 1081:80
- 1082:80
image: "nginx:latest"
volumes:
- ./nginx:/usr/share/nginx/html
nginx2:
ports:
- 1082:80
image: "nginx:latest"
volumes:
- ./nginx2:/usr/share/nginx/html
varnish:
network_mode: host
image: varnish:latest

View File

@ -165,7 +165,7 @@ backend haproxy-to-varnish-cache
server varnish unix@/shared-sockets/haproxy-to-varnish-cache.sock check observe layer7 inter 1s
backend servers
balance leastconn
balance roundrobin
use-server %[lua.get_server_names] if TRUE
backend bot_check_post_throttle

View File

@ -1 +1,2 @@
localhost 127.0.0.1:1081
localhost 127.0.0.1:1081;OC
localhost 127.0.0.1:1082;NA

View File

@ -1 +1 @@
localhost admin

View File

@ -1,11 +1,14 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>hello, world</p>
</body>
</html>
<head>
<meta charset="utf-8">
<title>test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>hello from nginx 1</p>
</body>
</html>

BIN
nginx2/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

14
nginx2/index.html Normal file
View File

@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>hello from nginx 2</p>
</body>
</html>

View File

@ -1,19 +1,37 @@
package.path = package.path .. "./?.lua;/etc/haproxy/scripts/?.lua;/etc/haproxy/libs/?.lua"
package.path = package.path .. "./?.lua;/etc/haproxy/scripts/?.lua;/etc/haproxy/libs/?.lua"
local bot_check = require("bot-check")
local utils = require("utils")
local server_cn_split_regex = "([^;]+);(%u%u)$"
local backends_map = Map.new('/etc/haproxy/map/backends.map', Map._str)
function get_server_names(txn)
local key = txn.sf:hdr("Host")
local user_cn = txn:get_var("txn.xcn") or "XX"
local value = backends_map:lookup(key or "")
if value ~= nil then
local filtered_backends = {}
local all_backends = {}
local vals = utils.split(value, ",")
-- todo: something smarter?
return vals[math.random(#vals)]
else
return ""
-- Single pass to filter and collect backends
for _, backend in ipairs(vals) do
local backend_server_name, server_cn = backend:match(server_cn_split_regex)
if backend_server_name then
table.insert(all_backends, backend_server_name)
if server_cn == user_cn or server_cn == "XX" then
table.insert(filtered_backends, backend_server_name)
end
end
end
-- Randomly select from filtered backends if available
if #filtered_backends > 0 then
return filtered_backends[math.random(#filtered_backends)]
elseif #all_backends > 0 then
-- If no filtered backends, randomly select from all backends
return all_backends[math.random(#all_backends)]
end
end
return ""
end
core.register_fetches("get_server_names", get_server_names)

View File

@ -1,8 +1,10 @@
package.path = package.path .. "./?.lua;/etc/haproxy/scripts/?.lua;/etc/haproxy/libs/?.lua"
package.path = package.path .. "./?.lua;/etc/haproxy/scripts/?.lua;/etc/haproxy/libs/?.lua"
local pow_difficulty = tonumber(os.getenv("POW_DIFFICULTY") or 18)
local backends_map = Map.new('/etc/haproxy/map/backends.map', Map._str)
local utils = require("utils")
local server_cn_split_regex = "([^;]+);(%u%u)$"
local map_space_split_rexex = "([^%s]+)%s+([^%s]+)"
-- setup initial server backends based on hosts.map
function setup_servers()
@ -23,21 +25,24 @@ function setup_servers()
tcp:settimeout(10);
tcp:connect("127.0.0.1", 2000); --TODO: configurable port
while line do
local domain, backend_host = line:match("([^%s]+)%s+([^%s]+)")
local new_map_value = server_prefix..counter
local domain, backend_data = line:match(map_space_split_rexex)
local backend_host, continent_code = backend_data:match(server_cn_split_regex)
local new_map_value = server_prefix .. counter .. ';' .. continent_code
local existing_map_value = backends_map:lookup(domain)
if existing_map_value ~= nil then
current_backends = utils.split(existing_map_value, ",")
local current_backends = utils.split(existing_map_value, ",")
if not utils.contains(current_backends, new_map_value) then
new_map_value = new_map_value .. "," .. existing_map_value
end
end
print("setting hosts.map "..domain.." "..new_map_value)
print("setting hosts.map " .. domain .. " " .. new_map_value)
core.set_map("/etc/haproxy/map/backends.map", domain, new_map_value)
local server_name = "servers/websrv"..counter
local server_name = "servers/websrv" .. counter
--NOTE: if you have a proper CA setup,
if verify_backend_ssl ~= nil then
tcp:send(string.format("add server %s %s check ssl verify required ca-file ca-certificates.crt sni req.hdr(Host);", server_name, backend_host))
tcp:send(string.format(
"add server %s %s check ssl verify required ca-file ca-certificates.crt sni req.hdr(Host);",
server_name, backend_host))
else
tcp:send(string.format("add server %s %s;", server_name, backend_host))
end
@ -46,7 +51,7 @@ function setup_servers()
counter = counter + 1
end
handle:close()
tcp:close()
tcp:close()
end
core.register_task(setup_servers)