Merge pull request 'Update dnsmasq.adoc to use sudo commands where relevant and to avoid using vim in commands' (!193) from goroboro/user-documentation:dnsmasq-root into main

Reviewed-on: server/user-documentation#193
Reviewed-by: Peter Boy <pboy@noreply.forge.fedoraproject.org>
This commit is contained in:
Peter Boy 2026-07-15 11:31:51 +00:00
commit fd47c0373c

View file

@ -1,8 +1,8 @@
= Setting up dnsmasq - a lightweight DHCP and DNS server
Peter Boy; Emmmanuel Seyman
Peter Boy; Emmmanuel Seyman, Rowan Puttergill
:page-authors: {author}, {author_2}
:revnumber: F35-F44
:revdate: 2026-05-11
:revdate: 2026-07-01
// :revremark: a new beginning
:page-aliases: sysadmin-dnsmasq.adoc
@ -37,7 +37,7 @@ You should get something like
+
[source,console]
----
# firewall-cmd --get-active-zones
$ firewall-cmd --get-active-zones
FedoraServer (default)
interfaces: <IF01> ...
<MY_ZONE>
@ -48,8 +48,8 @@ Fix the zone assignments if necessary
+
[source,console]
----
# firewall-cmd --permanent --zone=<zone_name> --change-interface=<interface_name>
# firewall-cmd --reload
$ sudo firewall-cmd --permanent --zone=<zone_name> --change-interface=<interface_name>
$ sudo firewall-cmd --reload
----
* **Check auto forwarding**
@ -58,8 +58,8 @@ The system should automatically forward between the interfaces. Check the forwar
+
[source,console]
----
# cat /proc/sys/net/ipv4/ip_forward
# cat /proc/sys/net/ipv6/conf/default/forwarding
$ cat /proc/sys/net/ipv4/ip_forward
$ cat /proc/sys/net/ipv6/conf/default/forwarding
----
+
In both cases a value of 1 indicates an active forwarding.
@ -68,15 +68,16 @@ Otherwise, enable it immediately and configure it permanently.
+
[source,console]
----
# echo 1 > /proc/sys/net/ipv4/ip_forward
# echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
$ echo 1 | sudo tee /proc/sys/net/ipv6/conf/all/forwarding
# vim /etc/sysctl.d/50-enable-forwarding.conf
$ sudo tee /etc/sysctl.d/50-enable-forwarding.conf << 'EOF'
# local customizations
#
# enable forwarding for dual stack
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
EOF
----
@ -86,7 +87,7 @@ The NetworkManager dnsmasq plugin included by default provides a basic configur
In case dnsmasq is not already installed
[source,console]
----
# dnf install dnsmasq
$ sudo dnf install dnsmasq
----
[IMPORTANT]
@ -111,151 +112,175 @@ The example here uses 2 interfaces, an external public interface enp1s0 (public.
1. **Activate the dnsmasq NetworkManager plugin**
+
[source,console]
Create and edit the file at `/etc/NetworkManager/conf.d/00-use-dnsmasq.conf` using your preferred editor running under sudo with root privileges. The content should be as follows:
+
[source, ini]
----
# vim /etc/NetworkManager/conf.d/00-use-dnsmasq.conf
# /etc/NetworkManager/conf.d/00-use-dnsmasq.conf
# This enables the dnsmasq plugin.
[main]
dns=dnsmasq
# /etc/NetworkManager/conf.d/00-use-dnsmasq.conf
# This enables the dnsmasq plugin.
[main]
dns=dnsmasq
----
2. **Configuration of the name resolution (DNS) for the internal private network (internal.lan)**
+
[source,console]
Create and edit the file at `/etc/NetworkManager/dnsmasq.d/01-DNS-<INTERNAL>.conf` using your preferred editor running under sudo with root privileges. The content should be as follows:
+
[source,ini]
----
# vim /etc/NetworkManager/dnsmasq.d/01-DNS-<INTERNAL>.conf
# /etc/NetworkManager/dnsmasq.d/01-DNS-<INTERNAL>.conf
# This file sets up DNS for the private local net domain '<INTERNAL>.lan'
local=/<INTERNAL>.lan/
# file where to find the list of IP - hostname mapping
addn-hosts=/etc/dnsmasq-<INTERNAL>.hosts
domain-needed
bogus-priv
# Automatically add <domain> to simple names in a hosts-file.
expand-hosts
# interfaces to listen on
interface=lo
interface=<ENPxyz>
# in case of a bridge don't use the attached server virtual ethernet interface here!
# Upstream public net DNS server (max.three)
no-poll
server=<uuu.vv.xx.yy>
server=<www.vv.xx.zz>
server=<2001:www:xxx:yyy::zz>
# /etc/NetworkManager/dnsmasq.d/01-DNS-<INTERNAL>.conf
# This file sets up DNS for the private local net domain '<INTERNAL>.lan'
local=/<INTERNAL>.lan/
# file where to find the list of IP - hostname mapping
addn-hosts=/etc/dnsmasq-<INTERNAL>.hosts
domain-needed
bogus-priv
# Automatically add <domain> to simple names in a hosts-file.
expand-hosts
# interfaces to listen on
interface=lo
interface=<ENPxyz>
# in case of a bridge don't use the attached server virtual ethernet interface here!
# Upstream public net DNS server (max.three)
no-poll
server=<uuu.vv.xx.yy>
server=<www.vv.xx.zz>
server=<2001:www:xxx:yyy::zz>
----
+
Substitute values for <INTERNAL>, <ENPxyz> with a name for your internal private network, and the network interface connected to your internal private network.
+
Substitute the values for <uuu.vv.xx.yy>, <www.vv.xx.zz>, and <2001:www:xxx:yyy::zz> with the IP addresses of any upstream DNS servers.
+
Provide an empty host file
+
[source,console]
----
# touch /etc/dnsmasq-<INTERNAL>.hosts
$ sudo touch /etc/dnsmasq-<INTERNAL>.hosts
----
3. **Configuration of the DHCP service for the internal private network (<INTERNAL>.lan)**
+
[source,console]
Create and edit the file at `/etc/NetworkManager/dnsmasq.d/02-DHCP-<INTERNAL>.conf` using your preferred editor running under sudo with root privileges. The content should be as follows:
+
[source,ini]
----
# vim /etc/NetworkManager/dnsmasq.d/02-DHCP-<INTERNAL>.conf
# etc/NetworkManager/dnsmasq.d/02-DHCP-<INTERNAL>.conf
# This file sets up DHCP for the private local net domain '<INTERNAL>.lan'
# The domain the DHCP part of dnsmasq is responsible for:
domain=<INTERNAL>.lan,<uuu.vv.xx.y/24>,local
# interfaces to listen on (redundant, same as for DNS)
interface=<ENPxyz>
# general DHCP stuff (options, see RFC 2132)
# 1: subnet masq
# 3: default router
# 6: DNS server
# 12: hostname
# 15: DNS domain (unneeded with option 'domain')
# 28: broadcast address
dhcp-authoritative
dhcp-option=1,<255.255.255.24>
dhcp-option=3,<www.xxx.yy.zz>
dhcp-option=6,<www.xx.yy.z>
# Assign fixed IP addresses based on MAC address
# dhcp-host=00:1a:64:ce:89:4a,NAME01,www.xx.yy.zz,infinite
# dhcp-host=52:54:00:42:6a:43,NAME02,www.xx.yy.zz,infinite
# Assign dynamically IP addresses to interface to listen on
# Range for distributed addresses, tagged <int> for further references
dhcp-range=tag:<ENPxyz>,<vvv.ww.xx.y,vvv.ww.xx.z>,24h
# etc/NetworkManager/dnsmasq.d/02-DHCP-<INTERNAL>.conf
# This file sets up DHCP for the private local net domain '<INTERNAL>.lan'
# The domain the DHCP part of dnsmasq is responsible for:
domain=<INTERNAL>.lan,<uuu.vv.xx.y/24>,local
# interfaces to listen on (redundant, same as for DNS)
interface=<ENPxyz>
# general DHCP stuff (options, see RFC 2132)
# 1: subnet masq
# 3: default router
# 6: DNS server
# 12: hostname
# 15: DNS domain (unneeded with option 'domain')
# 28: broadcast address
dhcp-authoritative
dhcp-option=1,<255.255.255.0>
dhcp-option=3,<www.xxx.yy.zz>
dhcp-option=6,<www.xx.yy.z>
# Assign fixed IP addresses based on MAC address
# dhcp-host=00:1a:64:ce:89:4a,NAME01,www.xx.yy.zz,infinite
# dhcp-host=52:54:00:42:6a:43,NAME02,www.xx.yy.zz,infinite
# Assign dynamically IP addresses to interface to listen on
# Range for distributed addresses, tagged <int> for further references
dhcp-range=tag:<ENPxyz>,<vvv.ww.xx.y,vvv.ww.xx.z>,24h
----
+
Substitute values for <INTERNAL>, <ENPxyz> with a name for your internal private network, and the network interface connected to your internal private network.
+
Substitute the value of <uuu.vv.xx.y/24> with the network address and mask for your internal private network.
+
The example shows the binding of the network interface and then sets the different DHCP responses for various client request options.
+
The subnet mask (dhcp-option=1) is set to <255.255.255.0>, the default router or gateway (dhcp-option=3) is set to <www.xxx.yy.zz>, and the DNS server (dhcp-option=6) is set to <www.xx.yy.z>. Substitute values appropriate to your network.
+
In this example, no permanent or fixed IP addresses are assigned, but examples are provided as commented lines, so that you can see how to add an entry to assign a particular IP address to a host based on it's MAC address.
+
The example enables a DHCP range within the network and assigns hosts IP addresses from <vvv.ww.xx.y> to <vvv.ww.xx.z> with leases lasting for 24 hours. Substitute values as appropriate for your network.
4. **Configuration of the DHCP service for the public network (<PUBLIC.TLD>)**
+
[source,console]
Create and edit the file at `/etc/NetworkManager/dnsmasq.d/03-DHCP-<PUBLIC.TLD>.conf` using your preferred editor running under sudo with root privileges. The content should be as follows:
+
[source,ini]
----
# vim /etc/NetworkManager/dnsmasq.d/03-DHCP-<PUBLIC>.conf
# etc/NetworkManager/dnsmasq.d/03-DHCP-<PUBLIC>.conf
# This file sets up DNCP for the public '<PUBLIC.TLD>' domain interface
# etc/NetworkManager/dnsmasq.d/03-DHCP-<PUBLIC.TLD>.conf
# This file sets up DHCP for the public '<PUBLIC.TLD>' domain interface
# The domain the DHCP part of dnsmasq is responsible for:
domain=<PUBLIC.TLD>,<uuu.vv.ww.xx/24>
# the public interfaces to listen on
interface=<ENPuvw>
# general DHCP stuff (options, see RFC 2132)
# 1: subnet masq
# 3: default router
# 6: DNS server
# 12: hostname
# 15: DNS domain (unneeded with option 'domain')
# 28: broadcast address
# The domain the DHCP part of dnsmasq is responsible for:
domain=<PUBLIC.TLD>,<uuu.vv.ww.xx/24>
##dhcp-authoritative
## we just send the bare minimum, e.g. no DNS server
##dhcp-option=1,<255.255.255.0>
dhcp-option=tag:<ENPuvw>,option=router,<uuu.vv.ww.zz>
# Assign fixed IP addresses based on MAC address
# dhcp-host=00:1a:64:ce:89:4a,thootes,10.10.10.50,infinite
# dhcp-host=52:54:00:42:6a:43,apollon,10.10.10.51,infinite
# Assign dynamically IP addresses to interface to listen on
# Range for distributed addresses, tagged <int> for further references dhcp-range=tag:<ENPuvw>,<uuu.vvv.w.x,uuu.vvv.w.y6,1h
# the public interfaces to listen on
interface=<ENPuvw>
# general DHCP stuff (options, see RFC 2132)
# 1: subnet masq
# 3: default router
# 6: DNS server
# 12: hostname
# 15: DNS domain (unneeded with option 'domain')
# 28: broadcast address
##dhcp-authoritative
## we just send the bare minimum, e.g. no DNS server
##dhcp-option=1,<255.255.255.0>
dhcp-option=tag:<ENPuvw>,option=router,<uuu.vv.ww.zz>
# Assign fixed IP addresses based on MAC address
# dhcp-host=00:1a:64:ce:89:4a,thootes,10.10.10.50,infinite
# dhcp-host=52:54:00:42:6a:43,apollon,10.10.10.51,infinite
# Assign dynamically IP addresses to interface to listen on
# Range for distributed addresses, tagged <int> for further references dhcp-range=tag:<ENPuvw>,<uuu.vvv.w.x,uuu.vvv.w.y6,1h
----
+
Substitute values for <PUBLIC.TLD>, <ENPuvw> with the domain name for your public facing network, and the network interface connected to your public facing network.
+
Substitute the value of <uuu.vv.ww.xx/24> with the network address and mask for your public facing network.
+
Substitute the value <uuu.vv.ww.zz> with the IP address of the network router or default gateway.
+
There is no DNS configuration for the external interface following, assuming that a official public DNS server is used to resolve all public facing interfaces of the domain public.tld.
5. **Test the dnsmasq configuration**
+
[source,console]
----
# dnsmasq --test
$ dnsmasq --test
----
6. **Adjusting the firewall**
+
Allow ports for DHCP and DNS (53) service on the public interface.
Allow ports for DHCP (UDP port 67) and DNS (TCP port 53) service on the public interface. If the system is running firewalld, you can configure these services as follows:
+
[source,console]
----
# firewall-cmd --get-services
# firewall-cmd --zone=<YOUR_ZONE> --permanent --add-service=dhcp
# firewall-cmd --zone=<YOUR_ZONE> --permanent --add-service=dns
# firewall-cmd --reload
# firewall-cmd --list-all --zone=<YOUR_ZONE>
$ firewall-cmd --get-services
$ sudo firewall-cmd --zone=<YOUR_ZONE> --permanent --add-service=dhcp
$ sudo firewall-cmd --zone=<YOUR_ZONE> --permanent --add-service=dns
$ sudo firewall-cmd --reload
$ firewall-cmd --list-all --zone=<YOUR_ZONE>
----
7. **Restart NetworkManager to start dnsmasq**
+
[source,console]
----
# systemctl restart NetworkManager
# ps -ef | grep dnsmasq
$ sudo systemctl restart NetworkManager
$ ps -ef | grep dnsmasq
dnsmasq 2114 2072 0 08:33 ? 00:00:00 /usr/sbin/dnsmasq --no-resolv ...
----
+
@ -266,8 +291,8 @@ command above.
+
[source,console]
----
# systemctl restart systemd-resolved
# resolvectl status
$ sudo systemctl restart systemd-resolved
$ resolvectl status
----
+
The systemd-resolved should recognize the dnsmasq nameserver attached to interfaces as configured.
@ -278,19 +303,19 @@ a. Test DHCP in the public using a machine without IP address
+
[source,console]
----
# ip a # no IPv4 address associated with interface
# dhclient -4 -1 -v eth0
# ip a # expect new IPv4 address associated with interface
# dhclient -4 -1 -r -v eth0 # expected: no IPv4 again
# ip a # expect no IPv4 address associated with interface again
$ ip a # no IPv4 address associated with interface
$ sudo dhclient -4 -1 -v eth0
$ ip a # expect new IPv4 address associated with interface
$ sudo dhclient -4 -1 -r -v eth0 # expected: no IPv4 again
$ ip a # expect no IPv4 address associated with interface again
----
b. Try on an other server
b. Validate that a DNS lookup for the system works correctly on another server, by running any of the following:
+
[source,console]
----
# dig app1 @10.10.10.1
# nslookup app1 10.10.10.1
# dhclient -v -d -s 10.10.10.1 enp6s0
$ dig app1 @10.10.10.1
$ nslookup app1 10.10.10.1
$ dhclient -v -d -s 10.10.10.1 enp6s0
----
@ -302,15 +327,15 @@ If machines in the private network need access to the public network, add masque
+
[source,console]
----
# firewall-cmd --zone=FedoraServer --add-masquerade --permanent
$ sudo firewall-cmd --zone=FedoraServer --add-masquerade --permanent
success
# firewall-cmd --zone=trusted --add-masquerade --permanent
$ sudo firewall-cmd --zone=trusted --add-masquerade --permanent
success
# firewall-cmd --reload
# firewall-cmd --zone=FedoraServer --query-masquerade
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --zone=FedoraServer --query-masquerade
yes
# firewall-cmd --zone=trusted --query-masquerade
$ sudo firewall-cmd --zone=trusted --query-masquerade
yes
----
@ -321,16 +346,16 @@ a. A commonly used way to accomplish this is to set 'rules' in the firewall conf
+
[source,console]
----
# firewall-cmd --get-active-zones
$ firewall-cmd --get-active-zones
FedoraServer
interfaces: enp1s0
trusted
interfaces: vbr2s0 enp2s0
# firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -o enp1s0 -j MASQUERADE
$ sudo firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -o enp1s0 -j MASQUERADE
success
# firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i vbr2s0 -o enp2s0 -j ACCEPT
$ sudo firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i vbr2s0 -o enp2s0 -j ACCEPT
success
# firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i enp1s0 -o vbr2s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
$ sudo firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i enp1s0 -o vbr2s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
success
----
@ -338,20 +363,20 @@ b. Fedora's firewall daemon, however, offers with release 35 and beyond a more e
+
[source,console]
----
# firewall-cmd --get-active-zones
$ firewall-cmd --get-active-zones
FedoraServer
interfaces: enp1s0
trusted
interfaces: vbr2s0 enp2s0
# firewall-cmd --permanent --new-policy trustedToExt
$ sudo firewall-cmd --permanent --new-policy trustedToExt
success
# firewall-cmd --permanent --policy trustedToExt --add-ingress-zone trusted
$ sudo firewall-cmd --permanent --policy trustedToExt --add-ingress-zone trusted
success
# firewall-cmd --permanent --policy trustedToExt --add-egress-zone FedoraServer
$ sudo firewall-cmd --permanent --policy trustedToExt --add-egress-zone FedoraServer
success
# firewall-cmd --permanent --policy trustedToExt --set-target ACCEPT
$ sudo firewall-cmd --permanent --policy trustedToExt --set-target ACCEPT
success
# firewall-cmd --reload
$ sudo firewall-cmd --reload
success
----
+
@ -361,45 +386,40 @@ This method is much clearer, improves maintainability and reduces sources of pot
== Integrate libvirt's virtual interface
In case libvirt and virtualization including a virtual network for the virtual machines, libvirt installs and configures its own dnsmasq instance. In most cases it is just convenient, instead of replacing the libvirt _default_ network to integrate it in NetworkManagers dnsmasq plugin. Thus, two instances of dnsmasq operate along each other.
To make it work, just add another configuration file. The example uses libvirt.lan as the libvirt virtual network domain name. Adjust as appropriate.
To make it work, just add another configuration file, for example `/etc/NetworkManager/dnsmasq.d/30-DNS-libvirt.conf`.
The example uses libvirt.lan as the libvirt virtual network domain name. Adjust as appropriate.
We just add the name resolution (DNS) for the libvirt virtual network (libvirt.lan), leaving the DHCP functionality untouched.
[source,console]
[source,ini]
----
# vim /etc/NetworkManager/dnsmasq.d/30-DNS-libvirt.conf
# /etc/NetworkManager/dnsmasq.d/30-DNS-libvirt.conf
# /etc/NetworkManager/dnsmasq.d/30-DNS-libvirt.conf
# This file directs dnsmasq to forward any request to resolve
# names under the .libvirt.lan domain to 192.168.122.1, the
# local libvirt DNS server default address.
server=/libvirt.lan/192.168.122.1
# This file directs dnsmasq to forward any request to resolve
# names under the .libvirt.lan domain to 192.168.122.1, the
# local libvirt DNS server default address.
server=/libvirt.lan/192.168.122.1
----
== Managing static DNS Entries
1. Edit the dnsmasq host file
1. **Edit the dnsmasq host file that you created at `/etc/dnsmasq-<INTERNAL>.hosts` to define internal DNS mappings for hosts on the local network.**
+
The format is the same as /etc/hosts .
+
[source,console]
----
# vim /etc/dnsmasq.hosts
----
The format is the same as /etc/hosts. See the hosts(5) man page for more information.
2. Restart NetworkManager to read the modified file.
2. **Restart NetworkManager to read the modified file.**
+
[source,console]
----
# systemctl restart NetworkManager
$ sudo systemctl restart NetworkManager
----
3. Test the modification
+
[source,console]
----
# nslookup {NAME}
# nslookup {NAME}.example.lan
$ sudo nslookup {NAME}
$ sudo nslookup {NAME}.example.lan
----