[AETHER-1000]
Allow reverse DNS lookups to work
NOTE: requires change in syntax used to define a zone - dns_zones no
longer works, must use dns_forward_zones/dns_reverse_zones
Fix multiplatform support
Change-Id: Ibd416b2da8853bc0b25ddec1774ddf9a9e1bf898
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f61049b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: © 2020 Open Networking Foundation <support@opennetworking.org>
+# SPDX-License-Identifier: Apache-2.0
+
+*.pyc
+__pycache__
diff --git a/README.md b/README.md
index 8af9627..84896ba 100644
--- a/README.md
+++ b/README.md
@@ -8,14 +8,15 @@
[NSD Documentation](https://nlnetlabs.nl/documentation/nsd/)
-By default, listens on 127.0.0.1 and assumes that `unbound` or a similar
-recursive resolver or a proxy like `dnscurve` is sending it requests.
+By default NSD will listen on 127.0.0.1 and assumes that `unbound` or a similar
+recursive resolver or a proxy like `dnscurve` is on the same host sending it
+requests.
-Both forward and reverse zones are created.
+Both forward and reverse zones can be specified.
-TODO:
-
-- Handle creating forward-only zones, where the IP address isn't within the subnet
+Note: Previous revisions of this role allowed for a single forward definition
+and inferred the reverse zone, but this does not work well with multiple
+RFC1918 subnets defined.
## Requirements
@@ -23,10 +24,10 @@
## Defaults
-See the `dns_zones` structure:
+See the `dns_forward_zones` and `dns_reverse_zones` structures:
```yaml
-dns_zones:
+dns_forward_zones:
example.com:
ip_range: 192.168.1.1/24
ns:
@@ -40,15 +41,28 @@
lpr: printer.example.com.
srv: {}
txt: {}
+
+dns_reverse_zones:
+ 192.168.0.0/16:
+ ns:
+ - gw.example.com.
+ ptr:
+ 192.168.1.1: gw.example.com.
+ 192.168.1.2: host1.example.com.
+ 192.168.1.3: host2.example.com.
+ 192.168.1.4: printer1.example.com.
+
```
Note: In the molecule tests, `<zone>.serial` is used for the zonefile serial,
-and is set to a static value to guarantee idempotency. In production, this
-must be changed every time the zonefile changes, or can be omitted and the
-current timestamp is used to generate the serial. Other DNS roles tried
-`complicated solutions
+and is set to a static value to guarantee idempotency. In production, this must
+be changed every time the zonefile changes, or can be omitted and the current
+timestamp is used to generate the serial. Other DNS roles tried `complicated
+solutions
<https://github.com/bertvv/ansible-role-bind/blob/master/templates/bind_zone.j2>`_
-to guarantee the serial changes, but that seems like a lot of trouble, and is only useful for zone transfers which are silly/antiquated
+to guarantee the serial changes, but that seems like a lot of trouble, and is
+only useful for facilitating zone transfers which are
+silly/antiquated/security-problematic.
## Example Playbook
diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml
index e88b105..1b9266f 100644
--- a/molecule/default/converge.yml
+++ b/molecule/default/converge.yml
@@ -7,7 +7,7 @@
- name: Converge
hosts: all
vars:
- dns_zones:
+ dns_forward_zones:
example.com:
serial: 20201102
ip_range: 10.0.0.1/24
@@ -26,12 +26,25 @@
serial: 20201102
ip_range: 10.0.10.1/24
ns:
- - gw2.example.com.
+ - gw2.example.org.
a:
gw2: 10.0.10.1
cname: {}
srv: {}
txt: {}
+ dns_reverse_zones:
+ 10.0.0.0/8:
+ serial: 20210315
+ ns:
+ - gw.example.com.
+ - gw2.example.org.
+ ptr:
+ 10.0.0.1: gw.example.com.
+ 10.0.0.2: host1.example.com.
+ 10.0.0.3: host2.example.com.
+ 10.0.0.4: printer1.example.com.
+ 10.0.10.1: gw2.example.org.
+
tasks:
- name: "Include nsd"
include_role:
diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml
index 43cba44..596330b 100644
--- a/molecule/default/verify.yml
+++ b/molecule/default/verify.yml
@@ -21,12 +21,24 @@
- name: Check for NS record
command: # noqa 301
- cmd: "dig ns example.com @127.0.0.1"
+ cmd: "dig ns +short example.com @127.0.0.1"
register: ns_dig
- failed_when: "'example.com.\t\t3600\tIN\tNS\tgw.example.com.' not in ns_dig.stdout"
+ failed_when: "'gw.example.com.' not in ns_dig.stdout"
- name: Check for CNAME record
command: # noqa 301
cmd: "dig lpr.example.com @127.0.0.1"
register: cn_dig
failed_when: "'lpr.example.com.\t3600\tIN\tCNAME\tprinter.example.com.' not in cn_dig.stdout"
+
+ - name: Check for reverse IP lookup
+ command: # noqa 301
+ cmd: "dig -x {{ item.key }} @127.0.0.1"
+ register: rip_dig
+ failed_when: "item.value not in rip_dig.stdout"
+ with_dict:
+ 10.0.0.1: gw.example.com.
+ 10.0.0.2: host1.example.com.
+ 10.0.0.3: host2.example.com.
+ 10.0.0.4: printer1.example.com.
+ 10.0.10.1: gw2.example.org.
diff --git a/tasks/OpenBSD.yml b/tasks/OpenBSD.yml
index e64f33f..e067aa9 100644
--- a/tasks/OpenBSD.yml
+++ b/tasks/OpenBSD.yml
@@ -4,4 +4,8 @@
# SPDX-FileCopyrightText: © 2020 Open Networking Foundation <support@opennetworking.org>
# SPDX-License-Identifier: Apache-2.0
-# nothing to do here, OpenBSD already has NSD installed in base
+# NSD installed in base
+
+- name: Set unbound arguments for use with service module
+ set_fact:
+ nsd_arguments: "-c /var/nsd/etc/nsd.conf"
diff --git a/tasks/main.yml b/tasks/main.yml
index d6a9af6..2d28754 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -38,21 +38,28 @@
owner: root
group: "{{ nsd_groupname }}"
validate: "nsd-checkzone {{ item.key }} %s"
- with_dict: "{{ dns_zones }}"
+ with_dict: "{{ dns_forward_zones }}"
notify:
- reload-nsd
-# - name: Create DNS reverse zonefiles from template
-# template:
-# src: zone.reverse.j2
-# dest: "{{ nsd_zones_dir }}/{{ item.key }}.reverse"
-# mode: 0644
-# owner: root
-# group: "{{ nsd_groupname }}"
-# validate: "nsd-checkzone {{ item.value.ip_range | unbound_revdns }} %s"
-# with_dict: "{{ dns_zones }}"
-# notify:
-# - reload-nsd
+- name: Create DNS reverse zonefiles from template
+ template:
+ src: zone.reverse.j2
+ dest: "{{ nsd_zones_dir }}/{{ item.key | ipaddr('network') }}.reverse"
+ mode: 0644
+ owner: root
+ group: "{{ nsd_groupname }}"
+ validate: "nsd-checkzone {{ item.key | unbound_revdns }} %s"
+ with_dict: "{{ dns_reverse_zones }}"
+ notify:
+ - reload-nsd
+
+- name: Enable and start nsd
+ service:
+ name: "{{ nsd_service }}"
+ enabled: true
+ state: started
+ arguments: "{{ nsd_arguments | default(omit) }}"
- name: Flush handlers as listen addresses can conflict with unbound
meta: flush_handlers
diff --git a/templates/nsd.conf.j2 b/templates/nsd.conf.j2
index 93c2a14..b079d13 100644
--- a/templates/nsd.conf.j2
+++ b/templates/nsd.conf.j2
@@ -18,14 +18,17 @@
remote-control:
control-enable: yes
-# zonefiles to load
-{% for key, value in dns_zones.items() %}
+# forward zones
+{% for key, value in dns_forward_zones.items() %}
zone:
name: {{ key }}
zonefile: {{ key }}.forward
+{% endfor %}
-# zone:
-# name: {{ value.ip_range | unbound_revdns }}
-# zonefile: {{ key }}.reverse
+# reverse zones
+{% for key, value in dns_reverse_zones.items() %}
+zone:
+ name: {{ key | unbound_revdns }}
+ zonefile: {{ key | ipaddr('network') }}.reverse
{% endfor %}
diff --git a/templates/zone.reverse.j2 b/templates/zone.reverse.j2
index a0e5ecc..512f34f 100644
--- a/templates/zone.reverse.j2
+++ b/templates/zone.reverse.j2
@@ -7,17 +7,20 @@
$ORIGIN {{ item.key }}. ; default zone domain
$TTL {{ item.value.ttl | default(nsd_default_ttl) }} ; default time to live
-{{ item.value.ip_range | unbound_revdns }} IN SOA {{ item.value.ns | first }} admin.{{ item.key }}. (
+{{ item.key| unbound_revdns }} IN SOA {{ item.value.ns | first }} admin.{{ item.key }}. (
{{ item.value.serial | default(ansible_date_time.epoch) }} ; Serial, must be incremented every time you change this file
3600 ; Refresh [1hr]
600 ; Retry [10m]
3600 ; Expire [1hr]
60 ; Min TTL [1m]
)
-{% if item.value.a is defined %}
+
+; NameServers
+{% for ns in item.value.ns %}
+ IN NS {{ ns }}
+{% endfor %}
; PTR records
-{% for name, ip4 in item.value.a.items() %}
+{% for ip4, name in item.value.ptr.items() %}
{{ ip4 | ipaddr('revdns')}} IN PTR {{ name }}
{% endfor %}
-{% endif %}