[Dnsmasq-discuss] Multiple instances of dnsmasq on Debian with systemd

M. Buecher maddes+dnsmasq at maddes.net
Sat Dec 1 12:20:58 GMT 2018


Hello Simon,

on my first tries to start multiple dnsmasq instances on Debian 9 
"Stretch" with systemd I faced several issues and created Debian bug 
report #914305 [1].
Yesterday I finally managed to spend several hours on the issue and 
found a clean solution for it.
While preparing the text for the bug report I recognized that you're the 
maintainer of the Debian packages, so I decided to write to the dnsmasq 
mailing list first.

[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914305



systemd unit files [2] allow to be used for multiple instances when the 
service unit file name ends with the at symbol (@).
Then the service can be enabled with an instance name following the at 
symbol, e.g. `systemctl enable dnsmasq at main.service`.
The instance name is available in an escaped format in variable %i 
(lower case) when the unit file is processed.
The attached unit file dnsmasq at .service passes the escaped instance name 
to the init.d script (minor changes to the code plus `mv -v 
/lib/systemd/system/dnsmasq.service 
/lib/systemd/system/dnsmasq at .service`).

The 2nd attached file is the updated init.d script for dnsmasq.
It now recognizes the instance name via the second script paramater and 
uses it wherever needed or possible (default file, pid file, resolvconf 
protocol, log entries).

Additionally three special cases had to be handled when running multiple 
instances of dnsmasq:
a) The original systemd unit file wants to check the configuration 
before starting the service but does not honor the settings from the 
default file (conf file and dir).
    Therefore the option checkconfig was added to the init.d script.
    I don't know if there's a common SysInit V standard name for such a 
function [3].
b) `mkdir /run/dnsmasq` in the init.d script can fail as unit files are 
run in parallel, so the directory has to be checked again if mkdir 
failed.
c) Only one dnsmasq instance should be the dns resolver for the local 
system and should bind to localhost.
    Therefore revived DNSMASQ_EXCEPT="lo" in the default file (3rd 
attached file).

Additional changes to the files are typo corrections.

[2] https://www.freedesktop.org/software/systemd/man/systemd.unit.html
[3] 
https://www.debian.org/doc/debian-policy/ch-opersys.html#writing-the-scripts



For testing I installed openresolv and dnsmasq on latest Debian 9 
"Stretch" and created some virtual network interfaces via systemd [4].
The main dnsmasq instance shall run on the real NIC while special 
instances shall run on the extra virtual NICs (dnsextra*).

Stopped and disabled the original service from the Debian dnsmasq 
package:
`systemctl stop dnsmasq.service`
`systemctl disable dnsmasq.service`
`systemctl status dnsmasq.service`

Prepared dnsmasq systemd unit file for instances by renaming and 
updating it:
`mv -v /lib/systemd/system/dnsmasq.service 
/lib/systemd/system/dnsmasq at .service`

As instance enabled systemd unit files have to be used with an instance 
name I decided to name the default dnsmasq instance simply "main".
Not to break SysInit V compatibility a symbol link was used for the 
"renaming" of the default file.
`ln -s -T dnsmasq /etc/default/dnsmasq.main`
(P.S. Other idea would be to default INSTANCE in init.d to 'main' when 
instance name not given.)

Updated also init.d script and normal default file.

Then prepared two dnsmasq instances:
1. Default file for main instance (/etc/default/dnsmasq.main)
Changed to DNSMASQ_OPTS="--bind-dynamic --except-interface=dnsextra*"
This way it will avoid binding to the extra virtual NICs while still 
recognizing new addresses and other new NICs, and it will also be the 
DNS resolver for the local system.

2. New default file for first extra instance 
(/etc/default/dnsmasq.extra01)
Copied from default file of main instance via `cp /etc/default/dnsmasq 
/etc/default/dnsmasq.extra01`
Changed the following settings for this extra instance:
* DNSMASQ_OPTS="--bind-dynamic --interface=dnsextra01 
--address=/heise.de/192.168.0.250"
   Binds to one explicit interface while still recognizing new addresses.
   One modified address resolution for testing with dig.
* IGNORE_RESOLVCONF=yes
   Always using /etc/resolv.conf therefore either using the dnsmasq main 
instance (if it is started) as upstream dns server or the upstream 
server from resolvconf (e.g. via DHCP).
* DNSMASQ_EXCEPT="lo"
   Avoid binding to localhost and also not being used as the DNS resolver 
for the local system.

With this setup I could start/stop any dnsmasq instance while keeping a 
working DNS setup.
Additionally I could assign an explicit dnsmasq instance to any dhcp 
client.

[4] https://gist.github.com/maddes-b/e487d1f95f73f5d40805315f0232d5d9



I hope that I explained everything understandably, completely and in 
correct English.
Any feedback is welcome and it would be great to see this in Debian 10 
:)

Kind regards
Maddes

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: dnsmasq at .service
URL: <http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/attachments/20181201/8932b344/attachment.ksh>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dnsmasq
Type: text/x-shellscript
Size: 9372 bytes
Desc: not available
URL: <http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/attachments/20181201/8932b344/attachment.bin>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: dnsmasq
URL: <http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/attachments/20181201/8932b344/attachment-0001.ksh>


More information about the Dnsmasq-discuss mailing list