diff options
Diffstat (limited to 'roles/dns')
| -rw-r--r-- | roles/dns/handlers/main.yaml | 6 | ||||
| -rw-r--r-- | roles/dns/tasks/check_dns_setup.yaml | 13 | ||||
| -rw-r--r-- | roles/dns/tasks/main.yaml | 3 | ||||
| -rw-r--r-- | roles/dns/tasks/setup_adblock.yaml | 66 | ||||
| -rw-r--r-- | roles/dns/tasks/setup_unbound.yaml | 44 | ||||
| -rw-r--r-- | roles/dns/templates/hostname.vether0.j2 | 1 | ||||
| -rw-r--r-- | roles/dns/templates/resolv.conf.j2 | 6 | ||||
| -rw-r--r-- | roles/dns/templates/unbound.conf.j2 | 41 |
8 files changed, 180 insertions, 0 deletions
diff --git a/roles/dns/handlers/main.yaml b/roles/dns/handlers/main.yaml new file mode 100644 index 00000000..cb476298 --- /dev/null +++ b/roles/dns/handlers/main.yaml @@ -0,0 +1,6 @@ +--- +- name: restart_unbound + ansible.builtin.service: + name: unbound + state: restarted + enabled: true diff --git a/roles/dns/tasks/check_dns_setup.yaml b/roles/dns/tasks/check_dns_setup.yaml new file mode 100644 index 00000000..b1fdb500 --- /dev/null +++ b/roles/dns/tasks/check_dns_setup.yaml @@ -0,0 +1,13 @@ +--- +- name: "check if adblock.rpz exists" + ansible.builtin.stat: + path: /var/unbound/db/adblock.rpz + register: adblock_rpz + +- name: "setup dns resolver (unbound)" + ansible.builtin.include_tasks: setup_unbound.yaml + when: not adblock_rpz.stat.exists + +- name: "setup adblocking" + ansible.builtin.include_tasks: setup_adblock.yaml + when: not adblock_rpz.stat.exists diff --git a/roles/dns/tasks/main.yaml b/roles/dns/tasks/main.yaml new file mode 100644 index 00000000..27978e73 --- /dev/null +++ b/roles/dns/tasks/main.yaml @@ -0,0 +1,3 @@ +--- +- name: "check dns resolver setup" + ansible.builtin.include_tasks: check_dns_setup.yaml diff --git a/roles/dns/tasks/setup_adblock.yaml b/roles/dns/tasks/setup_adblock.yaml new file mode 100644 index 00000000..edf09a7e --- /dev/null +++ b/roles/dns/tasks/setup_adblock.yaml @@ -0,0 +1,66 @@ +--- +- name: "activate unbound control" + ansible.builtin.command: unbound-control-setup + changed_when: false + +- name: "fetch unbound filter script" + ansible.builtin.get_url: + url: https://geoghegan.ca/pub/unbound-adblock/latest/unbound-adblock.sh + dest: /usr/local/bin/unbound-adblock + group: bin + mode: 755 + register: adblock_changed + # DL fails from time to time, so we retry a couple times + until: adblock_changed.state == "file" + retries: 10 + delay: 2 + ignore_errors: yes + notify: + - restart_unbound + +- name: "create adblock user" + ansible.builtin.user: + name: _adblock + shell: nologin + home: /var/empty + create_home: false + +- name: "add _adblock doas privileges" + ansible.builtin.blockinfile: + path: /etc/doas.conf + create: true + backup: true + marker: "### REACTANCE - Unbound Adblock - {mark} ###" + insertafter: "EOF" + block: | + permit nopass root + permit nopass _adblock cmd /usr/sbin/unbound-control args -q status + permit nopass _adblock cmd /usr/sbin/unbound-control args -q flush_zone unbound-adblock + permit nopass _adblock cmd /usr/sbin/unbound-control args -q auth_zone_reload unbound-adblock + +- name: "create binaries for adblock" + ansible.builtin.command: "{{ item }}" + loop: + - install -m 644 -o _adblock -g wheel /dev/null /var/unbound/db/adblock.rpz + - install -d -o root -g wheel -m 755 /var/log/unbound-adblock + - install -o _adblock -g wheel -m 640 /dev/null /var/log/unbound-adblock/unbound-adblock.log + - install -o _adblock -g wheel -m 640 /dev/null /var/log/unbound-adblock/unbound-adblock.log.0.gz + changed_when: false + notify: restart_unbound + +- name: "restarting adblock (as separate task otherwise cant create rule)" + ansible.builtin.service: + name: unbound + state: restarted + enabled: true + +- name: "create first ruleset" + ansible.builtin.shell: "cd /var/unbound/db && doas -u _adblock /usr/local/bin/unbound-adblock -O openbsd" + changed_when: false + +- name: "setup daily cronjob" + ansible.builtin.cron: + name: "update dns blocklist" + user: root + job: "cd /var/unbound/db && doas -u _adblock /usr/local/bin/unbound-adblock -O openbsd 1> /dev/null" + special_time: daily diff --git a/roles/dns/tasks/setup_unbound.yaml b/roles/dns/tasks/setup_unbound.yaml new file mode 100644 index 00000000..ec6f123e --- /dev/null +++ b/roles/dns/tasks/setup_unbound.yaml @@ -0,0 +1,44 @@ +--- +- name: "template out configs" + ansible.builtin.template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + loop: + - src: unbound.conf.j2 + dest: /var/unbound/etc/unbound.conf + - src: resolv.conf.j2 + dest: /etc/resolv.conf.j2 + - src: hostname.vether0.j2 + dest: /etc/hostname.vether0 + # we need a separate virtual network interface for binding the dns resolver to since ocserv doesn't creates tunnel interface for each separate connected client, it does not create a primary interface + + # unbound will fail if there's nonexisting interface in config +- name: "create vether0 interface" + ansible.builtin.shell: "sh /etc/netstart vether0" + when: inventory_hostname in (groups['ocserv']|default([])) + (groups['all_vpns']|default([])) + +- name: "setup log file" + ansible.builtin.file: + path: /var/log/unbound.log + state: touch + mode: "0600" + + # pure convenience +- name: "obsd : dns : symlink it to /etc" + ansible.builtin.file: + src: /var/unbound/etc/unbound.conf + dest: /etc/unbound.conf + state: link + +- name: "obsd : dns : not exists. generate..." + ansible.builtin.command: /usr/sbin/unbound-anchor -a /var/unbound/db/root.key + args: + creates: /var/unbound/db/root.key + failed_when: false + +- name: "obsd : dns : get root hints" + ansible.builtin.command: ftp -o /var/unbound/etc/root.hints https://www.internic.net/domain/named.root + args: + creates: /var/unbound/db/root.key + notify: + - restart_unbound diff --git a/roles/dns/templates/hostname.vether0.j2 b/roles/dns/templates/hostname.vether0.j2 new file mode 100644 index 00000000..e7ac2c71 --- /dev/null +++ b/roles/dns/templates/hostname.vether0.j2 @@ -0,0 +1 @@ +inet {{ (ocserv_network|default("172.16.16.0/24"))|ansible.utils.nthhost(2) }}/{{ (ocserv_network|default("172.16.16.0/24")|ipaddr('prefix')) }} diff --git a/roles/dns/templates/resolv.conf.j2 b/roles/dns/templates/resolv.conf.j2 new file mode 100644 index 00000000..7a0de7f4 --- /dev/null +++ b/roles/dns/templates/resolv.conf.j2 @@ -0,0 +1,6 @@ +{% if not disable_dns|default(false) %} +nameserver 127.0.0.1 +{% endif %} +nameserver 9.9.9.9 +nameserver 149.112.112.112 +lookup file bind diff --git a/roles/dns/templates/unbound.conf.j2 b/roles/dns/templates/unbound.conf.j2 new file mode 100644 index 00000000..b02df37e --- /dev/null +++ b/roles/dns/templates/unbound.conf.j2 @@ -0,0 +1,41 @@ +server: + interface: 127.0.0.1 +{% if inventory_hostname in (groups['ocserv']|default([])) + (groups['all_vpns']|default([])) %} + interface: {{ (ocserv_network|default("172.16.16.0/24"))|ansible.utils.nthhost(2) }} +{% endif %} + do-ip6: no + + access-control: 0.0.0.0/0 refuse + access-control: 127.0.0.0/8 allow +{% if inventory_hostname in (groups['ocserv']|default([])) + (groups['all_vpns']|default([])) %} + access-control: {{ ocserv_network|default("172.16.16.0/24") }} allow +{% endif %} + + hide-identity: yes + hide-version: yes + + auto-trust-anchor-file: "/var/unbound/db/root.key" + val-log-level: 2 + qname-minimisation: yes + + aggressive-nsec: yes + verbosity: 1 + log-queries: no + use-caps-for-id: yes + + cache-min-ttl: 3600 + cache-max-ttl: 86400 + prefetch: yes + unwanted-reply-threshold: 10000 + do-not-query-localhost: yes + val-clean-additional: yes + module-config: "respip validator iterator" + +remote-control: + control-enable: yes + +rpz: + name: "unbound-adblock" + zonefile: "/var/unbound/db/adblock.rpz" + rpz-log: no + rpz-log-name: "unbound-adblock" |
