dnsmasq on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and configuration of dnsmasq on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. dnsmasq is a small, widely deployed network infrastructure daemon that combines a caching DNS forwarder, a DHCP server and a TFTP boot server in a single lightweight package. It is a popular choice for local networks, edge sites, labs and container hosts that need name resolution and address assignment without running heavyweight services.
The image installs dnsmasq 2.90 from the Ubuntu 24.04 archive and configures it as a responsible, secure by default caching DNS forwarder. Unattended security upgrades remain enabled on the running VM so the package keeps receiving patches.
Security by design, not an open resolver. An open recursive or forwarding resolver (one that will resolve arbitrary names for anyone on the internet) is a well known DNS amplification and reflection DDoS vector. This image ships with dnsmasq's local-service mode, so the server answers DNS only for hosts whose source address is on a local subnet of this VM. A query arriving from the public internet is silently dropped, never answered and never reflected, so the server cannot be abused as an amplifier. The forwarder also sets domain-needed and bogus-priv so non qualified names and private reverse lookups are never sent upstream, and no-resolv with an explicit upstream list (1.1.1.1, 9.9.9.9).
Security by design, DHCP and TFTP are off by default. dnsmasq can also serve DHCP and TFTP, but running a DHCP server on a network you do not own is a rogue DHCP hazard, and an open TFTP root is a data exfiltration vector. This image therefore ships with neither enabled: no dhcp-range and no enable-tftp. You turn them on deliberately for your own network (see Step 8 and Step 9).
Security by design, no bootstrap credential. dnsmasq has no login or admin password of any kind; it is configured entirely through files under /etc/dnsmasq.d/. There is nothing to leak, so no shared secret ships in the image.
What is included:
-
dnsmasq 2.90 from the Ubuntu 24.04 archive, run under systemd as the unprivileged
dnsmasquser (dnsmasq.service) -
A secure caching DNS forwarder configuration:
local-service(not an open resolver),no-resolvwith explicit upstreams,domain-needed,bogus-priv, and a response cache -
A shipped local example record (
ns.dnsmasq.internalresolves to10.0.0.53) so a DNS round trip works out of the box even before any upstream is reachable -
DHCP and TFTP present in the daemon but disabled by default, with documented opt in for your own network
-
The systemd-resolved stub listener disabled so dnsmasq owns port 53, while the host still resolves names through its own upstreams
-
Ubuntu 24.04 LTS base with latest security patches applied at build time, and unattended security upgrades kept enabled
-
Azure Linux Agent for seamless cloud integration and SSH key injection
-
24/7 cloudimg support with a guaranteed 24 hour response SLA
Prerequisites
-
Active Azure subscription, SSH public key, VNet and subnet in the target region
-
Subscription to the dnsmasq listing on Azure Marketplace
-
Network Security Group rules allowing TCP 22 (admin) and both UDP and TCP 53 (DNS) from the clients that will query the server
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for a caching forwarder serving a local network. Sites with very high query volumes can use Standard_D2s_v5 or larger.
Step 1: Deploy from the Azure Portal
Search dnsmasq in Marketplace, select the cloudimg publisher, and click Create. Configure the Network Security Group to allow UDP 53 and TCP 53 (DNS) from your client networks, and TCP 22 for administration. DNS uses UDP 53 for most queries and falls back to TCP 53 for large responses, so open both.
Step 2: Deploy from the Azure CLI
RG="dns-prod"; LOCATION="eastus"; VM_NAME="dnsmasq1"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/dnsmasq/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$GALLERY_IMAGE_ID" \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values "$SSH_KEY" \
--public-ip-sku Standard
# Open the DNS and admin ports on the VM's NSG:
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 53 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1002
Step 3: First boot
On first boot the image resolves the VM public IP, asserts the secure defaults (local-service on, DHCP and TFTP off), config tests dnsmasq, starts the service, proves the local record answers and that upstream forwarding works, and writes /root/dnsmasq-credentials.txt. This completes within a minute. SSH in as azureuser and read the details:
sudo cat /root/dnsmasq-credentials.txt
Step 4: Confirm the service is running
dnsmasq.service is active and owns port 53. ss confirms dnsmasq is the listener on :53 for both UDP and TCP.
systemctl is-active dnsmasq.service
sudo ss -tulnp | grep -E ':53 ' || echo "(dnsmasq is not yet listening on :53)"

Step 5: Test DNS resolution
The image ships one local example record, ns.dnsmasq.internal, so a DNS round trip works immediately without any upstream. Forwarding of external names to the upstream resolvers also works out of the box. Query the loopback address (or the VM public IP from a client).
dig @127.0.0.1 ns.dnsmasq.internal +short
dig @127.0.0.1 example.com +short

Step 6: Review the configuration
The cloudimg configuration lives in /etc/dnsmasq.d/00-cloudimg.conf. dnsmasq --test validates the whole configuration. The version is 2.90 from the Ubuntu archive.
dnsmasq --version | head -1
sudo dnsmasq --test
cat /etc/dnsmasq.d/00-cloudimg.conf

Step 7: Verify the responsible defaults
This is the key security property. local-service is present (the server answers only local subnet clients, so it is not an open resolver), and there is no dhcp-range and no enable-tftp (DHCP and TFTP are off by default).
grep -E '^\s*(local-service|no-resolv|domain-needed|bogus-priv)' /etc/dnsmasq.d/00-cloudimg.conf
echo '--- DHCP and TFTP are off by default (the next command returns nothing): ---'
grep -E '^\s*(dhcp-range|enable-tftp)' /etc/dnsmasq.d/00-cloudimg.conf || echo 'confirmed: no dhcp-range and no enable-tftp are set'

Step 8: Point clients at the server
Configure the devices or the router on your local network to use the VM as their DNS server. On a Linux client you would set the nameserver to the VM address (replace <public-ip> with the VM public IP or its private IP inside the VNet):
echo "nameserver <public-ip>" | sudo tee /etc/resolv.conf
Because of local-service, only clients whose address is on a subnet local to the VM are answered, so keep the server and its clients on the same VNet or peered network.
Step 9: Enable DHCP for your own subnet (optional)
dnsmasq can hand out DHCP leases on a subnet you control. Only do this on a network where you are the intended DHCP server. Add a stanza like the following to /etc/dnsmasq.d/00-cloudimg.conf, adjusting the interface and range to your subnet:
interface=eth0
dhcp-range=192.0.2.50,192.0.2.150,255.255.255.0,12h
dhcp-option=option:router,192.0.2.1
Open UDP 67 in the NSG, then restart the service with sudo systemctl restart dnsmasq. Note that adding an interface= line also disables local-service, so if you enable DHCP you should add explicit except-interface or an address based restriction to keep the DNS forwarder from answering untrusted sources.
Step 10: Enable TFTP and PXE boot (optional)
dnsmasq includes a TFTP server for network boot. To serve a TFTP root, add the following to /etc/dnsmasq.d/00-cloudimg.conf:
enable-tftp
tftp-root=/srv/tftp
dhcp-boot=pxelinux.0
Create /srv/tftp, place your boot files there, open UDP 69 in the NSG, and restart with sudo systemctl restart dnsmasq. Keep the TFTP root read only and populated with only the files you intend to serve.
Step 11: Add local DNS records and custom upstreams (optional)
To add your own local names, or to change the upstream resolvers, drop a file such as /etc/dnsmasq.d/50-local.conf:
# local names answered directly by dnsmasq
host-record=app.internal,10.0.0.20
address=/dev.internal/10.0.0.30
# use your own upstream resolvers instead of the defaults
server=10.0.0.1
Validate with sudo dnsmasq --test and apply with sudo systemctl reload dnsmasq.
Step 12: Security recommendations
-
Restrict the NSG. Allow UDP and TCP 53 only from the client networks that need to query the server, and TCP 22 for administration only.
-
Keep it a local service. The shipped
local-servicedefault means the server never answers the public internet. If you add aninterface=line for DHCP, re add an explicit source restriction so the DNS forwarder does not become an open resolver. -
Enable DHCP and TFTP only where you own the network. A stray DHCP server or an open TFTP root on someone else's network is a security incident.
-
Keep the OS and dnsmasq patched. Unattended security upgrades remain enabled on the running VM.
-
Monitor the leases file. If you enable DHCP,
/var/lib/misc/dnsmasq.leasesrecords active leases.
Step 13: Support and Licensing
dnsmasq is free software written by Simon Kelley and distributed under the GNU General Public License, version 2 (GPL-2.0). This cloudimg image bundles the unmodified Ubuntu archive package. cloudimg provides the packaging, the secure caching forwarder hardening, the not an open resolver defaults, the DHCP and TFTP off by default posture, the local example record, and 24/7 support with a guaranteed 24 hour response SLA.
cloudimg is not affiliated with or endorsed by the dnsmasq project or Simon Kelley. dnsmasq is used here only to identify the software.
Deploy on Azure
Find dnsmasq on Ubuntu 24.04 LTS on the Azure Marketplace, published by cloudimg. Deploy from the Portal or the Azure CLI as shown above.
Need Help?
Email support@cloudimg.co.uk for deployment help, configuration questions, or licensing enquiries.