[Dnsmasq-discuss] [PATCH] Re: --server=/example/ --server=/example/ behaviour

Simon Kelley simon at thekelleys.org.uk
Mon May 3 16:49:08 UTC 2021

This is just to mark that I have spent the afternoon thinking about
this, and I'm in the process of a rather larger re-factor of the code.

The aim of this is to cover the points Petr makes below, but
additionally, to:

1) Allow a fast matching between subdomains in the configuration and the
query domain, s=to handle the ad-blocks that use thousands of
--local=/porn.here/ configuration lines.

2) To make the storage of --local=/domain/ more efficient.

3) To tidy up the mess that is search servers.

The first part of the plan is to remove the overloading of struct server
to store --address, --local and --rebind-domain-ok

There will be a data-structure that just holds domains, around which a
fast search algorithm can be put. Each domain will hold a pointer to a
struct server and a pointer to a list of addresses, to handle the
situation of


Which answers A queries for example.com with but forwards other
queries to

The algorithm for forwarding is

1) look up query-domain for domain-structure above with longest match.
2) Is there a suitable address? If so answer with that.
3) Otherwise, the struct server pointer points to the one of the set of
servers which  cover this domain, all linked in a ring with a new
group_next pointer.

The last_server feature is implemented by setting a flag for whichever
server in this ring is last used. That server has the forwarded counts
and times as well.

This makes the forwarding code which cycles through all eligible servers
very easy.

This code replaces some really knarly and old code, so  it's not a small
job to re-write it, especially as the list of servers is dynamic, with
DBUS etc.


On 19/04/2021 19:19, Petr Menšík wrote:
> Hi,
> I managed to prepare minimal change required. I think there is plenty of
> space to optimize daemon->servers handling, but added slight addition to
> it only. It introduces structure for every domain, keeping its state.
> According to dig ch txt servers.bind, it does what I tried. Reduces
> number of queries sent to alternative server, but queries it from time
> to time. Just like servers without domain.
> It sometimes tries all servers, but usually just one of them. Of course
> nothing should change with only single server=/example/
> I tested it with --servers-file=servers.conf, it can survive adding,
> commenting out and adding servers again.
> What do you think?
> On 4/16/21 6:26 PM, Petr Menšík wrote:
>> Hi all,
>> I am trying to improve dnsmasq to handle better redirections of some
>> given domains to multiple servers. Current implementation allows
>> specifying multiple domains in single --server= statement, but only one
>> server. It can be specified by multiple --server statements.
>> But some people would like domain specific forwards to choose outgoing
>> forwarders in similar way to common forwarders. By common forwarders I
>> mean multiple --server=<ip> without any domain specification, the same
>> way /etc/resolv.conf parsing with at least two nameservers works.
>> Current implementation chooses the best responding server (last_server)
>> and only sometime tries also other servers.
>> I would like to implement similar logic not only for global forwarders,
>> but also for any domain specific forwarders, where multiple forwarders
>> are configured. Current behavior is to send queries to all
>> domain-specific forwarders used for the domain. Even if three forwarders
>> are configured and all are perfectly working, requests would be
>> forwarded to all of them for every single query. It is bombarding all of
>> them, but just the first reply would be forwarded back to client and be
>> used. Is there a good reason for such behaviour? Are multiple servers
>> for a domain considered exceptional?
>> --rev-server for example allows only single target IP specified, even if
>> syntax would allow more easily. In DNS world a zone usually requires at
>> least two servers handling it.
>> Current code walks multiple times daemon->servers list. First it finds
>> longest domain match in search_servers() function.
>> All servers are checked, when FORWARD_TEST queries were sent or
>> FORWARD_TIME elapsed since last all servers check, whichever is sooner.
>> Also on error responses. Then it walks the same list again, starting on
>> daemon->last_server, sending forwarded queries. Unless
>> forward->forwardall is set, only last_server is used. For domain
>> specific forwarders, forwardall is always set.
>> It seems to me each domain should have at least a structure:
>> struct server_domain {
>>   char *domain;
>>   struct server *last_server;
>>   time_t forwardtime;
>>   int forwardcount;
>>   struct server_domain *next;
>> };
>> Where it could store forwardcount, forwardtime and last_server for each
>> different domain. I think it would make sense to add struct server
>> *servers and int flags and iterate only servers for given domain on each
>> forwarded query. But required changes for that seem to be huge, I failed
>> to prepare working patch yet. Minimal change would use domain found by
>> search_servers and just find server_domain structure with matching domain.
>> What do you think? Do you use multiple servers for custom domains?
>> Cheers,
>> Petr
>> _______________________________________________
>> Dnsmasq-discuss mailing list
>> Dnsmasq-discuss at lists.thekelleys.org.uk
>> https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
> _______________________________________________
> Dnsmasq-discuss mailing list
> Dnsmasq-discuss at lists.thekelleys.org.uk
> https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

More information about the Dnsmasq-discuss mailing list