Good morning !
The intended invariant is that /tmp/resolv.conf is handled whenever a resolver
listens on 127.0.0.1#53.
Within just the scope of dnsmasq, finding the instance that is to be regarded
the main instance, seems a fairly simple test:
(dnsmasq listens on loopback by default irrespective of the setting of
nonwildcard)
Proposed code:
dnsmasq_ismain() # true=0, false=1.
{
local cfg="$1"
local port notinterfaces
config_get port "$cfg" port “53"
[ $port = "53" ] || return 1
config_get notinterfaces "$cfg" notinterface ""
[ -n $notinterfaces -a list_contains $notinterfaces "loopback"
] || return 1
# dnsmasq instance is designated to listen on 127.0.0.1#53.
return 0
}
The dnsmasq init script will then handle /tmp/resolv.conf dnsmasq_ismain() is
true.
When running unbound as resolver with dnsmasq as the dhcp companion (dhcp_link
is dnsmasq), dnsmasq is configured to listen on another port, e.g. 1053, and
subsequently the above test will return false and the dnsmasq init start/stop
routines will not handle /tmp/resolv.conf, which is correct. In this setup, it
is unbound that listens on 127.0.0.1#53 and it should therefor be regarded the
designated main resolver.
The current guard (resolvsym) is now determined with:
if [ ! -x /usr/sbin/dnsmasq -o ! -x /etc/init.d/dnsmasq ] ; then
resolvsym=1
else
/etc/init.d/dnsmasq enabled || resolvsym=1
fi
This assumes that dnsmasq when enabled, in whatever way, will handle
/tmp/resolv.conf.
A correct solution would be to handle /tmp/resolv.conf in the unbound init
script whenever unbound will listen on 127.0.0.1#53. Then /tmp/resolv.conf is
handled whenever either dnsmasq or unbound listens on 127.0.0.1#53.
Agree ?
The unbound init routines **should** handle /tmp/resolv in this case, but
currently do not (when dnsmasq is the dhcp_link).
Proposed code:
unbound_ismain() # true=0, false=1.
{
if [ "$UNBOUND_D_DHCP_LINK" = "none" ] \
&& /etc/init.d/dnsmasq enabled && [ -x /usr/sbin/dnsmasq -a -x
/etc/init.d/dnsmasq ] ; then
return 1
fi
# unbound is designated to listen on 127.0.0.1#53.
return 0
}
Do you agree ?
If so, then I will post two patches, one for dnsmasq and one for unbound.
Ciao,
Paul
> Op 5 jun. 2017, om 05:37 heeft Eric Luehrsen <[email protected]> het
> volgende geschreven:
>
> Hi Paul -
>
> The solution I put into Unbound scripts was due to this trickiness.
> dnsmasq and its little extra functions have become entrenched and
> necessary in base OpenWrt/LEDE. This includes the oddities in
> architecture for UCI and LuCI.
>
> Normally, it is much easier to bind to the wild card address. So one
> might assume that the primary binds to #53, and any other instance must
> use a different port. It is also possible to bind per interface. An
> instance may bind to 127.0.0.1#53, another 192.168.1.1#53, and yet
> another to 192.168.2.1#53. Depending on subnet management and access
> limiting controls, this could get complicated.
>
> Requirements first. In an ecosystem with a choice of DNS servers
> (multiple instances each and stub vs recursive), what shall be the
> direct or inferred protocol to denote the primary DNS instance? The
> scripts all but write themselves with such requirement set and agreed to.
>
> - Eric
>
>> (in short: when dnsmasq.noresolv=1 and dnsmasq.resolvfile is unset, then
>> /tmp/resolv.conf is not handled).
>>
>> After some analysis the conclusion is that the dnsmasq init script should
>> handle /tmp/resolv.conf, if and only if, when its main instance is run. The
>> main instance is designated the one that will listen on 127.0.0.1#53
>> (naturally there can be only one such instance).
>>
>> When using unbound with UCI unbound.dhcp_link set to “dnsmasq”, the unbound
>> init script does **not** handle /tmp/resolv.conf and leaves it to dnsmasq to
>> do so. In the dhcp_link=dnsmasq setup it is unbound that listens on
>> 127.0.0.1#53 and so no instance of dnsmasq can possibly be the main
>> instance. Which makes sense.
>>
>> An attempt to solve this problem just within the scope of the dnsmasq init
>> script has proven to be more convoluted than I first thought.
>>
>> A simple, sane and much more elegant solution would be:
>> a) dnsmasq indeed only handles /tmp/resolv.conf when it runs the main
>> instance and
>> b) unbound does so when it the main instance, i.e. will listen on
>> 127.0.0.1#53.
>>
>> Do you agree ?
>>
>> If so, could you share your thoughts on how best to do the unbound change ?
>> A few different approaches to the determination of $resolvsym seem possible,
>> but I’m sure that picking best/easiest/whatever approach is best chosen by
>> you.
>>
>> Regards,
>> Paul
>>
>>
>>> Op 4 jun. 2017, om 16:26 heeft Paul Oranje <[email protected]> het volgende
>>> geschreven:
>>>
>>> Good afternoon,
>>>
>>> Conclusions:
>>> 1) Always initialise $resolvfile (i.e. independently of the state of
>>> noresolv).
>>> 2) The value of $resolvfile cannot not be used the determine the dnsmasq
>>> main instance since several instances likely will an equal value.
>>> 3) The main dnsmasq instance is the instance that listens on 127.0.0.1:53
>>> (of which there can only be one or none).
>>> 4) When no local DNS resolver runs /tmp/resolv.conf should soft-link
>>> $resolvfile (and that could possible be something else than
>>> /tmp/resolv.conf.auto).
>>>
>>> ad 3)
>>> The designated main instance can be determined at runtime by:
>>> - at start of an instance X, when this instance is configured to listen on
>>> 127.0.0.1#53 and no process listens on that socket, then
>>> - at stop of an instance X, when this instance is configured to listen on
>>> 127.0.0.1#53 and a process listens on that socket, then
>>>
>>> For a listening-on test something like “nslookup localhost 127.0.0.1#53
>>> >/dev/null” would seemingly work (though not on OWRT CC), but that will
>>> incur a timeout delay (10 sec ?) when no daemon is listening.
>>> Understandably, suggestions for an alternative test that will not incur
>>> such a timeout are welcome.
>>>
>>> The above determination of the main instance assume that only one of
>>> multiple instances is configured to listen on 127.0.0.1#53, otherwise the
>>> tests may result erroneously in undefined behaviour.
>>>
>>> ad 4)
>>> A use-case for setting resolvfile to a non-default might be the use of
>>> different upstream resolvers for different subnets, though that could
>>> easily be achieved with the server options of UCI dhcp.dnsmasq[x].
>>>
>>>
>>> Regards,
>>> Paul
>>>
>>>
>>>
>>>> Op 4 jun. 2017, om 00:09 heeft Hans Dedecker <[email protected]> het
>>>> volgende geschreven:
>>>>
>>>> On Sat, Jun 3, 2017 at 3:33 PM, Paul Oranje <[email protected]> wrote:
>>>>> Thanks, please see a few quick reactions of mine inline ...
>>>>> Paul
>>>>>
>>>>>> Op 3 jun. 2017, om 14:18 heeft Hans Dedecker <[email protected]> het
>>>>>> volgende geschreven:
>>>>>>
>>>>>> On Thu, Jun 1, 2017 at 12:00 PM, Paul Oranje <[email protected]> wrote:
>>>>>>> Hello Hans,
>>>>>>>
>>>>>>> A new version of this small patch is worked on -overlooked your
>>>>>>> previous comment and have lately been busy with other stuff-, but after
>>>>>>> studying the code a little more I’ve a few questions. The intended
>>>>>>> patch changes code that was added with commit
>>>>>>> a35f9bbc43c3da06eed042f80dc09e8c1da681b4 (dnsmasq: Multiple dnsmasq
>>>>>>> instances support) that was authored by you.
>>>>>>>
>>>>>>>
>>>>>>> The routines dnsmasq_start() and dnsmasq_stop() contain a guard on
>>>>>>> writing and resetting /tmp/resolv.conf:
>>>>>>> [ "$resolvfile" = "/tmp/resolv.conf.auto” ] &&
>>>>>>>
>>>>>>> As explained in FS#785, the guard test fails when $noresolv is true and
>>>>>>> $resolvfile has not been explicitly configured to its default
>>>>>>> "/tmp/resolv.conf.auto", causing /tmp/resolv.conf to remain a soft link
>>>>>>> to /tmp/resolv.conf.auto (the WAN its DNS).
>>>>>>>
>>>>>>> The routine dnsmasq_stop() the guard is commented with
>>>>>>> #relink /tmp/resolve.conf only for main instance
>>>>>>>
>>>>>>> This suggests that only for the main (first ?) instance
>>>>>>> /tmp/resolv.conf would be handled, which makes sense, but the test to
>>>>>>> accomplish that seems wrong.
>>>>>>>
>>>>>>> Q1:
>>>>>>> What is the supposed relation between dnsmasq instance and the value of
>>>>>>> the value/setting of resolvfile ?
>>>>>> The DNS servers learned on the wan interface(s) by netifd are written
>>>>>> in /tmp/resolv.conf.auto. By default a dnsmasq instance uses
>>>>>> /tmp/resolv.conf.auto as resolver file unless configured otherwise.
>>>>> Indeed and whether dnsmasq uses the (whatever) resolvfile is governed by
>>>>> the noresolv parameter; these two parameters are orthogonal.
>>>>> The init script though skips setting resolvfile when noresolv is true.
>>>> Agree the value of noresolv should have no influence on reading he
>>>> resolvfile parameter; this behavior has been introduced in commit
>>>> 2ac21bd793946a214295b760cd652b4150d3dc07
>>> So I blamed the wrong commit.
>>>
>>>>>> Using /tmp/rsolv.conf.auto as resolver file triggers logic to rewrite
>>>>>> /tmp/resolv.conf
>>>>> Why would the question whether local DNS resolution is handled by the DNS
>>>>> available on WAN interface be determined by this specific **value** of
>>>>> $resolvfile (and irrespective of the actual existence of that file) ?
>>>>>
>>>>> Also the above question (Q1) is about the relation with the dnsmasq
>>>>> **instance**.
>>>>> Could you please share your thoughts on the relation behind first
>>>>> instance and the value of $resolvfile ?
>>>> If resolvfile is set to /tmp/resolv.conf.auto assumption is made this
>>>> is the main dnsmasq instance due to a lack of a better criterium. DHCP
>>>> configs in use before the introduction of multiple dnsmasq instances
>>>> used /tmp/resolv.conf.auto as netifd by default populates the file
>>>> /tmp/resolv.conf.auto. That's the only link I see between the main
>>>> dnsmasq instance and the value of resolvfile
>>>>>
>>>>>>> A fix I considered is to omit this guard altogether (so different from
>>>>>>> the patch previously submitted), so that the local DNS service will
>>>>>>> allways be used for local (router) DNS resolution when dnsmasq is
>>>>>>> started; at stop of dnsmasq the local resolution would return to use
>>>>>>> $resolvfile. Obviously doing so in dnsmasq_start() and dnsmasq_stop()
>>>>>>> routines that start or stop an instance would be the wrong place to do
>>>>>>> so, since that code will be called for each instance. These routines ar
>>>>>>> spawned from the start_service() and stop_service() routines that do
>>>>>>> iterate on the instances.
>>>>>>>
>>>>>>> Q2:
>>>>>>> Would placement of the /tmp/resolv.conf handling not be better placed
>>>>>>> in the start_ and stop_service() routines or, be guarded by a better
>>>>>>> test in the dnsmasq_start() and _stop() routines ? In other words: what
>>>>>>> would be a correct test ?
>>>>>> we could move rewriting of /tmp/resolv.conf to the start routine; but
>>>>>> this will not be trivial as for every dnsmasq instance DNS_SERVERS and
>>>>>> DOMAIN state will need to be kept
>>>>> The objective is to rewrite /tmp/resolv.conf to use local resolution
>>>>> whenever a local resolver runs (i.e. dnsmasq, unbound, ... listening on
>>>>> localhost:53). As multiple instances may be started, triggering on the
>>>>> first/main one seems to make sense (for lack of a better criterium).
>>>>> So the question is: what do you think is a (practical) guard for that
>>>>> (and in what routines would those be placed best) ?
>>>> The dnsmasq instance which listens on 127.0.0.1 (and thus does not
>>>> exclude the loopback interface in the notinterface parameter) for dns
>>>> requests can be used as trigger to rewrite /tmp/resolv.conf.auto which
>>>> means the logic needs to be kept in dnsmasq_start
>>>>>>> In the stop routine the file /tmp/resolv.conf is (re)set to a soft link
>>>>>>> to $resolvfile, which currently because of the test always is
>>>>>>> "/tmp/resolv.conf.auto”, irrespective whether that file exists or not.
>>>>>>>
>>>>>>> Q3:
>>>>>>> What would be the desired state of /tmp/resolv.conf after dnsmasq has
>>>>>>> been stopped ?
>>>>>> In case dnsmasq is stopped /tmp/resolv.conf needs to use only the wan
>>>>>> DNS servers; which are written by netifd in /tmp/resolv.conf.auto; and
>>>>>> not anymore 127.0.0.1.
>>>>> Okay, so that should never be any self user defined resolvfile ?
>>>> AFAIK this has never been the case before
>>>>
>>>> Hans
>>>>>> Hans
>>>>>>>
>>>>>>> Bye,
>>>>>>> Paul
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>> Op 20 mei 2017, om 20:58 heeft Hans Dedecker <[email protected]> het
>>>>>>>> volgende geschreven:
>>>>>>>>
>>>>>>>> On Sat, May 20, 2017 at 12:41 AM, Paul Oranje <[email protected]> wrote:
>>>>>>>>> When UCI dhcp.dnsmasq.noresolv is true, dnsmasq ignores the (wan)
>>>>>>>>> resolv.conf
>>>>>>>>> for upstream name resolution and the dnsmasq init script ialso skips
>>>>>>>>> writing
>>>>>>>>> /tmp/resolv.conf (/etc/resolv.conf soft links that file).
>>>>>>>>>
>>>>>>>>> Not using the local running DNS service when noresolv is true does
>>>>>>>>> not make
>>>>>>>>> sence; the semantics of that config value do not imply this. With
>>>>>>>>> this patch
>>>>>>>>> the init script also writes /tmp/resolv.conf when noresolv is true.
>>>>>>>>>
>>>>>>>>> fixes FS#785
>>>>>>>>>
>>>>>>>>> Signed-off-by: Paul Oranje <[email protected]>
>>>>>>>>> ---
>>>>>>>>> This patch replaces an earlier patch with subject
>>>>>>>>> dnsmasq: also write /tmp/resolv.conf when UCI dhcp.dnsmasq.noresolv
>>>>>>>>> is '1'
>>>>>>>>> which is obsoleted because that subject was required to be shorter.
>>>>>>>>> ---
>>>>>>>>> package/network/services/dnsmasq/files/dnsmasq.init | 4 ++--
>>>>>>>>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>>>>>>>>
>>>>>>>>> diff --git a/package/network/services/dnsmasq/files/dnsmasq.init
>>>>>>>>> b/package/network/services/dnsmasq/files/dnsmasq.init
>>>>>>>>> index 30fec7a4ee..197aae9de1 100644
>>>>>>>>> --- a/package/network/services/dnsmasq/files/dnsmasq.init
>>>>>>>>> +++ b/package/network/services/dnsmasq/files/dnsmasq.init
>>>>>>>>> @@ -947,7 +947,7 @@ dnsmasq_start()
>>>>>>>>> echo >> $CONFIGFILE_TMP
>>>>>>>>> mv -f $CONFIGFILE_TMP $CONFIGFILE
>>>>>>>>>
>>>>>>>>> - [ "$resolvfile" = "/tmp/resolv.conf.auto" ] && {
>>>>>>>>> + [ "$noresolv" = "1" -o "$resolvfile" =
>>>>>>>>> "/tmp/resolv.conf.auto" ] && {
>>>>>>>>> rm -f /tmp/resolv.conf
>>>>>>>>> [ $ADD_LOCAL_DOMAIN -eq 1 ] && [ -n "$DOMAIN" ] && {
>>>>>>>>> echo "search $DOMAIN" >> /tmp/resolv.conf
>>>>>>>>> @@ -982,7 +982,7 @@ dnsmasq_stop()
>>>>>>>>> config_get resolvfile "$cfg" "resolvfile"
>>>>>>>>>
>>>>>>>>> #relink /tmp/resolve.conf only for main instance
>>>>>>>>> - [ "$resolvfile" = "/tmp/resolv.conf.auto" ] && {
>>>>>>>>> + [ "$noresolv" = "1" -o "$resolvfile" =
>>>>>>>>> "/tmp/resolv.conf.auto" ] && {
>>>>>>>> As mentioned in the previous code review noresolv value must be read
>>>>>>>> from config (similar to resolvfile) otherwise this will not work
>>>>>>>>> [ -f /tmp/resolv.conf ] && {
>>>>>>>>> rm -f /tmp/resolv.conf
>>>>>>>>> ln -s "$resolvfile" /tmp/resolv.conf
>>>>>>>> As mentioned in the previous code review resolvfile can now be empty
>>>>>>>> which will make ln -s produce an error
>>>>>>>>
>>>>>>>> Hans
>>>>>>>>> --
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Lede-dev mailing list
>>>>>>>>> [email protected]
>>>>>>>>> http://lists.infradead.org/mailman/listinfo/lede-dev
>>>>>>>> _______________________________________________
>>>>>>>> Lede-dev mailing list
>>>>>>>> [email protected]
>>>>>>>> http://lists.infradead.org/mailman/listinfo/lede-dev
>>>>>> _______________________________________________
>>>>>> Lede-dev mailing list
>>>>>> [email protected]
>>>>>> http://lists.infradead.org/mailman/listinfo/lede-dev
>>>> _______________________________________________
>>>> Lede-dev mailing list
>>>> [email protected]
>>>> http://lists.infradead.org/mailman/listinfo/lede-dev
>>>
>>> _______________________________________________
>>> Lede-dev mailing list
>>> [email protected]
>>> http://lists.infradead.org/mailman/listinfo/lede-dev
>
> _______________________________________________
> Lede-dev mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/lede-dev
_______________________________________________
Lede-dev mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/lede-dev