debops.dnsmasq default variables
Sections
APT packages
- dnsmasq__base_packages
List of APT packages to install for dnsmasq support.
dnsmasq__base_packages: [ 'dnsmasq' ]
- dnsmasq__packages
List of additional APT packages to install during dnsmasq configuration.
dnsmasq__packages: []
Global options
- dnsmasq__dhcpv4
Enable or disable DHCPv4 support.
dnsmasq__dhcpv4: True
- dnsmasq__dhcpv6
Enable or disable DHCPv6 support (router support is required).
dnsmasq__dhcpv6: True
Configuration specific to network interfaces
These variables define dnsmasq configuration related to a particular network interface. See dnsmasq__interfaces for more details.
- dnsmasq__default_interfaces
List of network interfaces for which dnsmasq configuration will be generated by default.
dnsmasq__default_interfaces:
# Name of the interface.
- name: 'br2'
state: '{{ "present"
if (hostvars[inventory_hostname]["ansible_br2"] is defined)
else "absent" }}'
- dnsmasq__interfaces
List of network interfaces for which dnsmasq configuration will be generated, defined by the user.
dnsmasq__interfaces: []
- dnsmasq__combined_interfaces
Combined list of network interfaces for which dnsmasq configuration will be generated, used in role tasks and templates.
dnsmasq__combined_interfaces: '{{ dnsmasq__default_interfaces
+ dnsmasq__interfaces }}'
DNS options
- dnsmasq__hostname
The router hostname used by dnsmasq. It will be used to configure DNS A and AAAA records pointing to the dnsmasq server.
dnsmasq__hostname: '{{ ansible_hostname }}'
- dnsmasq__base_domain
The DNS domain which will be used as a base for interface-based subdomains if none are explicitly configured.
dnsmasq__base_domain: '{{ ansible_domain }}'
- dnsmasq__base_domain_rebind_ok
When True
, dnsmasq will accept DNS records for the base DNS
domain that specify IP addresses in private address ranges. This is needed
when another DHCP/DNS server is managing the IP address leases, otherwise
they will be unresolvable.
dnsmasq__base_domain_rebind_ok: True
- dnsmasq__etc_hosts
List of absolute paths of the additional hosts(5) database files to
read by dnsmasq. This is useful if you don't want to keep the host
list in the system-wide /etc/hosts
database.
You can provide the files using the debops.resources Ansible role, non-existent files will be silently ignored by dnsmasq.
dnsmasq__etc_hosts: []
- dnsmasq__nameservers
List of upstream DNS nameservers where dnsmasq should forward its DNS queries which it can not answer by itself. If empty, system nameservers (for example received via DHCP) will be used by default.
dnsmasq__nameservers: []
- dnsmasq__public_dns
Enable or disable access to the local DNS from upstream networks using the firewall. You can publish your subdomain in the public DNS by delegating it in your zone configuration. Be wary of the DNS reflection and amplification attacks!
dnsmasq__public_dns: False
- dnsmasq__public_dns_allow
List of IP addresses or CIDR subnets which are allowed to connect to dnsmasq DNS service in public DNS mode. If the list is empty, any hosts can connect. The configuration will be set in the firewall.
dnsmasq__public_dns_allow: []
TFTP options
- dnsmasq__boot_enabled
Enable or disable support for BOOTP/PXE boot of remote hosts.
dnsmasq__boot_enabled: True
- dnsmasq__boot_ipxe_enabled
Enable or disable support for iPXE boot menu. The iPXE configuration can be done using the debops.ipxe Ansible role.
dnsmasq__boot_ipxe_enabled: True
- dnsmasq__boot_server
Specify the IP address of the "next server" which provides a TFTP service with boot files. If not specified, dnsmasq server will be contacted by the clients instead for the boot files.
dnsmasq__boot_server: ''
- dnsmasq__boot_tftp_root
Absolute path of the TFTP root directory from which boot files will be served. This path needs to exist, otherwise dnsmasq service will refuse to start.
dnsmasq__boot_tftp_root: '/srv/tftp'
- dnsmasq__boot_filename
Name of the file located in the TFTP root directory which will be sent to clients telling them which file to download and boot from.
dnsmasq__boot_filename: '{{ "menu.ipxe" if dnsmasq__boot_ipxe_enabled | bool else "pxelinux.0" }}'
DHCP hosts, DNS resource records
The variables below can be used to configure DHCP client entries as well as DNS resource records published by dnsmasq; syntax for both of these variables is the same. See dnsmasq__dhcp_hosts, dnsmasq__dns_records for more details.
- dnsmasq__dhcp_hosts
List of DHCP clients that dnsmasq knows about.
dnsmasq__dhcp_hosts: []
- dnsmasq__dns_records
List of DNS resource records that dnsmasq publishes.
dnsmasq__dns_records: []
- dnsmasq__dhcp_dns_filename
Name of the configuration file that contains DHCP and DNS entries, located in
the /etc/dnsmasq.d/
directory.
dnsmasq__dhcp_dns_filename: 'host-resource-records.conf'
The dnsmasq configuration files
These variables define the contents of the dnsmasq configuration
files located in the /etc/dnsmasq.d/
directory.
See dnsmasq__configuration for more details.
- dnsmasq__default_configuration
The configuration defined by the role by default.
dnsmasq__default_configuration:
# Remove the old default configuration file
- name: '00_main.conf'
state: 'absent'
- name: 'global.conf'
options:
- name: 'conntrack'
comment: 'Enable connection tracking support for firewalls'
raw: |
conntrack
state: 'present'
- name: 'enable-ra'
comment: 'Enable support for IPv6 Router Advertisements using dnsmasq'
raw: |
enable-ra
state: 'present'
- name: 'bind-interfaces'
comment: |
Bind only to the network interfaces explicitly set in the
configuration. This is required to allow additional dnsmasq instances
managed by, for example, libvirt.
raw: |
bind-dynamic
state: 'present'
- name: 'loopback-interface'
comment: 'Bind to loopback interface for local DNS queries'
raw: |
interface = lo
no-dhcp-interface = lo
state: 'present'
- name: 'addn-hosts'
comment: 'Read hosts information from additional files or directories'
value: '{{ dnsmasq__etc_hosts }}'
state: '{{ "present" if dnsmasq__etc_hosts | d() else "absent" }}'
- name: 'consul.conf'
comment: |
Support for Consul Agent DNS service on localhost
Ref: https://www.consul.io/docs/agent/dns.html
raw: |
server = /consul/127.0.0.1#8600
state: '{{ "present"
if (ansible_local.consul.installed | d() | bool)
else "init" }}'
- name: 'lxd-override'
filename: 'lxd'
comment: |
Tell any system-wide dnsmasq instance to make sure to bind to interfaces
instead of listening on 0.0.0.0
raw: |
bind-dynamic
except-interface = lxdbr0
state: '{{ "present" if (ansible_distribution == "Ubuntu") else "ignore" }}'
- name: 'reserved-domains.conf'
options:
- name: 'reserved-domains'
comment: |
Do not forward the reserved top level domains to upstream nameservers
raw: |
# Ref: https://tools.ietf.org/html/rfc2606
local = /test/example/invalid/
# Ref: https://tools.ietf.org/html/rfc6762
local = /local/
# Ref: https://tools.ietf.org/html/rfc7686
local = /onion/
state: 'present'
- name: 'private-domains'
comment: |
Do not forward the following private top level DNS names to upstream
DNS servers because RFC 6762 recommends not to use unregistered
top-level domains (https://tools.ietf.org/html/rfc6762#appendix-G)
raw: |
local = /intranet/internal/private/corp/home/lan/
state: 'present'
- name: 'block-dns-over-https'
comment: |
Blocking the 'use-application-dns.net' domain instructs the applications
that support DNS over HTTPS to not use it and rely on the system resolver
instead. This might be required for certain applications to support
access to internal services, resolve split-DNS correctly, etc.
Ref: https://support.mozilla.org/en-US/kb/canary-domain-use-application-dnsnet
raw: |
server = /use-application-dns.net/
state: 'present'
- name: 'dns-global.conf'
options:
- name: 'localise-queries'
comment: |
Return localized answers to DNS queries from '/etc/hosts' depending
on the originating network interface
raw: |
localise-queries
state: 'present'
- name: 'domain-needed'
comment: |
Never forward plain hostname queries for A or AAAA records to
upstream servers
raw: |
domain-needed
state: 'present'
- name: 'expand-hosts'
comment: |
Expand short hostnames found in the '/etc/hosts' file to full FQDN
addresses
raw: |
expand-hosts
state: 'present'
- name: 'stop-dns-rebind'
comment: |
Reject addresses from the upstream DNS nameservers which are located
in the private IP address ranges
raw: |
stop-dns-rebind
state: 'present'
- name: 'rebind-localhost-ok'
comment: |
Skip rebinding checks for '127.0.0.0/8' IP address range. This range
is used by the realtime black hole (RBL) servers.
raw: |
rebind-localhost-ok
state: 'present'
- name: 'rebind-local-domain-ok'
comment: |
Skip rebinding checks for local domain, in case dnsmasq is used as
a DNS cache and forwarder on a host that is a part of a network with
private IP address ranges, with a different DHCP/DNS server
maintaining the leases.
option: 'rebind-domain-ok'
value: '{{ dnsmasq__base_domain }}'
state: '{{ "present"
if (dnsmasq__base_domain_rebind_ok | bool and
dnsmasq__base_domain | d())
else "absent" }}'
- name: 'rebind-parent-domain-ok'
comment: |
Skip rebinding checks for the parent domain if it has 4 or more
levels, which is most likely an internal domain on a network with
private IP address ranges.
option: 'rebind-domain-ok'
value: '{{ dnsmasq__base_domain.split(".")[1:] | join(".") }}'
state: '{{ "present"
if (dnsmasq__base_domain_rebind_ok | bool and
dnsmasq__base_domain | d() and
(dnsmasq__base_domain.split(".") | length >= 4))
else "absent" }}'
- name: 'bogus-priv'
comment: |
Do not forward reverse DNS queries for private IP addresses to
upstream DNS servers.
When an LXC network support is enabled, this parameter is commented
out to allow revDNS queries. It will also be commented out when
upstream nameservers are located in a private network to allow DNS
queries to reach them. Ref: https://bugs.debian.org/461054
raw: |
bogus-priv
state: '{{ "comment"
if ((ansible_local.lxc.net_domain | d()) or
(ansible_local.resolvconf.upstream_nameservers
| d(ansible_dns.nameservers)
| ansible.utils.ipaddr("private")))
else "present" }}'
- name: 'resolv-file'
comment: |
Use custom list of nameservers instead of the system upstream
nameservers
value: '/etc/resolvconf/upstream.conf'
state: '{{ "present" if dnsmasq__nameservers | d() else "absent" }}'
- name: 'lxc-net.conf'
comment: |
Support for resolving LXC container hosts that use the 'lxc-net' bridge
configuration
options:
- name: 'local'
value: '{{ "/" + (ansible_local.lxc.net_domain | d(""))
+ "/" + ansible_local.lxc.net_address | d("") }}'
# Create a separate 'lxc' host record that points to the 'lxcbr0'
# interface from the outside, if there's no external domain set.
- name: 'host-record'
value: '{{ ansible_local.lxc.net_domain | d("")
+ "," + ansible_local.lxc.net_address | d("") }}'
state: '{{ "present"
if ("." not in ansible_local.lxc.net_domain | d())
else "absent" }}'
- name: 'rev-server'
value: '{{ ansible_local.lxc.net_subnet | d("")
+ "," + ansible_local.lxc.net_address | d("") }}'
- name: 'rebind-domain-ok'
value: '{{ ansible_local.lxc.net_domain | d("") }}'
state: '{{ "present"
if (ansible_local.lxc.net_domain | d())
else "init" }}'
- name: 'dhcp-boot.conf'
comment: |
This configuration file contains dnsmasq options related to booting
remote hosts using iPXE boot menu
options:
- name: 'dhcp-match-ipxe'
comment: |
Tag all DHCP requests with option 175 as coming from iPXE to avoid
recursive loops
option: 'dhcp-match'
value: 'set:ipxe,175'
- name: 'dhcp-match-d-i'
comment: |
Tag all DHCP requests with 'd-i' vendor class as coming from the
Debian Installer
option: 'dhcp-match'
value: 'set:debian-installer,option:vendor-class,"d-i"'
- name: 'vendor-match'
comment: |
Inspect the vendor class string and match the text to set the tag
Ref: https://tools.ietf.org/html/rfc4578#section-2.1
raw: |
dhcp-vendorclass = BIOS,PXEClient:Arch:00000
dhcp-vendorclass = UEFI32,PXEClient:Arch:00006
dhcp-vendorclass = UEFI,PXEClient:Arch:00007
dhcp-vendorclass = UEFI64,PXEClient:Arch:00009
- name: 'boot-ipxe-local'
comment: 'Set the boot file name based on the matching tag from the vendor class (above)'
raw: |
{% if dnsmasq__boot_ipxe_enabled | bool %}
# Redirect non-iPXE clients to iPXE
dhcp-boot = tag:!ipxe,tag:BIOS,undionly.kpxe
dhcp-boot = tag:!ipxe,tag:UEFI32,i386-efi/ipxe.efi
dhcp-boot = tag:!ipxe,tag:UEFI,ipxe.efi
dhcp-boot = tag:!ipxe,tag:UEFI64,ipxe.efi
# Load the main menu in iPXE clients
{% endif %}
dhcp-boot = {{ dnsmasq__boot_filename }}
state: '{{ "absent" if dnsmasq__boot_server | d() else "present" }}'
- name: 'boot-ipxe-remote'
comment: 'Set the boot file name based on the matching tag from the vendor class (above)'
raw: |
{% if dnsmasq__boot_ipxe_enabled | bool %}
# Redirect non-iPXE clients to iPXE
dhcp-boot = tag:!ipxe,tag:BIOS,undionly.kpxe,,{{ dnsmasq__boot_server }}
dhcp-boot = tag:!ipxe,tag:UEFI32,i386-efi/ipxe.efi,,{{ dnsmasq__boot_server }}
dhcp-boot = tag:!ipxe,tag:UEFI,ipxe.efi,,{{ dnsmasq__boot_server }}
dhcp-boot = tag:!ipxe,tag:UEFI64,ipxe.efi,,{{ dnsmasq__boot_server }}
# Load the main menu in iPXE clients
{% endif %}
dhcp-boot = {{ dnsmasq__boot_filename }},,{{ dnsmasq__boot_server }}
state: '{{ "present" if dnsmasq__boot_server | d() else "absent" }}'
state: '{{ "present" if dnsmasq__boot_enabled | bool else "init" }}'
- dnsmasq__interface_configuration
Automatically generated dnsmasq configuration for each of the
network interfaces defined in the dnsmasq__combined_interfaces
variable.
dnsmasq__interface_configuration: '{{ lookup("template", "lookup/dnsmasq__interface_configuration.j2",
convert_data=False) | from_yaml }}'
- dnsmasq__configuration
The configuration which should be present on all hosts in the Ansible inventory.
dnsmasq__configuration: []
- dnsmasq__group_configuration
The configuration which should be present on hosts in a specific Ansible inventory group.
dnsmasq__group_configuration: []
- dnsmasq__host_configuration
The configuration which should be present on specific hosts in the Ansible inventory.
dnsmasq__host_configuration: []
- dnsmasq__combined_configuration
The variable which combines all of the other configuration variables and is used in the Ansible tasks.
dnsmasq__combined_configuration: '{{ dnsmasq__default_configuration
+ dnsmasq__interface_configuration
+ dnsmasq__configuration
+ dnsmasq__group_configuration
+ dnsmasq__host_configuration }}'
Configuration for other Ansible roles
- dnsmasq__ferm__dependent_rules
Configuration for the debops.ferm Ansible role.
dnsmasq__ferm__dependent_rules:
- type: 'accept'
by_role: 'debops.dnsmasq'
name: 'dns'
weight: '40'
protocol: [ 'udp', 'tcp' ]
saddr: '{{ dnsmasq__public_dns_allow }}'
dport: [ 'domain' ]
accept_any: True
interface: '{{ []
if (dnsmasq__public_dns | bool)
else (dnsmasq__combined_interfaces | flatten | debops.debops.parse_kv_items
| selectattr("state", "equalto", "present")
| map(attribute="name") | list) }}'
rule_state: '{{ "present"
if ((dnsmasq__public_dns | bool) or
(dnsmasq__combined_interfaces | flatten | debops.debops.parse_kv_items
| selectattr("state", "equalto", "present")
| map(attribute="name") | list))
else "absent" }}'
- type: 'accept'
by_role: 'debops.dnsmasq'
name: 'dhcpv4'
weight: '40'
protocol: [ 'udp' ]
dport: [ 'bootps' ]
interface: '{{ dnsmasq__combined_interfaces | flatten | debops.debops.parse_kv_items
| selectattr("state", "equalto", "present")
| map(attribute="name") | list }}'
rule_state: '{{ "present"
if (dnsmasq__dhcpv4 | bool and
(dnsmasq__combined_interfaces | flatten | debops.debops.parse_kv_items
| selectattr("state", "equalto", "present")
| map(attribute="name") | list))
else "absent" }}'
- type: 'accept'
by_role: 'debops.dnsmasq'
name: 'dhcpv6'
weight: '40'
saddr: [ 'fe80::/10' ]
daddr: [ 'ff02::1:2' ]
# https://tools.ietf.org/html/rfc3315#section-13
protocol: [ 'udp' ]
sport: [ 'dhcpv6-client' ]
dport: [ 'dhcpv6-server' ]
interface: '{{ dnsmasq__combined_interfaces | flatten | debops.debops.parse_kv_items
| selectattr("state", "equalto", "present")
| map(attribute="name") | list }}'
rule_state: '{{ "present"
if (dnsmasq__dhcpv6 | bool and
(dnsmasq__combined_interfaces | flatten | debops.debops.parse_kv_items
| selectattr("state", "equalto", "present")
| map(attribute="name") | list))
else "absent" }}'
- type: 'accept'
by_role: 'debops.dnsmasq'
filename: 'tftp'
weight: '40'
dport: [ 'tftp' ]
protocol: [ 'udp' ]
interface: '{{ dnsmasq__combined_interfaces | flatten | debops.debops.parse_kv_items
| selectattr("state", "equalto", "present")
| map(attribute="name") | list }}'
rule_state: '{{ "present"
if (dnsmasq__boot_enabled | bool and
(dnsmasq__combined_interfaces | flatten | debops.debops.parse_kv_items
| selectattr("state", "equalto", "present")
| map(attribute="name") | list))
else "absent" }}'
- dnsmasq__tcpwrappers__dependent_allow
Configuration for the debops.tcpwrappers Ansible role.
dnsmasq__tcpwrappers__dependent_allow: '{{ lookup("template", "lookup/dnsmasq__tcpwrappers__dependent_allow.j2",
convert_data=False) | from_yaml }}'
- dnsmasq__apparmor__local_dependent_config
Configuration for the debops-contrib.apparmor
Ansible role.
dnsmasq__apparmor__local_dependent_config:
'usr.sbin.dnsmasq':
- comment: 'Allow dnsmasq to read upstream DNS servers'
rules:
- '/etc/resolvconf/upstream.conf r'
- '/etc/hosts.dnsmasq r'
- comment: 'Allow dnsmasq to read /usr/share/dnsmasq-base/trust-anchors.conf provided by dnsmasq-base'
rules:
- '/usr/share/dnsmasq-base/* r'
- dnsmasq__persistent_paths__dependent_paths
Configuration for the debops.persistent_paths Ansible role.
dnsmasq__persistent_paths__dependent_paths:
'50_debops_dnsmasq':
by_role: 'debops.dnsmasq'
paths:
- '/etc/ansible'
- '/etc/dnsmasq.d'
- '/etc/default/dnsmasq'
- '/etc/resolvconf/upstream.conf'
- '/etc/hosts.dnsmasq'