diff --git a/inventory/group_vars/all/global.yml b/inventory/group_vars/all/global.yml new file mode 100644 index 0000000..b45acdd --- /dev/null +++ b/inventory/group_vars/all/global.yml @@ -0,0 +1,3 @@ +--- + +global_public_ip_address: 82.66.135.228 diff --git a/inventory/group_vars/nsdservers.yml b/inventory/group_vars/nsdservers.yml index ca64f4c..ef020c1 100644 --- a/inventory/group_vars/nsdservers.yml +++ b/inventory/group_vars/nsdservers.yml @@ -2,7 +2,6 @@ zones: - name: giteu.be - parking: true - name: libertus.eu - name: mateu.be - name: monder.ch @@ -13,7 +12,6 @@ zones: parking: true - name: pipoworld.fr parking: true - - name: sebicomics.com tsig_key: !vault | $ANSIBLE_VAULT;1.1;AES256 diff --git a/inventory/host_vars/dns1.yml b/inventory/host_vars/dns1.yml new file mode 100644 index 0000000..eda4a82 --- /dev/null +++ b/inventory/host_vars/dns1.yml @@ -0,0 +1,3 @@ +--- + +natted_ipv4: "{{ global_public_ip_address }}" diff --git a/inventory/host_vars/ks3370405.yml b/inventory/host_vars/ks3370405.yml index 89a2642..24b1551 100644 --- a/inventory/host_vars/ks3370405.yml +++ b/inventory/host_vars/ks3370405.yml @@ -3,7 +3,9 @@ web_hostname: - host: mail-relay.mateu.be -allowed_smtp_ips: ["82.66.135.228", "80.67.179.200"] +allowed_smtp_ips: "{{ [global_public_ip_address] + ['80.67.179.200'] }}" global_smtp_relay_allowed_ips: "{{ allowed_smtp_ips }}" ufw_allowed_smtp_ips: "{{ allowed_smtp_ips }}" + +nsd_master: true diff --git a/inventory/static.yml b/inventory/static.yml index 1faf0b1..23778d9 100644 --- a/inventory/static.yml +++ b/inventory/static.yml @@ -25,6 +25,11 @@ physicalservers: hosts: frederica: serenor: + ks3370405: + +nsdservers: + hosts: + ks3370405: webservers: hosts: diff --git a/playbooks/global_smtprelay.yml b/playbooks/global_smtprelay.yml index 9a3af34..908e5af 100644 --- a/playbooks/global_smtprelay.yml +++ b/playbooks/global_smtprelay.yml @@ -3,5 +3,4 @@ - name: Install & configure the global SMTP relay hosts: ks3370405 roles: - - ufw - global_smtp_relay diff --git a/playbooks/nsd.yml b/playbooks/nsd.yml new file mode 100644 index 0000000..3e14ac3 --- /dev/null +++ b/playbooks/nsd.yml @@ -0,0 +1,7 @@ +--- + +- name: Deploy NSD + hosts: nsdservers + diff: true + roles: + - nsd diff --git a/playbooks/site.yml b/playbooks/site.yml index 3f6693c..80f8a5b 100644 --- a/playbooks/site.yml +++ b/playbooks/site.yml @@ -18,8 +18,12 @@ import_playbook: firewall.yml - name: Run mail playbook import_playbook: mail.yml +- name: Run ufw plabook + import_playbook: ufw.yml - name: Run global_smtprelay playbook import_playbook: global_smtprelay.yml +- name: Run nsd playbook + import_playbook: nsd.yml - name: Run xmpp playbook import_playbook: xmpp.yml - name: Run webservers playbook diff --git a/playbooks/ufw.yml b/playbooks/ufw.yml new file mode 100644 index 0000000..e31b48b --- /dev/null +++ b/playbooks/ufw.yml @@ -0,0 +1,6 @@ +--- + +- name: Install & configure UFW + hosts: ks3370405 + roles: + - ufw diff --git a/roles/firewall/templates/firewall.j2 b/roles/firewall/templates/firewall.j2 index 850e1a0..b2bc3f7 100644 --- a/roles/firewall/templates/firewall.j2 +++ b/roles/firewall/templates/firewall.j2 @@ -350,6 +350,53 @@ config redirect option dest_port '64738' option target 'DNAT' +# Allow DNS traffic +config rule + option name 'Allow-INPUT-DNS' + option src 'wan' + list proto 'tcp' + list proto 'udp' + option dest 'dmz' + option dest_ip '{{ hostvars['dns1'].proxmox_net0.ip6 | ansible.utils.ipaddr('address') }}' + option dest_port '53' + option target 'ACCEPT' + option family 'ipv6' + +config redirect + option name 'Allow-INPUT-DNS' + option src 'wan' + option src_dport '53' + list proto 'tcp' + list proto 'udp' + option dest 'dmz' + option dest_ip '{{ hostvars['dns1'].proxmox_net0.ip | ansible.utils.ipaddr('address') }}' + option dest_port '53' + option target 'DNAT' + +config rule + option name 'Allow-OUTPUT-DNS' + option src 'dmz' + option src_ip '{{ hostvars['dns1'].proxmox_net0.ip | ansible.utils.ipaddr('address') }}' + list proto 'tcp' + list proto 'udp' + option dest 'wan' + option dest_port '53' + option dest_ip '{{ hostvars['ks3370405'].ansible_default_ipv4.address }}' + option target 'ACCEPT' + option family 'ipv4' + +config rule + option name 'Allow-OUTPUT-DNS' + option src 'dmz' + option src_ip '{{ hostvars['dns1'].proxmox_net0.ip6 | ansible.utils.ipaddr('address') }}' + list proto 'tcp' + list proto 'udp' + option dest 'wan' + option dest_port '53' + option dest_ip '{{ hostvars['ks3370405'].ansible_default_ipv6.address }}' + option target 'ACCEPT' + option family 'ipv6' + # Allow mail traffic config rule option name 'Allow-OUTPUT-SMTP' diff --git a/roles/global_smtp_relay/templates/main.cf.j2 b/roles/global_smtp_relay/templates/main.cf.j2 index 594e819..64637d0 100644 --- a/roles/global_smtp_relay/templates/main.cf.j2 +++ b/roles/global_smtp_relay/templates/main.cf.j2 @@ -4,7 +4,7 @@ myhostname = mail-relay.mateu.be myorigin = $myhostname mydestination = $myhostname, localhost.$mydomain, localhost unknown_local_recipient_reject_code = 550 -mynetworks = 127.0.0.0/8, [::1]/128, 82.66.135.228, 80.67.179.200 +mynetworks = 127.0.0.0/8, [::1]/128, {{ global_smtp_relay_allowed_ips | join(', ') }} sendmail_path = /usr/bin/sendmail newaliases_path = /usr/bin/newaliases mailq_path = /usr/bin/mailq diff --git a/roles/munin_client/files/nsd b/roles/munin_client/files/nsd new file mode 100644 index 0000000..dbba03d --- /dev/null +++ b/roles/munin_client/files/nsd @@ -0,0 +1,127 @@ +#!/bin/sh + +: << =cut + +=head1 NAME + +nsd - Plugin to monitor nsd DNS server + +=head1 CONFIGURATION + +No configuration + +=head1 AUTHOR + +Kim Heino + +=head1 LICENSE + +GPLv2 + +=head1 MAGIC MARKERS + + #%# family=auto + #%# capabilities=autoconf + +=cut + +if [ "$1" = "autoconf" ]; then + if [ -x /usr/sbin/nsd-control ]; then + echo "yes" + exit 0 + else + echo "no (no /usr/sbin/nsd-control)" + exit 0 + fi +fi + +if [ "$1" = "config" ]; then + echo 'graph_title NSD queries' + echo 'graph_vlabel queries / second' + echo 'graph_category dns' + echo 'graph_info Queries per second, by query type' + echo 'a.label A' + echo 'a.type DERIVE' + echo 'a.min 0' + echo 'aaaa.label AAAA' + echo 'aaaa.type DERIVE' + echo 'aaaa.min 0' + echo 'ptr.label PTR' + echo 'ptr.type DERIVE' + echo 'ptr.min 0' + echo 'cname.label CNAME' + echo 'cname.type DERIVE' + echo 'cname.min 0' + echo 'mx.label MX' + echo 'mx.type DERIVE' + echo 'mx.min 0' + echo 'txt.label TXT' + echo 'txt.type DERIVE' + echo 'txt.min 0' + echo 'soa.label SOA' + echo 'soa.type DERIVE' + echo 'soa.min 0' + echo 'ns.label NS' + echo 'ns.type DERIVE' + echo 'ns.min 0' + echo 'srv.label SRV' + echo 'srv.type DERIVE' + echo 'srv.min 0' + echo 'dnskey.label DNSKEY' + echo 'dnskey.type DERIVE' + echo 'dnskey.min 0' + echo 'axfr.label AXFR' + echo 'axfr.type DERIVE' + echo 'axfr.min 0' + echo 'snxd.label NXDOMAIN' + echo 'snxd.type DERIVE' + echo 'snxd.min 0' + echo 'rq.label Total Successful' + echo 'rq.type DERIVE' + echo 'rq.min 0' + exit 0 +fi + +/usr/sbin/nsd-control stats_noreset | sed 's/=/ /; s/\.//g' | ( + numtypeA=0 + numtypeAAAA=0 + numtypePTR=0 + numtypeCNAME=0 + numtypeMX=0 + numtypeTXT=0 + numtypeSOA=0 + numtypeNS=0 + numtypeSRV=0 + numtypeDNSKEY=0 + numraxfr=0 + numrcodeNXDOMAIN=0 + numqueries=0 + while read -r key value rest; do + [ "${key}" = "numtypeA" ] && numtypeA=${value} + [ "${key}" = "numtypeAAAA" ] && numtypeAAAA=${value} + [ "${key}" = "numtypePTR" ] && numtypePTR=${value} + [ "${key}" = "numtypeCNAME" ] && numtypeCNAME=${value} + [ "${key}" = "numtypeMX" ] && numtypeMX=${value} + [ "${key}" = "numtypeTXT" ] && numtypeTXT=${value} + [ "${key}" = "numtypeSOA" ] && numtypeSOA=${value} + [ "${key}" = "numtypeNS" ] && numtypeNS=${value} + [ "${key}" = "numtypeSRV" ] && numtypeSRV=${value} + [ "${key}" = "numtypeDNSKEY" ] && numtypeDNSKEY=${value} + [ "${key}" = "numraxfr" ] && numraxfr=${value} + [ "${key}" = "numrcodeNXDOMAIN" ] && numrcodeNXDOMAIN=${value} + [ "${key}" = "numqueries" ] && numqueries=${value} + done + echo "a.value ${numtypeA}" + echo "aaaa.value ${numtypeAAAA}" + echo "ptr.value ${numtypePTR}" + echo "cname.value ${numtypeCNAME}" + echo "mx.value ${numtypeMX}" + echo "txt.value ${numtypeTXT}" + echo "soa.value ${numtypeSOA}" + echo "ns.value ${numtypeNS}" + echo "srv.value ${numtypeSRV}" + echo "dnskey.value ${numtypeDNSKEY}" + echo "axfr.value ${numraxfr}" + echo "snxd.value ${numrcodeNXDOMAIN}" + echo "rq.value ${numqueries}" +) diff --git a/roles/munin_client/tasks/main.yml b/roles/munin_client/tasks/main.yml index 547fb01..4981459 100644 --- a/roles/munin_client/tasks/main.yml +++ b/roles/munin_client/tasks/main.yml @@ -136,6 +136,11 @@ ansible.builtin.include_tasks: garage.yml when: "'garageservers' in group_names" +# Specific nsd commands +- name: Execute specific nsd commands + ansible.builtin.include_tasks: nsd.yml + when: "'nsdservers' in group_names" + # Specific restic commands - name: Execute specific restic commands ansible.builtin.include_tasks: restic.yml diff --git a/roles/munin_client/tasks/nsd.yml b/roles/munin_client/tasks/nsd.yml new file mode 100644 index 0000000..b06cc35 --- /dev/null +++ b/roles/munin_client/tasks/nsd.yml @@ -0,0 +1,21 @@ +--- + +- name: Put nsd plugin configuration + ansible.builtin.template: + src: nsd.j2 + dest: /etc/munin/plugin-conf.d/nsd + owner: root + group: root + mode: "0o640" + notify: + - Restart munin-node + +- name: Put nsd scripts + ansible.builtin.copy: + src: files/nsd + dest: /etc/munin/plugins/nsd + owner: root + group: root + mode: "0o755" + notify: + - Restart munin-node diff --git a/roles/munin_client/templates/nsd.j2 b/roles/munin_client/templates/nsd.j2 new file mode 100644 index 0000000..14b746c --- /dev/null +++ b/roles/munin_client/templates/nsd.j2 @@ -0,0 +1,2 @@ +[nsd] +user root diff --git a/roles/nsd/defaults/main.yml b/roles/nsd/defaults/main.yml new file mode 100644 index 0000000..fc1d01b --- /dev/null +++ b/roles/nsd/defaults/main.yml @@ -0,0 +1,3 @@ +--- + +nsd_master: false diff --git a/roles/nsd/handlers/main.yml b/roles/nsd/handlers/main.yml new file mode 100644 index 0000000..30bbd62 --- /dev/null +++ b/roles/nsd/handlers/main.yml @@ -0,0 +1,11 @@ +--- + +- name: Restart nsd + ansible.builtin.service: + name: nsd + state: restarted + +- name: Restart systemd-resolved + ansible.builtin.service: + name: systemd-resolved + state: restarted diff --git a/roles/nsd/tasks/cron.yml b/roles/nsd/tasks/cron.yml new file mode 100644 index 0000000..bbf4f7d --- /dev/null +++ b/roles/nsd/tasks/cron.yml @@ -0,0 +1,18 @@ +--- + +- name: Install cron script + ansible.builtin.template: + src: resignall.sh.j2 + dest: "{{ nsd_cron_script }}" + owner: root + group: root + mode: "0o750" + +- name: Install cron + ansible.builtin.cron: + name: "NSD zone resign" + hour: "3" + minute: "2" + weekday: "3" + job: "{{ nsd_cron_script }} &> /dev/null" + state: present diff --git a/roles/nsd/tasks/main.yml b/roles/nsd/tasks/main.yml new file mode 100644 index 0000000..857f074 --- /dev/null +++ b/roles/nsd/tasks/main.yml @@ -0,0 +1,68 @@ +--- + +- name: Install & check prerequisites + ansible.builtin.include_tasks: prerequisites.yml + +- name: Create slave group + ansible.builtin.group_by: + key: slave_nsdservers + when: not nsd_master + +- name: Create master group + ansible.builtin.group_by: + key: master_nsdservers + when: nsd_master + +- name: Create zone dir + ansible.builtin.file: + path: "{{ nsd_default_etc_path }}zones" + owner: nsd + group: nsd + mode: "0o755" + state: directory + +- name: Create key dir + ansible.builtin.file: + path: "{{ nsd_default_etc_path }}keys" + owner: nsd + group: nsd + mode: "0o700" + state: directory + +- name: Create nsd.conf + ansible.builtin.template: + src: nsd.conf.j2 + dest: "{{ nsd_default_etc_path }}nsd.conf" + owner: root + group: root + mode: "0o640" + notify: + - Restart nsd + +- name: Create each zone in NSD + ansible.builtin.template: + src: zone.j2 + dest: "{{ nsd_default_etc_path }}nsd.conf.d/{{ item.name }}.conf" + owner: root + group: root + mode: "0o644" + loop: "{{ zones }}" + notify: + - Restart nsd + +- name: Force zone reload + ansible.builtin.meta: flush_handlers + +- name: Create zone and reload + ansible.builtin.include_tasks: zones.yml + loop: "{{ zones }}" + when: nsd_master + +- name: Install renew cron + ansible.builtin.include_tasks: cron.yml + when: nsd_master + +- name: Ensure nsd is started + ansible.builtin.service: + name: nsd + state: started diff --git a/roles/nsd/tasks/prerequisites.yml b/roles/nsd/tasks/prerequisites.yml new file mode 100644 index 0000000..9315d1e --- /dev/null +++ b/roles/nsd/tasks/prerequisites.yml @@ -0,0 +1,30 @@ +--- + +- name: Gather facts on listening ports + community.general.listen_ports_facts: + +- name: Detect systemd-resolve + ansible.builtin.set_fact: + _systemd_resolve_enable: "{{ ansible_facts.udp_listen | selectattr('port', 'eq', 53) | selectattr('name', 'eq', 'systemd-resolve') | count > 0 }}" + +- name: Deactivate DNS stublistener + ansible.builtin.lineinfile: + path: /etc/systemd/resolved.conf + regex: '^#DNSStubListener=yes' + line: DNSStubListener=no + when: _systemd_resolve_enable + notify: + - Restart systemd-resolved + +- name: Force restart for stub resolver + ansible.builtin.meta: flush_handlers + +- name: Install nsd & utilities + ansible.builtin.package: + name: + - nsd + - dnsutils + - ldnsutils + - cron + state: present + update_cache: true diff --git a/roles/nsd/tasks/zones.yml b/roles/nsd/tasks/zones.yml new file mode 100644 index 0000000..6c92505 --- /dev/null +++ b/roles/nsd/tasks/zones.yml @@ -0,0 +1,56 @@ +--- + +- name: Create zone file + ansible.builtin.template: + src: "{{ 'zones/parking.zone.j2' if item.parking | default(false) else 'zones/' ~ item.name ~ '.zone.j2' }}" + dest: "{{ nsd_default_etc_path }}zones/{{ item.name }}.zone" + owner: nsd + group: nsd + mode: "0o644" + vars: + dns_serial: "{{ ansible_date_time.epoch }}" + web_hostname_block: |- + {% for webserver in groups['webservers'] | sort -%} + {% for web_hostname in (hostvars[webserver]['web_hostname'] | selectattr('host', 'match', '.+' ~ item.name) | sort(attribute='host')) -%} + {{ web_hostname.host | regex_replace('\.' ~ item.name ~ '$', '') }} IN CNAME {{ hostvars[webserver].ansible_host }}. + {% endfor %} + {% endfor %} + +- name: Create zone key dir + ansible.builtin.file: + path: "{{ nsd_default_etc_path }}keys/{{ item.name }}/" + owner: nsd + group: nsd + mode: "0o750" + state: directory + +- name: Create the associated keys + become: true + become_user: nsd + ansible.builtin.command: + cmd: "ldns-keygen -a ECDSAP256SHA256 -k -s {{ item.name }}" + chdir: "{{ nsd_default_etc_path }}/keys/{{ item.name }}/" + creates: "{{ nsd_default_etc_path }}/keys/{{ item.name }}/.ds" + +- name: Check zone file + ansible.builtin.command: + cmd: "nsd-checkzone {{ item.name }} {{ nsd_default_etc_path }}zones/{{ item.name }}.zone" + changed_when: false + +- name: Stat associated keys + ansible.builtin.stat: + path: "{{ nsd_default_etc_path }}/keys/{{ item.name }}/.ds" + register: _stat_keys + +- name: Sign zone file + become: true + become_user: nsd + ansible.builtin.command: + chdir: "{{ nsd_default_etc_path }}/keys/{{ item.name }}/" + cmd: "ldns-signzone -o {{ item.name }} -u {{ nsd_default_etc_path }}/zones/{{ item.name }}.zone {{ (_stat_keys.stat.lnk_target | split('.'))[:-1] | join('.') }}" + changed_when: true + +- name: Reload zone + ansible.builtin.command: + cmd: "nsd-control reload {{ item.name }}" + changed_when: false diff --git a/roles/nsd/templates/nsd.conf.j2 b/roles/nsd/templates/nsd.conf.j2 new file mode 100644 index 0000000..265e07a --- /dev/null +++ b/roles/nsd/templates/nsd.conf.j2 @@ -0,0 +1,11 @@ +key: + name: "{{ nsd_tsig_key_name }}" + algorithm: hmac-sha256 + secret: "{{ tsig_key }}" + +server: + log-only-syslog: yes + hide-version: yes + zonesdir: "/etc/nsd/zones" + +include: "/etc/nsd/nsd.conf.d/*.conf" diff --git a/roles/nsd/templates/resignall.sh.j2 b/roles/nsd/templates/resignall.sh.j2 new file mode 100644 index 0000000..5e8cecd --- /dev/null +++ b/roles/nsd/templates/resignall.sh.j2 @@ -0,0 +1,17 @@ +#!/bin/bash + +for i in {{ nsd_default_etc_path }}keys/*/*.ds +do + # Get the different names + FILENAME=${i##*/} + KEYNAME=${FILENAME/.ds/} + DIRPATH=${i/${FILENAME}/} + _ZONEFILEPATH=${DIRPATH/keys/zones} + ZONEFILEPATH=${_ZONEFILEPATH%/*}.zone + _ZONENAME=${_ZONEFILEPATH%/*} + ZONENAME=${_ZONENAME##*/} + + cd $DIRPATH + sudo -u nsd /usr/bin/ldns-signzone -o ${ZONENAME} -u ${ZONEFILEPATH} ${KEYNAME} + /usr/sbin/nsd-control reload ${ZONENAME} +done diff --git a/roles/nsd/templates/zone.j2 b/roles/nsd/templates/zone.j2 new file mode 100644 index 0000000..3c9c776 --- /dev/null +++ b/roles/nsd/templates/zone.j2 @@ -0,0 +1,23 @@ +{% set other_server = groups['slave_nsdservers'] if nsd_master else (groups['master_nsdservers'] | first) -%} +{% set default_ipv4 = hostvars[other_server].ansible_default_ipv4.address -%} +{% set default_ipv6 = hostvars[other_server].ansible_default_ipv6.address -%} +zone: + name: "{{ item.name }}" + zonefile: {{ item.name }}.zone.signed + {% if nsd_master -%} + {% for server in other_server -%} + {% set default_ipv4 = hostvars[server].natted_ipv4 | default(hostvars[server].ansible_default_ipv4.address) -%} + {% set default_ipv6 = hostvars[server].ansible_default_ipv6.address -%} + notify: {{ default_ipv4 }} {{ nsd_tsig_key_name }} + provide-xfr: {{ default_ipv4 }} {{ nsd_tsig_key_name }} + notify: {{ default_ipv6 }} {{ nsd_tsig_key_name }} + provide-xfr: {{ default_ipv6 }} {{ nsd_tsig_key_name }} + {% endfor -%} + {% else -%} + {% set default_ipv4 = hostvars[other_server].natted_ipv4 | default(hostvars[other_server].ansible_default_ipv4.address) -%} + {% set default_ipv6 = hostvars[other_server].ansible_default_ipv6.address -%} + allow-notify: {{ default_ipv4 }} {{ nsd_tsig_key_name }} + request-xfr: {{ default_ipv4 }} {{ nsd_tsig_key_name }} + allow-notify: {{ default_ipv6 }} {{ nsd_tsig_key_name }} + request-xfr: {{ default_ipv6 }} {{ nsd_tsig_key_name }} + {% endif -%} diff --git a/roles/nsd/templates/zones/giteu.be.zone.j2 b/roles/nsd/templates/zones/giteu.be.zone.j2 new file mode 100644 index 0000000..b17f299 --- /dev/null +++ b/roles/nsd/templates/zones/giteu.be.zone.j2 @@ -0,0 +1,20 @@ +$TTL 86400 +@ IN SOA {{ groups['master_nsdservers'] | first }}. tech.ovh.net. ( + {{ dns_serial }}; timestamp serial number + 28800; Refresh + 7200; Retry + 864000; Expire + 86400; Min TTL + ) + +{% for server in groups['nsdservers'] %} +@ IN NS {{ hostvars[server].ansible_host }}. +{% endfor %} + +$ORIGIN {{ item.name }}. +@ IN CAA 0 issue ";" +@ IN MX 0 . +@ IN TXT "v=spf1 -all" +@ IN TXT "spf2.0/mfrom -all" +_dmarc IN TXT "v=DMARC1;p=reject;pct=100;sp=reject;aspf=s;" +{{ web_hostname_block }} diff --git a/roles/nsd/templates/zones/libertus.eu.zone.j2 b/roles/nsd/templates/zones/libertus.eu.zone.j2 new file mode 100644 index 0000000..b1b1736 --- /dev/null +++ b/roles/nsd/templates/zones/libertus.eu.zone.j2 @@ -0,0 +1,31 @@ +$TTL 86400 +@ IN SOA {{ groups['master_nsdservers'] | first }}. tech.ovh.net. ( + {{ dns_serial }}; timestamp serial number + 28800; Refresh + 7200; Retry + 864000; Expire + 86400; Min TTL + ) + +{% for server in groups['nsdservers'] %} +@ IN NS {{ hostvars[server].ansible_host }}. +{% endfor %} + +$ORIGIN {{ item.name }}. +@ IN CAA 0 issue "letsencrypt.org" +@ IN MX 1 mail.dmz.mateu.be. +@ 3600 IN TXT "v=spf1 mx a:ks3370405.kimsufi.com -all" +@ 3600 IN TXT "spf2.0/mfrom mx a:ks3370405.kimsufi.com -all" +_dmarc 3600 IN TXT "v=DMARC1; p=reject; rua=mailto:report@mateu.be; adkim=s; aspf=s" +dkim._domainkey 3600 IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv3kGIw5015Q35LLbkGwaBE+wC0PseodezDdkoGwzRsazEWINv1bg0mCIjtDbXLpv5VgRSynRyB+764i15DoFJp6mabcHlXxQVBWMClAtCJ9+Fn6SEwQjFbQeuFVQKH3xMwIq0S+ggP7qhFTaiLBn909Fi8oEMXGvqbBSlvoaeJwIDAQAB" +_jabber._tcp IN SRV 0 0 5269 jabber.dmz.mateu.be. +_xmpp-client._tcp IN SRV 0 0 5222 jabber.dmz.mateu.be. +_xmpp-server._tcp IN SRV 0 0 5269 jabber.dmz.mateu.be. +_xmppconnect IN TXT "_xmpp-client-xbosh=https://xmpp.libertus.eu/http-bind" +altsrv IN CNAME ks3370405.kimsufi.com. +p IN MX 1 mail.dmz.mateu.be. +p 3600 IN TXT "v=spf1 mx a:ks3370405.kimsufi.com -all" +p 3600 IN TXT "spf2.0/mfrom mx a:ks3370405.kimsufi.com -all" +_dmarc.p 3600 IN TXT "v=DMARC1; p=reject; rua=mailto:report@mateu.be; adkim=s; aspf=s" +dkim._domainkey.p 3600 IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv3kGIw5015Q35LLbkGwaBE+wC0PseodezDdkoGwzRsazEWINv1bg0mCIjtDbXLpv5VgRSynRyB+764i15DoFJp6mabcHlXxQVBWMClAtCJ9+Fn6SEwQjFbQeuFVQKH3xMwIq0S+ggP7qhFTaiLBn909Fi8oEMXGvqbBSlvoaeJwIDAQAB" +{{ web_hostname_block }} diff --git a/roles/nsd/templates/zones/mateu.be.zone.j2 b/roles/nsd/templates/zones/mateu.be.zone.j2 new file mode 100644 index 0000000..6016194 --- /dev/null +++ b/roles/nsd/templates/zones/mateu.be.zone.j2 @@ -0,0 +1,54 @@ +$TTL 86400 +@ IN SOA {{ groups['master_nsdservers'] | first }}. tech.ovh.net. ( + {{ dns_serial }}; timestamp serial number + 28800; Refresh + 7200; Retry + 864000; Expire + 86400; Min TTL + ) + +{% for server in groups['nsdservers'] %} +@ IN NS {{ hostvars[server].ansible_host | regex_replace('^([a-z0-9-]+)\\.', '\\1-v4.') if hostvars[server].ansible_host.endswith('dmz.mateu.be') else hostvars[server].ansible_host }}. +{% endfor %} + +$ORIGIN {{ item.name }}. +@ IN CAA 0 issue "letsencrypt.org" +@ IN MX 1 mail.dmz.mateu.be. +@ 3600 IN TXT "v=spf1 mx a:ks3370405.kimsufi.com -all" +@ 3600 IN TXT "spf2.0/mfrom mx a:ks3370405.kimsufi.com -all" +_dmarc 3600 IN TXT "v=DMARC1; p=reject; rua=mailto:report@mateu.be; adkim=s; aspf=s" +dkim._domainkey 3600 IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv3kGIw5015Q35LLbkGwaBE+wC0PseodezDdkoGwzRsazEWINv1bg0mCIjtDbXLpv5VgRSynRyB+764i15DoFJp6mabcHlXxQVBWMClAtCJ9+Fn6SEwQjFbQeuFVQKH3xMwIq0S+ggP7qhFTaiLBn909Fi8oEMXGvqbBSlvoaeJwIDAQAB" +libertus.eu._report._dmarc 3600 IN TXT "v=DMARC1;" +nintendojo.fr._report._dmarc 3600 IN TXT "v=DMARC1;" +p.libertus.eu._report._dmarc 3600 IN TXT "v=DMARC1;" +altsrv IN CNAME ks3370405.kimsufi.com. +backup IN A 10.233.212.60 +baybay-ponay IN AAAA 2a01:e0a:9bd:2810:9e6b:ff:fe13:ef88 +ciol IN A 109.190.68.133 +derdriu IN A 10.233.212.77 +dom IN A 10.233.212.15 +enbarr.dmz IN AAAA 2a01:e0a:9bd:2811::50 +evse IN A 10.233.211.198 +fc IN A 10.233.211.194 +frederica.dmz IN A {{ global_public_ip_address }} +frederica.dmz IN AAAA 2a01:e0a:9bd:2811::60 +ftp IN A 10.233.212.14 +garreg-mach IN A 10.233.212.66 +imprimante IN A 10.233.212.94 +machinbox IN A {{ global_public_ip_address }} +machinbox IN AAAA 2a01:e0a:9bd:2810::1 +mailalt IN CNAME altsrv +memcardprogc IN A 10.233.211.199 +nfs IN A 10.233.212.60 +rb IN A 194.156.203.253 +rc IN A 10.233.211.195 +serenor.dmz IN A {{ global_public_ip_address }} +serenor.dmz IN AAAA 2a01:e0a:9bd:2811::59 +{% for proxmox_host in groups['proxmox_all_lxc'] + groups['proxmox_all_running'] | sort %} +{{ proxmox_host }}.dmz IN A {{ global_public_ip_address }} +{% if proxmox_host.startswith('dns') %} +{{ proxmox_host }}-v4.dmz IN A {{ global_public_ip_address }} +{% endif %} +{{ proxmox_host }}.dmz IN AAAA {{ hostvars[proxmox_host].proxmox_net0.ip6 | ansible.utils.ipaddr('address') }} +{% endfor %} +{{ web_hostname_block }} diff --git a/roles/nsd/templates/zones/nintendojo.fr.zone.j2 b/roles/nsd/templates/zones/nintendojo.fr.zone.j2 new file mode 100644 index 0000000..951073d --- /dev/null +++ b/roles/nsd/templates/zones/nintendojo.fr.zone.j2 @@ -0,0 +1,23 @@ +$TTL 86400 +@ IN SOA {{ groups['master_nsdservers'] | first }}. tech.ovh.net. ( + {{ dns_serial }}; timestamp serial number + 28800; Refresh + 7200; Retry + 864000; Expire + 86400; Min TTL + ) + +{% for server in groups['nsdservers'] %} +@ IN NS {{ hostvars[server].ansible_host }}. +{% endfor %} + +$ORIGIN {{ item.name }}. +@ IN CAA 0 issue "letsencrypt.org" +@ IN MX 1 mail.dmz.mateu.be. +@ 3600 IN TXT "v=spf1 mx a:ks3370405.kimsufi.com -all" +@ 3600 IN TXT "spf2.0/mfrom mx a:ks3370405.kimsufi.com -all" +@ 3600 IN TXT "google-site-verification=rIe1fnrQnv-E1H8qsMtEIhM4XYUqCELshWH9pHkwPBI" +_dmarc 3600 IN TXT "v=DMARC1; p=reject; rua=mailto:report@mateu.be; adkim=s; aspf=s" +dkim._domainkey 3600 IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv3kGIw5015Q35LLbkGwaBE+wC0PseodezDdkoGwzRsazEWINv1bg0mCIjtDbXLpv5VgRSynRyB+764i15DoFJp6mabcHlXxQVBWMClAtCJ9+Fn6SEwQjFbQeuFVQKH3xMwIq0S+ggP7qhFTaiLBn909Fi8oEMXGvqbBSlvoaeJwIDAQAB" +mumble IN CNAME voice1.dmz.mateu.be. +{{ web_hostname_block }} diff --git a/roles/nsd/templates/zones/nintendojofr.com.zone.j2 b/roles/nsd/templates/zones/nintendojofr.com.zone.j2 new file mode 100644 index 0000000..9fa4abb --- /dev/null +++ b/roles/nsd/templates/zones/nintendojofr.com.zone.j2 @@ -0,0 +1,20 @@ +$TTL 86400 +@ IN SOA {{ groups['master_nsdservers'] | first }}. tech.ovh.net. ( + {{ dns_serial }}; timestamp serial number + 28800; Refresh + 7200; Retry + 864000; Expire + 86400; Min TTL + ) + +{% for server in groups['nsdservers'] %} +@ IN NS {{ hostvars[server].ansible_host }}. +{% endfor %} + +$ORIGIN {{ item.name }}. +@ IN CAA 0 issue "letsencrypt.org" +@ IN MX 0 . +@ IN TXT "v=spf1 -all" +@ IN TXT "spf2.0/mfrom -all" +_dmarc IN TXT "v=DMARC1;p=reject;pct=100;sp=reject;aspf=s;" +{{ web_hostname_block }} diff --git a/roles/nsd/templates/zones/parking.zone.j2 b/roles/nsd/templates/zones/parking.zone.j2 new file mode 100644 index 0000000..fb0f0e9 --- /dev/null +++ b/roles/nsd/templates/zones/parking.zone.j2 @@ -0,0 +1,19 @@ +$TTL 86400 +@ IN SOA {{ groups['master_nsdservers'] | first }}. tech.ovh.net. ( + {{ dns_serial }}; timestamp serial number + 28800; Refresh + 7200; Retry + 864000; Expire + 86400; Min TTL + ) + +{% for server in groups['nsdservers'] %} +@ IN NS {{ hostvars[server].ansible_host }}. +{% endfor %} + +$ORIGIN {{ item.name }}. +@ IN CAA 0 issue ";" +@ IN MX 0 . +@ IN TXT "v=spf1 -all" +@ IN TXT "spf2.0/mfrom -all" +_dmarc IN TXT "v=DMARC1;p=reject;pct=100;sp=reject;aspf=s;" diff --git a/roles/nsd/vars/main.yml b/roles/nsd/vars/main.yml new file mode 100644 index 0000000..3cb5fe8 --- /dev/null +++ b/roles/nsd/vars/main.yml @@ -0,0 +1,5 @@ +--- + +nsd_default_etc_path: "/etc/nsd/" +nsd_tsig_key_name: "tsig0" +nsd_cron_script: /usr/local/bin/resignall.sh diff --git a/roles/ufw/tasks/main.yml b/roles/ufw/tasks/main.yml index a3bb8f2..fd8f6db 100644 --- a/roles/ufw/tasks/main.yml +++ b/roles/ufw/tasks/main.yml @@ -34,6 +34,11 @@ src: "{{ item }}" loop: "{{ ufw_allowed_smtp_ips }}" +- name: Allow incoming DNS + community.general.ufw: + rule: allow + port: domain + - name: Set logging community.general.ufw: logging: "on"