diff --git a/playbooks/ns.yml b/playbooks/ns.yml new file mode 100644 index 0000000..e29c441 --- /dev/null +++ b/playbooks/ns.yml @@ -0,0 +1,6 @@ +- name: Configure bind9 name server + hosts: all + tasks: + - name: Configure services to install in the server + import_role: + name: ns \ No newline at end of file diff --git a/roles/ns/defaults/main.yml b/roles/ns/defaults/main.yml new file mode 100644 index 0000000..daeccf4 --- /dev/null +++ b/roles/ns/defaults/main.yml @@ -0,0 +1,29 @@ +bind_packages: + - bind9 + - bind9-dnsutils + - bind9-host + - bind9-libs + - bind9-utils + - dnsutils + - python3-pycurl +bind_config_templates: + - { src: 'named.conf.j2', dest: '/etc/bind/named.conf', mode: 'u=rw,g=r,o=r' } + - { src: 'named.conf.master.j2', dest: '/etc/bind/named.conf.master', mode: 'u=rw,g=r,o=r' } + - { src: 'named.conf.local.j2', dest: '/etc/bind/named.conf.local', mode: 'u=rw,g=r,o=r' } + - { src: 'named.conf.slave.j2', dest: '/etc/bind/named.conf.slave', mode: 'u=rw,g=r,o=r' } + - { src: 'certbot.key', dest: '/etc/bind/keys/certbot.key', mode: 'u=rw,g=r,o=' } + - { src: 'lan.key', dest: '/etc/bind/keys/lan.key', mode: 'u=rw,g=r,o=' } + - { src: 'wan.key', dest: '/etc/bind/keys/wan.key', mode: 'u=rw,g=r,o=' } + - { src: 'rndc.key', dest: '/etc/bind/rndc.key', mode: 'u=rw,g=r,o=' } + - { src: 'dhcp.key', dest: '/etc/bind/keys/dhcp.key', mode: 'u=rw,g=r,o=' } + - { src: 'isp1.ns', dest: '/root/scripts/switch-isp', mode: 'u=rw,g=rw,o=r' } + - { src: 'isp2.ns', dest: '/root/scripts/switch-isp', mode: 'u=rw,g=rw,o=r' } +directory: + - { path: '/root/scripts', owner: 'root', group: 'root', mode: 'u=rwx,g=rx,o=rx' } + - { path: '/etc/bind/keys', owner: 'root', group: 'bind', mode: 'u=rwx,g=rxs,o=rx' } + - { path: '/root/scripts/switch-isp', owner: 'root', group: 'bind', mode: 'u=rwx,g=rxs,o=rx' } +required_files: + - { src: 'delete.ns', dest: '/root/scripts/switch-isp', owner: 'root', group: 'bind', mode: 'u=rw,g=rw,o=r' } + - { src: 'switch-isp.sh', dest: '/root/scripts', owner: 'root', group: 'root', mode: 'u=rwx,g=rx,o=rx' } + - { src: 'sync-conf', dest: '/root/scripts', owner: 'root', group: 'root', mode: 'u=rwx,g=rx,o=rx' } + - { src: 'gen-key.sh', dest: '/root/scripts', owner: 'root', group: 'bind', mode: 'u=rwx,g=rx,o=rx' } diff --git a/roles/ns/files/delete.ns b/roles/ns/files/delete.ns new file mode 100644 index 0000000..cbb97ad --- /dev/null +++ b/roles/ns/files/delete.ns @@ -0,0 +1,14 @@ +update delete verdnatura.es A +update delete kube-proxy.verdnatura.es A +update delete smtp.verdnatura.es A +update delete imap.verdnatura.es A +update delete autodiscover.verdnatura.es A +update delete time1.verdnatura.es A +update delete time2.verdnatura.es A +update delete dc-ip01.verdnatura.es A +update delete dc-ip02.verdnatura.es A +update delete dc-ip03.verdnatura.es A +update delete dc-ip04.verdnatura.es A +update delete mailgw1.verdnatura.es A +update delete mailgw2.verdnatura.es A +send diff --git a/roles/ns/files/gen-key.sh b/roles/ns/files/gen-key.sh new file mode 100644 index 0000000..4c062a2 --- /dev/null +++ b/roles/ns/files/gen-key.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +KEYNAME=$1 + +if [ -z "$KEYNAME" ]; then + echo "Usage: $0 " + exit 1 +fi + +tsig-keygen -a hmac-sha512 "$KEYNAME" diff --git a/roles/ns/files/switch-isp.sh b/roles/ns/files/switch-isp.sh new file mode 100644 index 0000000..5444192 --- /dev/null +++ b/roles/ns/files/switch-isp.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +ISP=$1 + +if [ -z "$ISP" ]; then + echo "Usage: $0 " + exit 1 +fi + +KEY_FILE="/etc/bind/keys/wan.key" +NS_DIR="/root/scripts/switch-isp" +ISP_FILE="$NS_DIR/$ISP.ns" + +if [ ! -f "$ISP_FILE" ]; then + echo "ISP file for nsupdate not found: $ISP_FILE" + exit 2 +fi + +echo "Deleting ISP dependent DNS records." +nsupdate -k "$KEY_FILE" "$NS_DIR/delete.ns" + +echo "Registering $ISP DNS records." +nsupdate -k "$KEY_FILE" "$ISP_FILE" diff --git a/roles/ns/files/sync-conf b/roles/ns/files/sync-conf new file mode 100644 index 0000000..a3b947b --- /dev/null +++ b/roles/ns/files/sync-conf @@ -0,0 +1,27 @@ +#!/bin/bash + +if [ "$(hostname)" = "ns1" ]; then + partner=root@ns2.servers.dc.verdnatura.es +else + partner=root@ns1.servers.dc.verdnatura.es +fi + +confDir=/etc/bind + +echo "Restarting service." +service bind9 restart + +if [ $? -eq "0" ]; then + echo "Synchronizing partner configuration." + + scp "$confDir/named.conf.local" $partner:$confDir + scp "$confDir/named.conf.master" $partner:$confDir + scp "$confDir/named.conf.slave" $partner:$confDir + + ssh "$partner" rm -rf "$confDir/keys" + ssh "$partner" mkdir "$confDir/keys" + scp -r "$confDir/keys/"* $partner:"$confDir/keys" + + echo "Restarting partner service." + ssh $partner service bind9 restart +fi diff --git a/roles/ns/handlers/main.yml b/roles/ns/handlers/main.yml new file mode 100644 index 0000000..840d041 --- /dev/null +++ b/roles/ns/handlers/main.yml @@ -0,0 +1,4 @@ +- name: restart-dns + systemd: + name: bind9 + state: restarted \ No newline at end of file diff --git a/roles/ns/tasks/main.yml b/roles/ns/tasks/main.yml new file mode 100644 index 0000000..0948ab4 --- /dev/null +++ b/roles/ns/tasks/main.yml @@ -0,0 +1,2 @@ +- import_tasks: ns.yml + tags: ns diff --git a/roles/ns/tasks/ns.yml b/roles/ns/tasks/ns.yml new file mode 100644 index 0000000..7943efa --- /dev/null +++ b/roles/ns/tasks/ns.yml @@ -0,0 +1,34 @@ +- name: Update apt cache + apt: + update_cache: yes +- name: Install bind package requirements + apt: + name: "{{ bind_packages }}" + state: present + install_recommends: no +- name: Create directory + file: + path: "{{ item.path }}" + state: directory + owner: "{{ item.group }}" + group: "{{ item.group }}" + mode: "{{ item.mode }}" + loop: "{{ directory }}" +- name: Copy required files and scripts + copy: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ item.group }}" + group: "{{ item.group }}" + mode: "{{ item.mode }}" + loop: "{{ required_files }}" +- name: Deploy BIND config templates + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: root + group: bind + mode: "{{ item.mode }}" + loop: "{{ bind_config_templates }}" + notify: restart-dns + diff --git a/roles/ns/templates/certbot.key b/roles/ns/templates/certbot.key new file mode 100644 index 0000000..6e9f1b9 --- /dev/null +++ b/roles/ns/templates/certbot.key @@ -0,0 +1,4 @@ +key "certbot" { + algorithm hmac-sha512; + secret "{{ lookup(passbolt, 'certbot', folder_parent_id=passbolt_folder).password }}"; +}; diff --git a/roles/ns/templates/dhcp.key b/roles/ns/templates/dhcp.key new file mode 100644 index 0000000..a732d1e --- /dev/null +++ b/roles/ns/templates/dhcp.key @@ -0,0 +1,4 @@ +key "dhcp" { + algorithm hmac-sha512; + secret "{{ lookup(passbolt, 'dhcpkey', folder_parent_id=passbolt_folder).password }}"; +}; diff --git a/roles/ns/templates/isp1.ns b/roles/ns/templates/isp1.ns new file mode 100644 index 0000000..57eba65 --- /dev/null +++ b/roles/ns/templates/isp1.ns @@ -0,0 +1,4 @@ +{% for record in dns_records_main %} +update add {{ record.name.ljust(30) }} {{ record.ttl }} A {{ record.ip }} +{% endfor %} +send diff --git a/roles/ns/templates/isp2.ns b/roles/ns/templates/isp2.ns new file mode 100644 index 0000000..e89b38e --- /dev/null +++ b/roles/ns/templates/isp2.ns @@ -0,0 +1,4 @@ +{% for record in dns_records_secondary %} +update add {{ record.name.ljust(30) }} {{ record.ttl }} A {{ record.ip }} +{% endfor %} +send diff --git a/roles/ns/templates/lan.key b/roles/ns/templates/lan.key new file mode 100644 index 0000000..c99ad33 --- /dev/null +++ b/roles/ns/templates/lan.key @@ -0,0 +1,4 @@ +key "lan" { + algorithm hmac-sha512; + secret "{{ lookup(passbolt, 'lankey', folder_parent_id=passbolt_folder).password }}"; +}; diff --git a/roles/ns/templates/named.conf.j2 b/roles/ns/templates/named.conf.j2 new file mode 100644 index 0000000..32e13f7 --- /dev/null +++ b/roles/ns/templates/named.conf.j2 @@ -0,0 +1,16 @@ +// This is the primary configuration file for the BIND DNS server named. +// +// Please read /usr/share/doc/bind9/README.Debian.gz for information on the +// structure of BIND configuration files in Debian, *BEFORE* you customize +// this configuration file. +// +// If you are just adding zones, please do that in /etc/bind/named.conf.local + +#include "/etc/bind/named.conf.options"; +include "/etc/bind/named.conf.local"; +{% if bind_is_master %} +include "/etc/bind/named.conf.master"; +{% else %} +include "/etc/bind/named.conf.slave"; +{% endif %} +#include "/etc/bind/named.conf.default-zones"; diff --git a/roles/ns/templates/named.conf.local.j2 b/roles/ns/templates/named.conf.local.j2 new file mode 100644 index 0000000..09a8935 --- /dev/null +++ b/roles/ns/templates/named.conf.local.j2 @@ -0,0 +1,30 @@ +include "/etc/bind/rndc.key"; +include "/etc/bind/keys/wan.key"; +include "/etc/bind/keys/lan.key"; +include "/etc/bind/keys/certbot.key"; +include "/etc/bind/keys/dhcp.key"; + +server fe80::/16 { bogus yes; }; + +acl lan { + 10.0.0.0/8; + 172.16.0.0/12; + 192.168.0.0/16; + }; + +acl rfc5735 { + 0.0.0.0/8; + 169.254.0.0/16; + 192.0.0.0/24; + 192.0.2.0/24; + 192.88.99.0/24; + 198.18.0.0/15; + 198.51.100.0/24; + 203.0.113.0/24; + 224.0.0.0/4; + 240.0.0.0/4; + }; + +controls { + inet * allow { localhost; lan; } keys { "rndc-key"; }; +}; diff --git a/roles/ns/templates/named.conf.master.j2 b/roles/ns/templates/named.conf.master.j2 new file mode 100644 index 0000000..dc63834 --- /dev/null +++ b/roles/ns/templates/named.conf.master.j2 @@ -0,0 +1,78 @@ +options { + directory "/var/cache/bind"; + max-cache-size 500m; + auth-nxdomain no; + listen-on-v6 { none; }; + version "DNS"; + allow-update { none; }; + blackhole { rfc5735; }; + + allow-transfer { + {% for ip in bind_allow_transfer %} + {{ ip }}; + {% endfor %} + }; +}; + +view "lan" { + match-clients { + {% for item in key_match_clients_lan_master if item.startswith("!key") %} + {{ item }}; + {% endfor %} +{% for item in acl_match_clients %} + {{ item }}; + {% endfor %} +{% for item in key_match_clients_lan_master if not item.startswith("!key") %} + {{ item }}; + {% endfor %} +}; + + recursion yes; + allow-recursion { any; }; + empty-zones-enable yes; + notify yes; + + include "/etc/bind/named.conf.default-zones"; + + {% for zone in bind_zones.lan %} + zone "{{ zone.name }}" { + type master; + forwarders {}; + allow-update { key {{ zone.key }}; }; + file "{{ zone.file }}"; + }; + {% endfor %} +}; + +view "wan" { + match-clients { any; }; + + recursion no; + allow-query-cache { none; }; + empty-zones-enable no; + + notify explicit; + + also-notify { + {% for entry in bind_also_notify %} + {{ entry.ip }} key {{ entry.key }}; + {% endfor %} + }; + + {% for zone in bind_zones.wan %} + {% if zone.in_view is defined %} + {% for z in zone.in_view %} + zone "{{ z }}" { + in-view "lan"; + }; + {% endfor %} + {% else %} + zone "{{ zone.name }}" { + type master; + forwarders {}; + allow-update { key {{ zone.key }}; }; + file "{{ zone.file }}"; + }; + {% endif %} + {% endfor %} +}; diff --git a/roles/ns/templates/named.conf.slave.j2 b/roles/ns/templates/named.conf.slave.j2 new file mode 100644 index 0000000..c1142a1 --- /dev/null +++ b/roles/ns/templates/named.conf.slave.j2 @@ -0,0 +1,73 @@ +options { + directory "/var/cache/bind"; + max-cache-size 500m; + auth-nxdomain no; + listen-on-v6 { none; }; + version "DNS"; + allow-update { none; }; + blackhole { rfc5735; }; + + notify no; + allow-transfer { none; }; + masterfile-format text; +}; + +masters master-ips { +{% for ip in bind_slave_masters %} + {{ ip }}; +{% endfor %} +}; + +view "lan" { + match-clients { + {% for item in key_match_clients_lan_master if item.startswith("!key") %} + {{ item }}; + {% endfor %} +{% for item in acl_match_clients %} + {{ item }}; + {% endfor %} +{% for item in key_match_clients_lan_slave if not item.startswith("!key") %} + {{ item }}; + {% endfor %} +}; + + recursion yes; + allow-recursion { any; }; + empty-zones-enable yes; + + include "/etc/bind/named.conf.default-zones"; + + {% for zone in bind_zones.lan %} + zone "{{ zone.name }}" { + type slave; + masters { master-ips; }; + forwarders {}; + file "{{ zone.file }}"; + }; + {% endfor %} +}; + +view "wan" { + match-clients { any; }; + + recursion no; + allow-query-cache { none; }; + empty-zones-enable no; + + {% for zone in bind_zones.wan %} + {% if zone.in_view is defined %} + {% for z in zone.in_view %} + zone "{{ z }}" { + in-view "lan"; + }; + {% endfor %} + {% else %} + zone "{{ zone.name }}" { + type slave; + masters { {{ bind_slave_masters | join('; ') }} key {{ zone.key }}; }; + forwarders {}; + file "{{ zone.file }}"; + }; + {% endif %} + {% endfor %} +}; diff --git a/roles/ns/templates/rndc.key b/roles/ns/templates/rndc.key new file mode 100644 index 0000000..40d9600 --- /dev/null +++ b/roles/ns/templates/rndc.key @@ -0,0 +1,4 @@ +key "rndc-key" { + algorithm hmac-md5; + secret "{{ lookup(passbolt, 'rndc-key', folder_parent_id=passbolt_folder).password }}"; +}; diff --git a/roles/ns/templates/wan.key b/roles/ns/templates/wan.key new file mode 100644 index 0000000..daa655c --- /dev/null +++ b/roles/ns/templates/wan.key @@ -0,0 +1,4 @@ +key "wan-key" { + algorithm hmac-md5; + secret "{{ lookup(passbolt, 'wan-key', folder_parent_id=passbolt_folder).password }}"; +};