From 0f441a843ce2454bb212d0eac2455f1aa4c0e42f Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 22 Jul 2026 15:17:38 +0200 Subject: [PATCH] BUG/MINOR: resolvers: do not index resolvers names in the proxies Resolvers are self-sustaining sections that have their own list, but for the purpose of supporting TCP connections, a backend proxy is created with them, and it holds the same name as the section. Since we started to create a "default" resolvers section, a similarly named backend in TCP mode automatically appeared, resulting in issues such as the one described in GH #3445: defaults mode http frontend public bind :8001 default_backend default It yells: "... tries to use incompatible tcp proxy 'default' (:0) in a 'use_backend' rule (see 'mode')" because it in fact finds the hidden resolvers proxy. Depending on versions, adding such a default backend makes the issue go away or not. Worse, the following config: frontend public bind :8001 default_backend default actually routes the traffic to the local resolvers :-( Resolvers do not need to appear in proxies index tree, as they're looked up by find_resolvers_by_id() which iterates over all resolvers sections (i.e. tree not used), so we can safely avoid indexing them. Some other proxies are now protected against this via the use of PR_CAP_INT which also prevents indexing, but that flag changed multiple times along versions and is extremely sensitive in older ones, to the point of not being suitable for a backport. Instead, commit 116983ad94 ("MEDIUM: cfgparse: do not store unnamed defaults in name tree") added the following test to refrain from indexing an unnamed proxy in setup_new_proxy(): @@ -1718,7 +1718,8 @@ int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char * px->cap = cap; px->last_change = ns_to_sec(now_ns); - if (name && !(cap & PR_CAP_INT)) + /* Internal proxies or with empty name are not stored in the named tree. */ + if (name && name[0] != '\0' && !(cap & PR_CAP_INT)) proxy_store_name(px); if (!(cap & PR_CAP_DEF)) This part is totally suitable for backporting and permits to simply change the resolvers' proxy creation to pass NULL or an empty string instead of the resolvers section's name so that we don't index that proxy. That's what this patch does. For versions before 3.4, the commented patch above must be explicitly backported. This patch must be backported to 3.0. Thanks to Lukasz Nowak for reporting this bug. It's worth noting that this area is really falling apart and urgently needs attention. The internal API is currently too limited to permit reliable lookups, which is the reason why so many proxies are hidden that way. In an ideal world, all names would be indexed and caps and modes properly set to unambiguous values, so that lookup functions only look up specific caps and modes, and support being passed a mask to avoid matching undesired caps. At the very least a mask should be given in lookups, and a few extra caps should permit to distinguish regular proxies (those declared with the "frontend" and "backend" keyword, supporting use_backend) from other ones (rings, resolvers, log-forward etc). --- src/resolvers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resolvers.c b/src/resolvers.c index f646e6aa7..89dc104a0 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -3613,7 +3613,7 @@ static int resolvers_new(struct resolvers **resolvers, const char *id, const cha } /* allocate new proxy to tcp servers */ - p = alloc_new_proxy(id, PR_CAP_FE | PR_CAP_BE, &errmsg); + p = alloc_new_proxy(NULL, PR_CAP_FE | PR_CAP_BE, &errmsg); if (!p) { ha_free(&errmsg); // ignored err_code |= ERR_ALERT | ERR_FATAL; -- 2.47.3