Explorar el Código

start migration

Blaine Story hace 3 años
commit
27a8da99f0

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+galaxy_roles
+.vault-password

+ 11 - 0
ansible.cfg

@@ -0,0 +1,11 @@
+[defaults]
+inventory      = ./hosts.ini
+forks          = 20
+vault_password_file = ./.vault-password
+ansible_managed = This file is managed by Ansible. Any local changes may be wiped out!
+interpreter_python = auto_silent
+display_skipped_hosts = False
+roles_path = ./galaxy_roles:./roles
+
+[ssh_connection]
+pipelining = True

+ 20 - 0
git-init.sh

@@ -0,0 +1,20 @@
+#!/bin/bash
+# sets up a pre-commit hook to ensure that vault.yaml is encrypted
+#
+# credit goes to nick busey from homelabos for this neat little trick
+# https://gitlab.com/NickBusey/HomelabOS/-/issues/355
+
+if [ -d .git/ ]; then
+rm .git/hooks/pre-commit
+cat <<EOT >> .git/hooks/pre-commit
+if ( git show :vars/vault.yaml | grep -q "\$ANSIBLE_VAULT;" ); then
+echo "Vault Encrypted. Safe to commit."
+else
+echo "Vault not encrypted! Run 'make encrypt' and try again."
+exit 1
+fi
+EOT
+
+fi
+
+chmod +x .git/hooks/pre-commit

+ 85 - 0
group_vars/all.yml

@@ -0,0 +1,85 @@
+---
+# generic settings
+ansible_user: ansible
+ansible_ssh_private_key_file: ~/.ssh/ansible_ed25519
+
+main_username: container
+main_groupname: "{{ main_username }}"
+main_uid: 1558
+main_gid: 3333
+
+# ssh keys
+ssh_root_keys:
+  # Blaine iPhone
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAal21bS5ROtzWDy3Z45/Dg5WQbC4qEgpU2nMM+EZaZk homelan
+
+  # Blaine Shortcuts
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIINoR827FesLbphYJr9gX/gXGvrYY8ztZE3Y7Tgpt1UW Shortcuts on iPhone
+
+  # Blaine Fedora
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDqi3dVzfrkil7c00Zfx2WKS9Gn9UlXwLdPNU65BIMWJ blaine@t440s-fedora
+
+  # Blaine Arch
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKXvDJXDv7Q8ldaLbYngHVICebbzNnyN1ebKu+Hd4S2i blaine@t440s-arch
+
+  # Blaine NixOS
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ3EuQyNxeS+WRXDJ5fmVsNAgNI1bukBqJrT4yRqtqrN blaine@nixos-laptop
+
+  # NAS
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPL79uY7Z8JPCi35I+d4JsC/H7Liw+gLKbADaAmLhUHp root@nas
+
+  # Ricky Fedora
+  - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTuQQEhfITCS2h03BZYFL1dLgCVGcfZrbefX7c8HUfNDkghMpJa/31gu6e+ZX4qe4HmYxWmV30s2gbUJUq3OfIIxnQsIqyqe9vg1+mSqpmkB3saYtDVkvzxbWhCTxZaA+yCUV0bR7eakg8tjbm/F5DZ1rRKvK5plptMfQoeQytIzasySyZwE5pwp3yj4eq/JhiZQ307IlmdmFAyglkozU/r1h73yBWRQZxwl71mMGvnoNeCLhZltXmYlTBQpq2At1NtTMD6Mz0ZItsAp1TKy5lAZRZrqYudX5J8D+kayBpLcr/XwMcMycwzQqr1UYYlk2Ph7kzrKOgUt16U/EYqfib ricky@Herbert
+
+  # Ricky OnePlus
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEScwg88EUjtptpEyD2dmPu7f4+1wdCoxbYa/Vl8acTn u0_a462@localhost
+
+  # Ricky Ubuntu
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKO5FhPYJFFaWmnfTjo1Ud+PMDz81woiyLycHMF1POLO eric@SG-42
+  #- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf7cAHajeIQkJ+bjrAUUjU8aJ5KiEmAKDPhN9HiQpOt5dqA8o9OA+ONlTU3S5JjLuU6c5wgd7N6h0TIEfsy0Z83TS7CXu6GG4UsNXitrwvlcuNFK0vgQB54BRyXqtOLQ9LHuMmjP1qYKM5xW+aOyuC9nuKSCxbyg7VhotXVp2/w1OXMSZ00YzUjx6GBY/eJJ/9+7HdWSZJwBDKQMlIxVAzpmAhofD2oUjk1EGQMMv8COY2UGMuSSyHMpFsJ9qIYJhLLvwVvxSZLJAtG3vey177us2+TxDQwmJiZC3vNzaaeyCy1/nDQ55BcgmmvRxkMRfONCeZdIRDTumm2g2uVLZJ ricky@ricky-ThinkPad-T440
+
+  # Ricky Windows
+  - ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAidTGFyI1cg0DV2Qz12JOM4SgMs7biw+v5kdFZ+a4MyUU51w+dociPV1R8qjnN1mVlNbXzskJpivN5lEO2HuegIZCQvOhDfmGVqgtv+ibJTMKNdH3sJbhj3GWE58qhKri3jEnlyCnSYubkFrzfZn1GsKbBVDDu5ca6ySrejBE54ANugU53t5GCqOTX4q235i+Ye5YwJqd3HPfvs5n1f3oOqWVOtvj/kzpJeZcxlfLaJ435P07MGTTuV2eGyI47zrS4xkL+cw23bwCIQcvgJUyPW8GR1Dmc87lOVGAMLC4Bbi30NEp/sFmZI7aKcDxzDYjx2mIPjcmMlfn55SGHoSC6w== rsa-key-20190930
+
+  # Xen Laptop
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAEKAwnsNPz4pnlk043W66ZWrd1Dq4CYznBXIFhUmOIn xen@localhost.localdomain
+
+ssh_ansible_keys:
+  # Blaine Fedora Ansible
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHuSA9kN3cKawQrL4SFPPuGU9bZGUnJ2+O7hbYNEGcsw blaine@t440s-fedora
+
+  # Blaine Arch Ansible
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFRedECgniqSdFMULTTjdvCOHw+C1k1TGiepSCKt6fIl blaine@t440s-arch
+
+  # Blaine NixOS Ansible
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBqtr2EwVqJaO87RasHLEvBQgEUVYyl0h6PWt0LlmC+O blaine@nixos-laptop
+
+  # Ricky Ubuntu Ansible
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDsKlgd1Xnr00TGdGIYO6zIKsEu0vQRBncoSD+S8yDMJ ricky@ricky-ThinkPad-T440
+
+  # NAS
+  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJmyvKWjJLJl6755J9iMCneeaOGZhVvv9PWfwsG3Cl7i root@nas
+
+# backblaze b2 cloud backups
+b2_account_key: "{{ vaulted_b2_account_key }}"
+b2_key_id: "{{ vaulted_b2_key_id }}"
+b2_backups_bucket: "{{ vaulted_b2_backups_bucket }}"
+b2_container_data_bucket: "{{ vaulted_b2_container_data_bucket }}"
+b2_data_bucket: "{{ vaulted_b2_data_bucket }}"
+b2_music_bucket: "{{ vaulted_b2_music_bucket }}"
+b2_photos_bucket: "{{ vaulted_b2_photos_bucket }}"
+b2_backups_config_encryption_password: "{{ vaulted_b2_backups_config_encryption_password }}"
+b2_backups_config_encryption_salt: "{{ vaulted_b2_backups_config_encryption_salt }}"
+b2_container_data_encryption_password: "{{ vaulted_b2_container_data_encryption_password }}"
+b2_container_data_encryption_salt: "{{ vaulted_b2_container_data_encryption_salt }}"
+b2_data_config_encryption_password: "{{ vaulted_b2_data_config_encryption_password }}"
+b2_data_config_encryption_salt: "{{ vaulted_b2_data_config_encryption_salt }}"
+b2_music_config_encryption_password: "{{ vaulted_b2_music_config_encryption_password }}"
+b2_music_config_encryption_salt: "{{ vaulted_b2_music_config_encryption_salt }}"
+b2_photos_config_encryption_password: "{{ vaulted_b2_photos_config_encryption_password }}"
+b2_photos_config_encryption_salt: "{{ vaulted_b2_photos_config_encryption_salt }}"
+
+# wasabi cloud backups
+wasabi_access_key: "{{ vaulted_wasabi_access_key }}"
+wasabi_secret_access_key: "{{ vaulted_wasabi_secret_access_key }}"
+wasabi_backups_bucket: "{{ vaulted_wasabi_backups_bucket }}"

+ 165 - 0
group_vars/dhcp.yml

@@ -0,0 +1,165 @@
+---
+
+default_domain: "server.home"
+default_dns: 10.0.0.2
+default_lease: 600
+max_lease: 7200
+
+subnets:
+  - cidr: 10.0.0.0
+    netmask: 255.255.255.0
+    range_start: 10.0.0.100
+    range_end: 10.0.0.200
+    routers: 10.0.0.1
+    subnet_domain: "{{ default_domain }}"
+    subnet_default_lease: "{{ default_lease }}"
+    subnet_max_lease: "{{ max_lease }}"
+
+reservations:
+- type: default
+    name: gateway
+    mac: 1c:69:7a:0f:d3:a4
+    ip: 10.0.0.2
+
+  - type: default
+    name: netgearap
+    mac: 94:a6:7e:58:3a:9f
+    #mac: 10:da:43:8c:a3:13
+    ip: 10.0.0.3
+
+  - type: secured
+    name: nas
+    mac: fc:aa:14:86:9d:7b
+    ip: 10.0.0.4
+
+  - type: secured
+    name: kodimb
+    mac: e4:5f:01:4f:7c:74
+    ip: 10.0.0.5
+
+  - type: secured
+    name: kodilv
+    mac: dc:a6:32:b4:ed:be
+    ip: 10.0.0.6
+
+  - type: secured
+    name: kodijb
+    mac: dc:a6:32:69:fc:80
+    ip: 10.0.0.7
+
+  - type: default
+    name: tvheadend
+    mac: 00:11:2f:fd:52:ba
+    ip: 10.0.0.8
+
+  - type: secured
+    name: arm
+    mac: 10:bf:48:d4:d5:fc
+    ip: 10.0.0.9
+
+  - type: default
+    name: arm2 # don't know
+    mac: 00:25:4b:bc:cc:e0
+    ip: 10.0.0.10
+
+  - type: devnull
+    name: ipcameras
+    mac: 9c:8e:cd:2e:51:9c
+    ip: 10.0.0.11
+
+  - type: default
+    name: retropie
+    mac: b8:27:eb:42:71:dc
+    ip: 10.0.0.12
+
+  - type: default
+    name: kitchen
+    mac: 68:a3:c4:16:fb:74
+    ip: 10.0.0.15
+
+  - type: default
+    name: x10
+    mac: b8:27:eb:7c:f3:ff
+    ip: 10.0.0.16
+
+  - type: default
+    name: brother-print-server
+    mac: 80:1f:02:4a:cd:cf
+    ip: 10.0.0.17
+
+  - type: default
+    name: dellxps
+    mac: f0:1f:af:36:0c:48
+    ip: 10.0.0.19
+
+  - type: devnull
+    name: zoom
+    mac: 00:12:41:ba:5c:00
+    ip: 10.0.0.20
+
+  # Ricky's Camera joystick manually set to 10.0.0.21
+
+  # will set cameras to 10.0.0.30
+
+  - type: default
+    name: nixos-laptop
+    mac: 28:d2:44:d8:7f:95
+    ip: 10.0.0.40
+
+  # Ricky's new laptop wifi manually set to 10.0.0.41
+
+  # Ricky's old laptop manually set to 10.0.0.42
+
+  # Ricky's new laptop ethernet manually set to 10.0.0.43
+
+  - type: cloudflare
+    name: blaine-work-laptop
+    mac: 08:3a:88:57:ab:fa
+    ip: 10.0.0.45
+
+  - type: default
+    name: s7
+    mac: 8c:f5:a3:6a:55:f6
+    ip: 10.0.0.51
+
+  - type: default
+    name: t440s-ethernet
+    mac: 68:f7:28:21:36:60
+    ip: 10.0.0.52
+
+  - type: default
+    name: t440s-wifi
+    mac: a4:c4:94:df:2f:c3
+    ip: 10.0.0.53
+
+  - type: default
+    name: blaine-iphone
+    mac: f0:a3:5a:95:b4:cd
+    ip: 10.0.0.54
+
+  - type: default
+    name: blaine-iphone
+    mac: f0:a3:5a:95:b4:cd
+    ip: 10.0.0.54
+
+  - type: cloudflare
+    name: julie-macbook
+    mac: b8:8d:12:36:f1:16
+    ip: 10.0.0.90
+
+  # Ken is using 10.0.0.91
+
+  - type: devnull
+    name: cameradvr
+    mac: 00:12:41:12:e5:22
+    ip: 10.0.0.158
+
+  - type: devnull
+    name: backyard-camera
+    mac: 00:2a:2a:5c:06:9a
+    ip: 10.0.0.173
+
+  - type: default
+    name: netgear-switch1
+    mac: cc:40:d0:4c:3a:b6
+    ip: 10.0.0.254

+ 45 - 0
group_vars/heyu.yml

@@ -0,0 +1,45 @@
+---
+heyu_aliases:
+  - device: Cameras
+    type: StdAM
+    code: A1
+
+  - device: Lights
+    type: StdAM
+    code: A2
+
+  - device: RetroPieTV
+    type: StdAM
+    code: A3
+
+  - device: MediaCenter
+    type: StdAM
+    code: A4
+
+  - device: Bedroom-Fan
+    type: StdAM
+    code: A5
+
+  - device: LivingRoom-ChairLamp
+    type: StdLM
+    code: A6
+
+  - device: Overhead-Lights
+    type: StdAM
+    code: A7
+
+  - device: LR-Cameras
+    type: StdAM
+    code: A8
+
+  - device: Bedroom
+    type: ""
+    code: A1-5
+
+  - device: Fish
+    type: StdAM
+    code: A9
+
+  - device: LR-Fan
+    type: StdAM
+    code: A12

+ 34 - 0
hosts.ini

@@ -0,0 +1,34 @@
+#[bootstrap]
+# new hosts will go here once bootstrap role has been transferred
+
+[gateway]
+10.0.0.2
+
+[nas]
+nas
+
+[tvheadend]
+tvheadend
+
+[heyu]
+x10
+
+[kodi]
+kodilr
+kodimb
+kodijb
+
+[arm]
+arm
+
+[cloud]
+warchildstory.com
+shareunderware.com
+
+[kodi:vars]
+ansible_ssh_user=root
+
+#[weber]
+#weber-server
+#weber-kodi
+#weber-pi

+ 26 - 0
roles/name-resolution/README.md

@@ -0,0 +1,26 @@
+DHCP-Server
+===========
+
+An ansible role to install a working dhcp server (or update an existing dhcp server). It will install the necessary packgaes, open the firewall port, copy a working config, and start/enable the systemd service.
+
+Requirements
+------------
+
+A server that has already been bootstrapped for ansible administration.
+
+Role Variables
+--------------
+
+__dhcp_hosts__: DNS hostname or IP address of the host that will be acting as a dhcp server. Defaults to the ansible inventory group "bootstrap"
+
+Example Usage
+-------------
+
+To install/update the dhcp server settings:
+
+    ansible-playbook dhcp.yml
+
+License
+-------
+
+GPLv3

+ 2 - 0
roles/name-resolution/defaults/main.yml

@@ -0,0 +1,2 @@
+---
+dhcp_hosts: "bootstrap"

+ 19 - 0
roles/name-resolution/handlers/main.yml

@@ -0,0 +1,19 @@
+---
+- name: Reload systemd services
+  systemd:
+    daemon_reload: yes
+
+- name: Restart dhcpd
+  service:
+    name: dhcpd
+    state: restarted
+
+- name: Restart NetworkManager
+  systemd:
+    name: NetworkManager
+    state: restarted
+
+- name: Restart unbound
+  service:
+    name: unbound
+    state: restarted

+ 138 - 0
roles/name-resolution/tasks/main.yml

@@ -0,0 +1,138 @@
+---
+- name: Install dhcp & dns packages
+  dnf:
+    name:
+      - dhcp-server
+      - unbound
+    update_cache: no
+    state: present
+
+- name: Make services autorestart themselves on failure
+  template:
+    src: "{{ item }}.service.j2"
+    dest: /etc/systemd/system/{{ item }}.service
+    owner: root
+    group: root
+    mode: '0644'
+  loop:
+    - dhcpd
+    - unbound
+  notify:
+    - Restart {{ item }}
+    - Reload systemd services
+
+- name: Enable dhcpd and unbound services
+  systemd:
+    name: "{{ item }}"
+    enabled: yes
+  loop:
+    - dhcpd
+    - unbound
+
+- name: Set home as default zone
+  shell:
+    cmd: firewall-cmd --set-default-zone=home
+  register: setdefaultzone
+  changed_when: "'Warning: ZONE_ALREADY_SET' not in setdefaultzone.stderr"
+  failed_when: "'success' not in setdefaultzone.stdout"
+
+- name: Open ports
+  firewalld:
+    service: "{{ item }}"
+    zone: home
+    permanent: yes
+    state: enabled
+    immediate: yes
+  loop:
+    - dhcp
+    - dns
+
+- name: Copy dhcpd.conf
+  template:
+    src: dhcpd.conf.j2
+    dest: /etc/dhcp/dhcpd.conf
+    owner: root
+    group: root
+    mode: '0644'
+  notify:
+    - Restart dhcpd
+
+- name: Copy unbound.conf
+  template:
+    src: unbound.conf.j2
+    dest: /etc/unbound/unbound.conf
+    owner: root
+    group: unbound
+    mode: '0644'
+  notify:
+    - Restart unbound
+
+- name: Copy unbound resolution files
+  template:
+    src: "{{ item }}.j2"
+    dest: /etc/unbound/local.d/{{ item }}
+    owner: root
+    group: unbound
+    mode: '0640'
+  loop:
+    - lan-name-resolution.conf
+    - plug-onion-addresses.conf
+    - server.home.conf
+    - local.conf
+    - home-lan.conf
+  notify:
+    - Restart unbound
+
+- name: Check adblock config file
+  stat:
+    path: /etc/unbound/local.d/ad-servers.conf
+  register: adservers_conf
+
+- set_fact:
+    adservers_conf_age_in_days: "{{ (lookup('pipe', 'date +%s')|int - adservers_conf.stat.ctime|int) / 86400 }}"
+  when:
+    - adservers_conf.stat.exists
+
+- name: Download fresh adblock config
+  get_url:
+    url: 'https://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&mimetype=plaintext'
+    dest: /etc/unbound/local.d/ad-servers.conf
+    owner: root
+    group: unbound
+    mode: '0644'
+  when:
+    - not adservers_conf.stat.exists or adservers_conf_age_in_days|int > 30
+  notify:
+    - Restart unbound
+
+- name: Update /etc/hosts
+  template:
+    src: hosts.j2
+    dest: /etc/hosts
+    owner: root
+    group: root
+    mode: '0644'
+
+- set_fact:
+    ethernet: "{{ (ansible_interfaces | reject('search', 'podman') | list | sort)[0] }}"
+
+- name: Configure static IP on {{ ethernet }}
+  lineinfile:
+    path: /etc/sysconfig/network-scripts/ifcfg-{{ ethernet }}
+    regexp: "{{ item.regexp | default(omit) }}"
+    line: "{{ item.line }}"
+  loop:
+    - { regexp: 'BOOTPROTO=', line: 'BOOTPROTO="none"' }
+    - { regexp: 'IPADDR=', line: 'IPADDR="10.0.0.2"' }
+    - { regexp: 'PREFIX=', line: 'PREFIX="24"' }
+    - { regexp: 'GATEWAY=' ,line: 'GATEWAY="10.0.0.1"' }
+    - { regexp: 'DNS1=', line: 'DNS1="{{ dns_primary }}"' }
+    - { regexp: 'DNS2=', line: 'DNS2="{{ dns_secondary }}"' }
+    - { regexp: 'IPV4_FAILURE_FATAL=', line: 'IPV4_FAILURE_FATAL="yes"' }
+    - { regexp: 'IPV6INIT=', line: 'IPV6INIT="NO"' }
+    - { regexp: 'ZONE=', line: 'ZONE="home"' }
+  loop_control:
+    label: "{{ item.line }}"
+  notify:
+    - Restart NetworkManager
+

+ 70 - 0
roles/name-resolution/templates/dhcpd.conf.j2

@@ -0,0 +1,70 @@
+# {{ ansible_managed }}
+#
+# DHCP Server Configuration file.
+#   see /usr/share/doc/dhcp*/dhcpd.conf.example
+#   see dhcpd.conf(5) man page
+#
+
+authoritative;
+
+default-lease-time 43200; # 12 hours
+max-lease-time 86400;     # 24 hours
+
+option rfc3442-classless-static-routes code 121 = array of integer 8;
+option ms-classless-static-routes code 249 = array of integer 8;
+option rfc3442-classless-static-routes 24, 192, 168, 1, 10, 0, 0, 8, 0, 10, 0, 0, 1;
+option ms-classless-static-routes 24, 192, 168, 1, 10, 0, 0, 8, 0, 10, 0, 0, 1;
+
+subnet 10.0.0.0 netmask 255.255.255.0 {
+
+  option routers 10.0.0.1;
+
+  option domain-name-servers 10.0.0.2, {{ dns_primary }}, {{ dns_secondary }};
+
+  # WINS info for Windows capability
+  option netbios-name-servers 10.0.0.4;
+  option netbios-node-type 8; 
+
+  # Dynamic IPs
+  range 10.0.0.100 10.0.0.200;
+
+  class "secured" {
+    option routers 10.0.0.2;
+
+    # 192.168.1.0/24 thru 10.0.0.8, 10.0.0.2 as default route
+    option rfc3442-classless-static-routes 24, 192, 168, 1, 10, 0, 0, 8, 0, 10, 0, 0, 2;
+    option ms-classless-static-routes 24, 192, 168, 1, 10, 0, 0, 8, 0, 10, 0, 0, 2;
+
+    match hardware;
+  }
+
+  class "cloudflare" {
+    option domain-name-servers 1.1.1.3, 1.0.0.3; # cloudflare block malware + porn
+    
+    match hardware;
+  }
+
+  class "devnull" {
+    option domain-name-servers 127.0.0.1;
+
+    match hardware;
+  }
+
+  # nothing in here (yet)
+  class "default" {
+    match hardware;
+  }
+
+{% for node in nodes %}
+  subclass "{{ node.type }}" 1:{{ node.mac }}; # {{ node.name }}
+{% endfor %}
+
+{% for node in nodes %}
+  host {{ node.name }}
+  {
+    hardware ethernet {{ node.mac }};
+    fixed-address {{ node.ip }};
+  }
+
+{% endfor %}
+}

+ 19 - 0
roles/name-resolution/templates/dhcpd.service.j2

@@ -0,0 +1,19 @@
+[Unit]
+Description=DHCPv4 Server Daemon
+Documentation=man:dhcpd(8) man:dhcpd.conf(5)
+Wants=network-online.target
+After=network-online.target
+After=time-sync.target
+
+[Service]
+Type=notify
+EnvironmentFile=-/etc/sysconfig/dhcpd
+ExecStart=/usr/sbin/dhcpd -f -cf /etc/dhcp/dhcpd.conf -user dhcpd -group dhcpd --no-pid $DHCPDARGS
+StandardError=null
+Restart=on-failure
+RestartSec=5s
+StartLimitIntervalSec=30
+StartLimitBurst=5
+
+[Install]
+WantedBy=multi-user.target

+ 9 - 0
roles/name-resolution/templates/home-lan.conf.j2

@@ -0,0 +1,9 @@
+# {{ ansible_managed }}
+
+local-data: "home.lan A 10.0.0.4"
+local-data-ptr: "10.0.0.4 home.lan"
+
+{% for node in nodes %}
+local-data: "{{ node.name }}.home.lan A {{ node.ip }}"
+local-data-ptr: "{{ node.ip }} {{ node.name }}.home.lan"
+{% endfor %}

+ 8 - 0
roles/name-resolution/templates/hosts.j2

@@ -0,0 +1,8 @@
+127.0.0.1	localhost	localhost.localdomain	localhost4	localhost4.localdomain4
+::1		localhost	localhost.localdomain	localhost6	localhost6.localdomain6
+
+# BEGIN ANSIBLE MANAGED BLOCK
+{% for node in nodes %}
+{{ node.ip }}	{{ node.name }}	{{ node.name }}.home	{{ node.name }}.home.lan
+{% endfor %}
+# END ANSIBLE MANAGED BLOCK

+ 6 - 0
roles/name-resolution/templates/lan-name-resolution.conf.j2

@@ -0,0 +1,6 @@
+# {{ ansible_managed }}
+
+{% for node in nodes %}
+local-data: "{{ node.name }} A {{ node.ip }}"
+local-data-ptr: "{{ node.ip }} {{ node.name }}"
+{% endfor %}

+ 9 - 0
roles/name-resolution/templates/local.conf.j2

@@ -0,0 +1,9 @@
+# {{ ansible_managed }}
+
+local-data: "local A 10.0.0.4"
+local-data-ptr: "10.0.0.4 local"
+
+{% for node in nodes %}
+local-data: "{{ node.name }}.local A {{ node.ip }}"
+local-data-ptr: "{{ node.ip }} {{ node.name }}.local"
+{% endfor %}

+ 2 - 0
roles/name-resolution/templates/plug-onion-addresses.conf.j2

@@ -0,0 +1,2 @@
+local-zone: "onion." redirect
+local-data: "onion. A 127.0.0.1"

+ 12 - 0
roles/name-resolution/templates/server.home.conf.j2

@@ -0,0 +1,12 @@
+{% for node in nodes %}
+{% if node['name'] == 'nas' %}
+local-data: "server.home A {{ node['ip'] }}"
+local-data-ptr: "{{ node['ip'] }} server.home"
+local-data: "www.server.home A {{ node['ip'] }}"
+local-data-ptr: "{{ node['ip'] }} www.server.home"
+{% for service in heimdall_services %}
+local-data: "{{ service }}.server.home A {{ node['ip'] }}"
+local-data-ptr: "{{ node['ip'] }} {{ service }}.server.home"
+{% endfor %}
+{% endif %}
+{% endfor %}

+ 15 - 0
roles/name-resolution/templates/statusservices.j2

@@ -0,0 +1,15 @@
+#!/bin/bash
+# {{ ansible_managed }}
+
+declare -a arr=("openvpn-client@proton" "unbound" "dhcpd")
+
+for i in "${arr[@]}"; do
+  istatus=$(systemctl is-active $i)
+  format="%-28s \x1b[32m%s\x1b[0m\n" # green output by default
+
+  if [ "$istatus" != "active" ]; then
+    format="%-28s \x1b[31m%s\x1b[0m\n" # make red if service not active
+  fi
+
+  printf "$format" "$i:" "$istatus"
+done

+ 953 - 0
roles/name-resolution/templates/unbound.conf.j2

@@ -0,0 +1,953 @@
+server:
+
+	# verbosity number, 0 is least verbose. 1 is default.
+	verbosity: 1
+
+	# print statistics to the log (for every thread) every N seconds.
+	# Set to "" or 0 to disable. Default is disabled.
+	# Needs to be disabled for munin plugin
+	statistics-interval: 0
+
+	# enable shm for stats, default no.  if you enable also enable
+	# statistics-interval, every time it also writes stats to the
+	# shared memory segment keyed with shm-key.
+	# shm-enable: no
+
+	# shm for stats uses this key, and key+1 for the shared mem segment.
+	# shm-key: 11777
+
+	# enable cumulative statistics, without clearing them after printing.
+	# Needs to be disabled for munin plugin
+	statistics-cumulative: no
+
+	# enable extended statistics (query types, answer codes, status)
+	# printed from unbound-control. default off, because of speed.
+	# Needs to be enabled for munin plugin
+	extended-statistics: yes
+
+	# number of threads to create. 1 disables threading.
+	num-threads: 4
+
+	interface: 127.0.0.1
+  interface: {{ ansible_all_ipv4_addresses|sort|first }}
+
+	# for dns over tls and raw dns over port 80
+	# interface: 0.0.0.0@443
+	# interface: ::0@443
+	# interface: 0.0.0.0@80
+	# interface: ::0@80
+
+	# enable this feature to copy the source address of queries to reply.
+	# Socket options are not supported on all platforms. experimental.
+	# interface-automatic: yes
+	#
+	# NOTE: Enable this option when specifying interface 0.0.0.0 or ::0
+	# NOTE: Disabled per Fedora policy not to listen to * on default install
+	# NOTE: If deploying on non-default port, eg 80/443, this needs to be disabled
+	interface-automatic: no
+
+	# port to answer queries from
+	# port: 53
+
+	# specify the interfaces to send outgoing queries to authoritative
+	# server from by ip-address. If none, the default (all) interface
+	# is used. Specify every interface on a 'outgoing-interface:' line.
+	# outgoing-interface: 192.0.2.153
+	# outgoing-interface: 2001:DB8::5
+	# outgoing-interface: 2001:DB8::6
+	outgoing-interface: {{ ansible_default_ipv4.address }}
+
+	# Specify a netblock to use remainder 64 bits as random bits for
+	# upstream queries.  Uses freebind option (Linux).
+	# outgoing-interface: 2001:DB8::/64
+	# Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
+	# And: ip -6 route add local 2001:db8::/64 dev lo
+	# And set prefer-ip6: yes to use the ip6 randomness from a netblock.
+	# Set this to yes to prefer ipv6 upstream servers over ipv4.
+	# prefer-ip6: no
+
+	# number of ports to allocate per thread, determines the size of the
+	# port range that can be open simultaneously.  About double the
+	# num-queries-per-thread, or, use as many as the OS will allow you.
+	# outgoing-range: 4096
+
+	# permit unbound to use this port number or port range for
+	# making outgoing queries, using an outgoing interface.
+	# Only ephemeral ports are allowed by SElinux
+	outgoing-port-permit: 32768-60999
+
+	# deny unbound the use this of port number or port range for
+	# making outgoing queries, using an outgoing interface.
+	# Use this to make sure unbound does not grab a UDP port that some
+	# other server on this computer needs. The default is to avoid
+	# IANA-assigned port numbers.
+	# If multiple outgoing-port-permit and outgoing-port-avoid options
+	# are present, they are processed in order.
+	# Our SElinux policy does not allow non-ephemeral ports to be used
+	outgoing-port-avoid: 0-32767
+
+	# number of outgoing simultaneous tcp buffers to hold per thread.
+	# outgoing-num-tcp: 10
+
+	# number of incoming simultaneous tcp buffers to hold per thread.
+	# incoming-num-tcp: 10
+
+	# buffer size for UDP port 53 incoming (SO_RCVBUF socket option).
+	# 0 is system default.  Use 4m to catch query spikes for busy servers.
+	# so-rcvbuf: 0
+
+	# buffer size for UDP port 53 outgoing (SO_SNDBUF socket option).
+	# 0 is system default.  Use 4m to handle spikes on very busy servers.
+	# so-sndbuf: 0
+
+	# use SO_REUSEPORT to distribute queries over threads.
+	so-reuseport: yes
+
+	# use IP_TRANSPARENT so the interface: addresses can be non-local
+	# and you can config non-existing IPs that are going to work later on
+	# (uses IP_BINDANY on FreeBSD).
+	ip-transparent: yes
+
+	# use IP_FREEBIND so the interface: addresses can be non-local
+	# and you can bind to nonexisting IPs and interfaces that are down.
+	# Linux only.  On Linux you also have ip-transparent that is similar.
+	# ip-freebind: no
+
+	# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
+	# is set with msg-buffer-size). 1472 can solve fragmentation (timeouts).
+	# edns-buffer-size: 4096
+
+	# Maximum UDP response size (not applied to TCP response).
+	# Suggested values are 512 to 4096. Default is 4096. 65536 disables it.
+	# 3072 causes +dnssec any isc.org queries to need TC=1.
+	# Helps mitigating DDOS
+	max-udp-size: 3072
+
+	# buffer size for handling DNS data. No messages larger than this
+	# size can be sent or received, by UDP or TCP. In bytes.
+	# msg-buffer-size: 65552
+
+	# the amount of memory to use for the message cache.
+	# plain value in bytes or you can append k, m or G. default is "4Mb".
+	# msg-cache-size: 4m
+
+	# the number of slabs to use for the message cache.
+	# the number of slabs must be a power of 2.
+	# more slabs reduce lock contention, but fragment memory usage.
+	# msg-cache-slabs: 4
+
+	# the number of queries that a thread gets to service.
+	# num-queries-per-thread: 1024
+
+	# if very busy, 50% queries run to completion, 50% get timeout in msec
+	# jostle-timeout: 200
+
+	# msec to wait before close of port on timeout UDP. 0 disables.
+	# delay-close: 0
+
+	# the amount of memory to use for the RRset cache.
+	# plain value in bytes or you can append k, m or G. default is "4Mb".
+	# rrset-cache-size: 4m
+
+	# the number of slabs to use for the RRset cache.
+	# the number of slabs must be a power of 2.
+	# more slabs reduce lock contention, but fragment memory usage.
+	# rrset-cache-slabs: 4
+
+	# the time to live (TTL) value lower bound, in seconds. Default 0.
+	# If more than an hour could easily give trouble due to stale data.
+	# cache-min-ttl: 0
+
+	# the time to live (TTL) value cap for RRsets and messages in the
+	# cache. Items are not cached for longer. In seconds.
+	# cache-max-ttl: 86400
+
+	# the time to live (TTL) value cap for negative responses in the cache
+	# cache-max-negative-ttl: 3600
+
+	# the time to live (TTL) value for cached roundtrip times, lameness and
+	# EDNS version information for hosts. In seconds.
+	# infra-host-ttl: 900
+
+	# minimum wait time for responses, increase if uplink is long. In msec.
+	# infra-cache-min-rtt: 50
+
+	# the number of slabs to use for the Infrastructure cache.
+	# the number of slabs must be a power of 2.
+	# more slabs reduce lock contention, but fragment memory usage.
+	# infra-cache-slabs: 4
+
+	# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
+	# infra-cache-numhosts: 10000
+
+	# define a number of tags here, use with local-zone, access-control.
+	# repeat the define-tag statement to add additional tags.
+	# define-tag: "tag1 tag2 tag3"
+
+	# Enable IPv4, "yes" or "no".
+	# do-ip4: yes
+
+	# Enable IPv6, "yes" or "no".
+	# do-ip6: yes
+
+	# Enable UDP, "yes" or "no".
+	# NOTE: if setting up an unbound on tls443 for public use, you might want to
+	# disable UDP to avoid being used in DNS amplification attacks.
+	# do-udp: yes
+
+	# Enable TCP, "yes" or "no".
+	do-tcp: yes
+
+	# upstream connections use TCP only (and no UDP), "yes" or "no"
+	# useful for tunneling scenarios, default no.
+	# tcp-upstream: no
+
+	# upstream connections also use UDP (even if do-udp is no).
+	# useful if if you want UDP upstream, but don't provide UDP downstream.
+	# udp-upstream-without-downstream: no
+
+	# Maximum segment size (MSS) of TCP socket on which the server
+	# responds to queries. Default is 0, system default MSS.
+	# tcp-mss: 0
+
+	# Maximum segment size (MSS) of TCP socket for outgoing queries.
+	# Default is 0, system default MSS.
+	# outgoing-tcp-mss: 0
+
+	# Fedora note: do not activate this - can cause a crash
+	# Use systemd socket activation for UDP, TCP, and control sockets.
+	# use-systemd: no
+
+	# Detach from the terminal, run in background, "yes" or "no".
+	# Set the value to "no" when unbound runs as systemd service.
+	# do-daemonize: yes
+
+	# control which clients are allowed to make (recursive) queries
+	# to this server. Specify classless netblocks with /size and action.
+	# By default everything is refused, except for localhost.
+	# Choose deny (drop message), refuse (polite error reply),
+	# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
+	# allow_snoop (recursive and nonrecursive ok)
+	# deny_non_local (drop queries unless can be answered from local-data)
+	# refuse_non_local (like deny_non_local but polite error reply).
+	# access-control: 0.0.0.0/0 refuse
+	# access-control: 127.0.0.0/8 allow
+	# access-control: ::0/0 refuse
+	# access-control: ::1 allow
+	# access-control: ::ffff:127.0.0.1 allow
+	access-control: 127.0.0.0/8 allow
+	access-control: 10.0.0.0/24 allow
+
+	# tag access-control with list of tags (in "" with spaces between)
+	# Clients using this access control element use localzones that
+	# are tagged with one of these tags.
+	# access-control-tag: 192.0.2.0/24 "tag2 tag3"
+
+	# set action for particular tag for given access control element
+	# if you have multiple tag values, the tag used to lookup the action
+	# is the first tag match between access-control-tag and local-zone-tag
+	# where "first" comes from the order of the define-tag values.
+	# access-control-tag-action: 192.0.2.0/24 tag3 refuse
+
+	# set redirect data for particular tag for access control element
+	# access-control-tag-data: 192.0.2.0/24 tag2 "A 127.0.0.1"
+
+	# Set view for access control element
+	# access-control-view: 192.0.2.0/24 viewname
+
+	# if given, a chroot(2) is done to the given directory.
+	# i.e. you can chroot to the working directory, for example,
+	# for extra security, but make sure all files are in that directory.
+	#
+	# If chroot is enabled, you should pass the configfile (from the
+	# commandline) as a full path from the original root. After the
+	# chroot has been performed the now defunct portion of the config
+	# file path is removed to be able to reread the config after a reload.
+	#
+	# All other file paths (working dir, logfile, roothints, and
+	# key files) can be specified in several ways:
+	# 	o as an absolute path relative to the new root.
+	# 	o as a relative path to the working directory.
+	# 	o as an absolute path relative to the original root.
+	# In the last case the path is adjusted to remove the unused portion.
+	#
+	# The pid file can be absolute and outside of the chroot, it is
+	# written just prior to performing the chroot and dropping permissions.
+	#
+	# Additionally, unbound may need to access /dev/random (for entropy).
+	# How to do this is specific to your OS.
+	#
+	# If you give "" no chroot is performed. The path must not end in a /.
+	# chroot: "/var/lib/unbound"
+	chroot: ""
+
+	# if given, user privileges are dropped (after binding port),
+	# and the given username is assumed. Default is user "unbound".
+	# If you give "" no privileges are dropped.
+	username: "unbound"
+
+	# the working directory. The relative files in this config are
+	# relative to this directory. If you give "" the working directory
+	# is not changed.
+	# If you give a server: directory: dir before include: file statements
+	# then those includes can be relative to the working directory.
+	directory: "/etc/unbound"
+
+	# the log file, "" means log to stderr.
+	# Use of this option sets use-syslog to "no".
+	# logfile: ""
+
+	# Log to syslog(3) if yes. The log facility LOG_DAEMON is used to
+	# log to. If yes, it overrides the logfile.
+	# use-syslog: yes
+ 
+	# Log identity to report. if empty, defaults to the name of argv[0]
+	# (usually "unbound").
+	# log-identity: ""
+
+	# print UTC timestamp in ascii to logfile, default is epoch in seconds.
+	log-time-ascii: yes
+
+	# print one line with time, IP, name, type, class for every query.
+	# log-queries: no
+
+	# print one line per reply, with time, IP, name, type, class, rcode,
+	# timetoresolve, fromcache and responsesize.
+	# log-replies: no
+
+	# the pid file. Can be an absolute path outside of chroot/work dir.
+	pidfile: "/var/run/unbound/unbound.pid"
+
+	# file to read root hints from.
+	# get one from https://www.internic.net/domain/named.cache
+	# root-hints: ""
+
+	# enable to not answer id.server and hostname.bind queries.
+	# hide-identity: no
+
+	# enable to not answer version.server and version.bind queries.
+	# hide-version: no
+
+	# enable to not answer trustanchor.unbound queries.
+	# hide-trustanchor: no
+
+	# the identity to report. Leave "" or default to return hostname.
+	# identity: ""
+
+	# the version to report. Leave "" or default to return package version.
+	# version: ""
+
+	# the target fetch policy.
+	# series of integers describing the policy per dependency depth.
+	# The number of values in the list determines the maximum dependency
+	# depth the recursor will pursue before giving up. Each integer means:
+	# 	-1 : fetch all targets opportunistically,
+	# 	0: fetch on demand,
+	#	positive value: fetch that many targets opportunistically.
+	# Enclose the list of numbers between quotes ("").
+	# target-fetch-policy: "3 2 1 0 0"
+
+	# Harden against very small EDNS buffer sizes.
+	# harden-short-bufsize: no
+
+	# Harden against unseemly large queries.
+	# harden-large-queries: no
+
+	# Harden against out of zone rrsets, to avoid spoofing attempts.
+	harden-glue: yes
+
+	# Harden against receiving dnssec-stripped data. If you turn it
+	# off, failing to validate dnskey data for a trustanchor will
+	# trigger insecure mode for that zone (like without a trustanchor).
+	# Default on, which insists on dnssec data for trust-anchored zones.
+	harden-dnssec-stripped: yes
+
+	# Harden against queries that fall under dnssec-signed nxdomain names.
+	harden-below-nxdomain: yes
+
+	# Harden the referral path by performing additional queries for
+	# infrastructure data.  Validates the replies (if possible).
+	# Default off, because the lookups burden the server.  Experimental
+	# implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
+	harden-referral-path: yes
+
+	# Harden against algorithm downgrade when multiple algorithms are
+	# advertised in the DS record.  If no, allows the weakest algorithm
+	# to validate the zone.
+	# harden-algo-downgrade: no
+
+	# Sent minimum amount of information to upstream servers to enhance
+	# privacy. Only sent minimum required labels of the QNAME and set QTYPE
+	# to NS when possible.
+	qname-minimisation: yes
+
+	# QNAME minimisation in strict mode. Do not fall-back to sending full
+	# QNAME to potentially broken nameservers. A lot of domains will not be
+	# resolvable when this option in enabled.
+	# This option only has effect when qname-minimisation is enabled.
+	# qname-minimisation-strict: no
+
+	# Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
+	# and other denials, using information from previous NXDOMAINs answers.
+	aggressive-nsec: yes
+
+	# Use 0x20-encoded random bits in the query to foil spoof attempts.
+	# This feature is an experimental implementation of draft dns-0x20.
+	# use-caps-for-id: no
+
+	# Domains (and domains in them) without support for dns-0x20 and
+	# the fallback fails because they keep sending different answers.
+	# caps-whitelist: "licdn.com"
+	# caps-whitelist: "senderbase.org"
+
+	# Enforce privacy of these addresses. Strips them away from answers.
+	# It may cause DNSSEC validation to additionally mark it as bogus.
+	# Protects against 'DNS Rebinding' (uses browser as network proxy).
+	# Only 'private-domain' and 'local-data' names are allowed to have
+	# these private addresses. No default.
+	# private-address: 10.0.0.0/8
+	# private-address: 172.16.0.0/12
+	# private-address: 192.168.0.0/16
+	# private-address: 169.254.0.0/16
+	# private-address: fd00::/8
+	# private-address: fe80::/10
+	# private-address: ::ffff:0:0/96
+
+	# Allow the domain (and its subdomains) to contain private addresses.
+	# local-data statements are allowed to contain private addresses too.
+	# private-domain: "example.com"
+
+	# If nonzero, unwanted replies are not only reported in statistics,
+	# but also a running total is kept per thread. If it reaches the
+	# threshold, a warning is printed and a defensive action is taken,
+	# the cache is cleared to flush potential poison out of it.
+	# A suggested value is 10000000, the default is 0 (turned off).
+	unwanted-reply-threshold: 10000000
+
+	# Do not query the following addresses. No DNS queries are sent there.
+	# List one address per entry. List classless netblocks with /size,
+	# do-not-query-address: 127.0.0.1/8
+	# do-not-query-address: ::1
+
+	# if yes, the above default do-not-query-address entries are present.
+	# if no, localhost can be queried (for testing and debugging).
+	# do-not-query-localhost: yes
+
+	# if yes, perform prefetching of almost expired message cache entries.
+	prefetch: yes
+
+	# if yes, perform key lookups adjacent to normal lookups.
+	prefetch-key: yes
+
+	# if yes, Unbound rotates RRSet order in response.
+	rrset-roundrobin: yes
+
+	# if yes, Unbound doesn't insert authority/additional sections
+	# into response messages when those sections are not required.
+	minimal-responses: yes
+
+	# true to disable DNSSEC lameness check in iterator.
+	# disable-dnssec-lame-check: no
+
+	# module configuration of the server. A string with identifiers
+	# separated by spaces. Syntax: "[dns64] [validator] iterator"
+	module-config: "ipsecmod validator iterator"
+
+	# File with trusted keys, kept uptodate using RFC5011 probes,
+	# initial file like trust-anchor-file, then it stores metadata.
+	# Use several entries, one per domain name, to track multiple zones.
+	#
+	# If you want to perform DNSSEC validation, run unbound-anchor before
+	# you start unbound (i.e. in the system boot scripts).  And enable:
+	# Please note usage of unbound-anchor root anchor is at your own risk
+	# and under the terms of our LICENSE (see that file in the source).
+	# auto-trust-anchor-file: "/var/lib/unbound/root.key"
+
+	# trust anchor signaling sends a RFC8145 key tag query after priming.
+	trust-anchor-signaling: yes
+
+	# Root key trust anchor sentinel (draft-ietf-dnsop-kskroll-sentinel)
+	root-key-sentinel: yes
+
+	# File with DLV trusted keys. Same format as trust-anchor-file.
+	# There can be only one DLV configured, it is trusted from root down.
+	# DLV is going to be decommissioned.  Please do not use it any more.
+	# dlv-anchor-file: "dlv.isc.org.key"
+
+	# File with trusted keys for validation. Specify more than one file
+	# with several entries, one file per entry.
+	# Zone file format, with DS and DNSKEY entries.
+	# Note this gets out of date, use auto-trust-anchor-file please.
+	# trust-anchor-file: ""
+
+	# Trusted key for validation. DS or DNSKEY. specify the RR on a
+	# single line, surrounded by "". TTL is ignored. class is IN default.
+	# Note this gets out of date, use auto-trust-anchor-file please.
+	# (These examples are from August 2007 and may not be valid anymore).
+	# trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
+	# trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
+
+	# File with trusted keys for validation. Specify more than one file
+	# with several entries, one file per entry. Like trust-anchor-file
+	# but has a different file format. Format is BIND-9 style format,
+	# the trusted-keys { name flag proto algo "key"; }; clauses are read.
+	# you need external update procedures to track changes in keys.
+	# trusted-keys-file: ""
+	#
+	trusted-keys-file: /etc/unbound/keys.d/*.key
+	auto-trust-anchor-file: "/var/lib/unbound/root.key"
+
+	# Ignore chain of trust. Domain is treated as insecure.
+	# domain-insecure: "example.com"
+
+	# Override the date for validation with a specific fixed date.
+	# Do not set this unless you are debugging signature inception
+	# and expiration. "" or "0" turns the feature off. -1 ignores date.
+	# val-override-date: ""
+
+	# The time to live for bogus data, rrsets and messages. This avoids
+	# some of the revalidation, until the time interval expires. in secs.
+	# val-bogus-ttl: 60
+
+	# The signature inception and expiration dates are allowed to be off
+	# by 10% of the signature lifetime (expir-incep) from our local clock.
+	# This leeway is capped with a minimum and a maximum.  In seconds.
+	# val-sig-skew-min: 3600
+	# val-sig-skew-max: 86400
+
+	# Should additional section of secure message also be kept clean of
+	# unsecure data. Useful to shield the users of this validator from
+	# potential bogus data in the additional section. All unsigned data
+	# in the additional section is removed from secure messages.
+	val-clean-additional: yes
+
+	# Turn permissive mode on to permit bogus messages. Thus, messages
+	# for which security checks failed will be returned to clients,
+	# instead of SERVFAIL. It still performs the security checks, which
+	# result in interesting log files and possibly the AD bit in
+	# replies if the message is found secure. The default is off.
+	# NOTE: TURNING THIS ON DISABLES ALL DNSSEC SECURITY
+	val-permissive-mode: no
+
+	# Ignore the CD flag in incoming queries and refuse them bogus data.
+	# Enable it if the only clients of unbound are legacy servers (w2008)
+	# that set CD but cannot validate themselves.
+	# ignore-cd-flag: no
+
+	# Serve expired responses from cache, with TTL 0 in the response,
+	# and then attempt to fetch the data afresh.
+	serve-expired: yes
+
+	# Have the validator log failed validations for your diagnosis.
+	# 0: off. 1: A line per failed user query. 2: With reason and bad IP.
+	val-log-level: 1
+
+	# It is possible to configure NSEC3 maximum iteration counts per
+	# keysize. Keep this table very short, as linear search is done.
+	# A message with an NSEC3 with larger count is marked insecure.
+	# List in ascending order the keysize and count values.
+	# val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
+
+	# instruct the auto-trust-anchor-file probing to add anchors after ttl.
+	# add-holddown: 2592000 # 30 days
+
+	# instruct the auto-trust-anchor-file probing to del anchors after ttl.
+	# del-holddown: 2592000 # 30 days
+
+	# auto-trust-anchor-file probing removes missing anchors after ttl.
+	# If the value 0 is given, missing anchors are not removed.
+	# keep-missing: 31622400 # 366 days
+
+	# debug option that allows very small holddown times for key rollover,
+	# otherwise the RFC mandates probe intervals must be at least 1 hour.
+	# permit-small-holddown: no
+
+	# the amount of memory to use for the key cache.
+	# plain value in bytes or you can append k, m or G. default is "4Mb".
+	# key-cache-size: 4m
+
+	# the number of slabs to use for the key cache.
+	# the number of slabs must be a power of 2.
+	# more slabs reduce lock contention, but fragment memory usage.
+	# key-cache-slabs: 4
+
+	# the amount of memory to use for the negative cache (used for DLV).
+	# plain value in bytes or you can append k, m or G. default is "1Mb".
+	# neg-cache-size: 1m
+
+	# By default, for a number of zones a small default 'nothing here'
+	# reply is built-in.  Query traffic is thus blocked.  If you
+	# wish to serve such zone you can unblock them by uncommenting one
+	# of the nodefault statements below.
+	# You may also have to use domain-insecure: zone to make DNSSEC work,
+	# unless you have your own trust anchors for this zone.
+	# local-zone: "localhost." nodefault
+	# local-zone: "127.in-addr.arpa." nodefault
+	# local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
+	# local-zone: "onion." nodefault
+	# local-zone: "test." nodefault
+	# local-zone: "invalid." nodefault
+	# local-zone: "10.in-addr.arpa." nodefault
+	# local-zone: "16.172.in-addr.arpa." nodefault
+	# local-zone: "17.172.in-addr.arpa." nodefault
+	# local-zone: "18.172.in-addr.arpa." nodefault
+	# local-zone: "19.172.in-addr.arpa." nodefault
+	# local-zone: "20.172.in-addr.arpa." nodefault
+	# local-zone: "21.172.in-addr.arpa." nodefault
+	# local-zone: "22.172.in-addr.arpa." nodefault
+	# local-zone: "23.172.in-addr.arpa." nodefault
+	# local-zone: "24.172.in-addr.arpa." nodefault
+	# local-zone: "25.172.in-addr.arpa." nodefault
+	# local-zone: "26.172.in-addr.arpa." nodefault
+	# local-zone: "27.172.in-addr.arpa." nodefault
+	# local-zone: "28.172.in-addr.arpa." nodefault
+	# local-zone: "29.172.in-addr.arpa." nodefault
+	# local-zone: "30.172.in-addr.arpa." nodefault
+	# local-zone: "31.172.in-addr.arpa." nodefault
+	# local-zone: "168.192.in-addr.arpa." nodefault
+	# local-zone: "0.in-addr.arpa." nodefault
+	# local-zone: "254.169.in-addr.arpa." nodefault
+	# local-zone: "2.0.192.in-addr.arpa." nodefault
+	# local-zone: "100.51.198.in-addr.arpa." nodefault
+	# local-zone: "113.0.203.in-addr.arpa." nodefault
+	# local-zone: "255.255.255.255.in-addr.arpa." nodefault
+	# local-zone: "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
+	# local-zone: "d.f.ip6.arpa." nodefault
+	# local-zone: "8.e.f.ip6.arpa." nodefault
+	# local-zone: "9.e.f.ip6.arpa." nodefault
+	# local-zone: "a.e.f.ip6.arpa." nodefault
+	# local-zone: "b.e.f.ip6.arpa." nodefault
+	# local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault
+	# And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa.
+
+	# If unbound is running service for the local host then it is useful
+	# to perform lan-wide lookups to the upstream, and unblock the
+	# long list of local-zones above.  If this unbound is a dns server
+	# for a network of computers, disabled is better and stops information
+	# leakage of local lan information.
+	# unblock-lan-zones: no
+
+	# The insecure-lan-zones option disables validation for
+	# these zones, as if they were all listed as domain-insecure.
+	# insecure-lan-zones: no
+
+	# a number of locally served zones can be configured.
+	# 	local-zone: <zone> <type>
+	# 	local-data: "<resource record string>"
+	# o deny serves local data (if any), else, drops queries.
+	# o refuse serves local data (if any), else, replies with error.
+	# o static serves local data, else, nxdomain or nodata answer.
+	# o transparent gives local data, but resolves normally for other names
+	# o redirect serves the zone data for any subdomain in the zone.
+	# o nodefault can be used to normally resolve AS112 zones.
+	# o typetransparent resolves normally for other types and other names
+	# o inform acts like transparent, but logs client IP address
+	# o inform_deny drops queries and logs client IP address
+	# o always_transparent, always_refuse, always_nxdomain, resolve in
+	#   that way but ignore local data for that name
+	# o noview breaks out of that view towards global local-zones.
+	#
+	# defaults are localhost address, reverse for 127.0.0.1 and ::1
+	# and nxdomain for AS112 zones. If you configure one of these zones
+	# the default content is omitted, or you can omit it with 'nodefault'.
+	#
+	# If you configure local-data without specifying local-zone, by
+	# default a transparent local-zone is created for the data.
+	#
+	# You can add locally served data with
+	# local-zone: "local." static
+	# local-data: "mycomputer.local. IN A 192.0.2.51"
+	# local-data: 'mytext.local TXT "content of text record"'
+	#
+	# You can override certain queries with
+	# local-data: "adserver.example.com A 127.0.0.1"
+	#
+	# You can redirect a domain to a fixed address with
+	# (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
+	# local-zone: "example.com" redirect
+	# local-data: "example.com A 192.0.2.3"
+	#
+	# Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
+	# You can also add PTR records using local-data directly, but then
+	# you need to do the reverse notation yourself.
+	# local-data-ptr: "192.0.2.3 www.example.com"
+
+	include: /etc/unbound/local.d/*.conf
+
+	# tag a localzone with a list of tag names (in "" with spaces between)
+	# local-zone-tag: "example.com" "tag2 tag3"
+
+	# add a netblock specific override to a localzone, with zone type
+	# local-zone-override: "example.com" 192.0.2.0/24 refuse
+
+	# service clients over SSL (on the TCP sockets), with plain DNS inside
+	# the SSL stream.  Give the certificate to use and private key.
+	# default is "" (disabled).  requires restart to take effect.
+	# tls-service-key: "/etc/unbound/unbound_server.key"
+	# tls-service-pem: "/etc/unbound/unbound_server.pem"
+	# tls-port: 853
+	#
+	# request upstream over SSL (with plain DNS inside the SSL stream).
+	# Default is no.  Can be turned on and off with unbound-control.
+	# tls-upstream: no
+
+	# Certificates used to authenticate connections made upstream.
+	# tls-cert-bundle: ""
+
+	# Add system certs to the cert bundle, from the Windows Cert Store
+	# tls-win-cert: no
+
+	# Also serve tls on these port numbers (eg. 443, ...), by listing
+	# tls-additional-ports: portno for each of the port numbers.
+
+	# DNS64 prefix. Must be specified when DNS64 is use.
+	# Enable dns64 in module-config.  Used to synthesize IPv6 from IPv4.
+	# dns64-prefix: 64:ff9b::0/96
+
+	# ratelimit for uncached, new queries, this limits recursion effort.
+	# ratelimiting is experimental, and may help against randomqueryflood.
+	# if 0(default) it is disabled, otherwise state qps allowed per zone.
+	# ratelimit: 0
+
+	# ratelimits are tracked in a cache, size in bytes of cache (or k,m).
+	# ratelimit-size: 4m
+	# ratelimit cache slabs, reduces lock contention if equal to cpucount.
+	# ratelimit-slabs: 4
+
+	# 0 blocks when ratelimited, otherwise let 1/xth traffic through
+	# ratelimit-factor: 10
+
+	# what is considered a low rtt (ping time for upstream server), in msec
+	# low-rtt: 45
+	# select low rtt this many times out of 1000. 0 means the fast server
+	# select is disabled.  prefetches are not sped up.
+	# low-rtt-permil: 0
+
+	# override the ratelimit for a specific domain name.
+	# give this setting multiple times to have multiple overrides.
+	# ratelimit-for-domain: example.com 1000
+	# override the ratelimits for all domains below a domain name
+	# can give this multiple times, the name closest to the zone is used.
+	# ratelimit-below-domain: com 1000
+
+	# global query ratelimit for all ip addresses.
+	# feature is experimental.
+	# if 0(default) it is disabled, otherwise states qps allowed per ip address
+	# ip-ratelimit: 0
+
+	# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
+	# ip-ratelimit-size: 4m
+	# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
+	# ip-ratelimit-slabs: 4
+
+	# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
+	# ip-ratelimit-factor: 10
+
+	# Specific options for ipsecmod. unbound needs to be configured with
+	# --enable-ipsecmod for these to take effect.
+	#
+	# Enable or disable ipsecmod (it still needs to be defined in
+	# module-config above). Can be used when ipsecmod needs to be
+	# enabled/disabled via remote-control(below).
+	# Fedora: module will be enabled on-demand by libreswan
+	ipsecmod-enabled: no
+
+	# Path to executable external hook. It must be defined when ipsecmod is
+	# listed in module-config (above).
+	# ipsecmod-hook: "./my_executable"
+	ipsecmod-hook:/usr/libexec/ipsec/_unbound-hook
+
+	# When enabled unbound will reply with SERVFAIL if the return value of
+	# the ipsecmod-hook is not 0.
+	# ipsecmod-strict: no
+	#
+	# Maximum time to live (TTL) for cached A/AAAA records with IPSECKEY.
+	# ipsecmod-max-ttl: 3600
+	#
+	# Reply with A/AAAA even if the relevant IPSECKEY is bogus. Mainly used for
+	# testing.
+	# ipsecmod-ignore-bogus: no
+	#
+	# Domains for which ipsecmod will be triggered. If not defined (default)
+	# all domains are treated as being whitelisted.
+	# ipsecmod-whitelist: "libreswan.org"
+	# ipsecmod-whitelist: "nlnetlabs.nl"
+
+# Python config section. To enable:
+# o use --with-pythonmodule to configure before compiling.
+# o list python in the module-config string (above) to enable.
+# o and give a python-script to run.
+python:
+	# Script file to load
+	# python-script: "/etc/unbound/ubmodule-tst.py"
+
+# Remote control config section.
+remote-control:
+	# Enable remote control with unbound-control(8) here.
+	# set up the keys and certificates with unbound-control-setup.
+	# Note: required for unbound-munin package
+	control-enable: yes
+
+	# Set to no and use an absolute path as control-interface to use
+	# a unix local named pipe for unbound-control.
+	# control-use-cert: yes
+
+	# what interfaces are listened to for remote control.
+	# give 0.0.0.0 and ::0 to listen to all interfaces.
+	 control-interface: 127.0.0.1
+	# control-interface: ::1
+
+	# port number for remote control operations.
+	# control-port: 8953
+
+	# unbound server key file.
+	server-key-file: "/etc/unbound/unbound_server.key"
+
+	# unbound server certificate file.
+	server-cert-file: "/etc/unbound/unbound_server.pem"
+
+	# unbound-control key file.
+	control-key-file: "/etc/unbound/unbound_control.key"
+
+	# unbound-control certificate file.
+	control-cert-file: "/etc/unbound/unbound_control.pem"
+
+# Stub and Forward zones
+include: /etc/unbound/conf.d/*.conf
+
+# Stub zones.
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of nameservers. list zero or more
+# nameservers by hostname or by ipaddress. If you set stub-prime to yes,
+# the list is treated as priming hints (default is no).
+# With stub-first yes, it attempts without the stub if it fails.
+# Consider adding domain-insecure: name and local-zone: name nodefault
+# to the server: section if the stub is a locally served zone.
+# stub-zone:
+#	name: "example.com"
+#	stub-addr: 192.0.2.68
+#	stub-prime: no
+#	stub-first: no
+#	stub-tls-upstream: no
+# stub-zone:
+#	name: "example.org"
+#	stub-host: ns.example.com.
+
+# You can now also dynamically create and delete stub-zone's using
+# unbound-control stub_add domain.com 1.2.3.4 5.6.7.8
+# unbound-control stub_remove domain.com 1.2.3.4 5.6.7.8
+
+# Forward zones
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of servers. These servers have to handle
+# recursion to other nameservers. List zero or more nameservers by hostname
+# or by ipaddress. Use an entry with name "." to forward all queries.
+# If you enable forward-first, it attempts without the forward if it fails.
+# forward-zone:
+# 	name: "example.com"
+# 	forward-addr: 192.0.2.68
+# 	forward-addr: 192.0.2.73@5355  # forward to port 5355.
+# 	forward-first: no
+# 	forward-tls-upstream: no
+# forward-zone:
+# 	name: "example.org"
+# 	forward-host: fwd.example.com
+#
+# You can now also dynamically create and delete forward-zone's using
+# unbound-control forward_add domain.com 1.2.3.4 5.6.7.8
+# unbound-control forward_remove domain.com 1.2.3.4 5.6.7.8
+
+# Authority zones
+# The data for these zones is kept locally, from a file or downloaded.
+# The data can be served to downstream clients, or used instead of the
+# upstream (which saves a lookup to the upstream).  The first example
+# has a copy of the root for local usage.  The second serves example.org
+# authoritatively.  zonefile: reads from file (and writes to it if you also
+# download it), master: fetches with AXFR and IXFR, or url to zonefile.
+auth-zone:
+	name: "."
+	for-downstream: no
+	for-upstream: yes
+	fallback-enabled: yes
+	master: b.root-servers.net
+	master: c.root-servers.net
+	master: e.root-servers.net
+	master: f.root-servers.net
+	master: g.root-servers.net
+	master: k.root-servers.net
+# auth-zone:
+#	name: "example.org"
+#	for-downstream: yes
+#	for-upstream: yes
+#	zonefile: "example.org.zone"
+
+# Views
+# Create named views. Name must be unique. Map views to requests using
+# the access-control-view option. Views can contain zero or more local-zone
+# and local-data options. Options from matching views will override global
+# options. Global options will be used if no matching view is found.
+# With view-first yes, it will try to answer using the global local-zone and
+# local-data elements if there is no view specific match.
+# view:
+#	name: "viewname"
+#	local-zone: "example.com" redirect
+#	local-data: "example.com A 192.0.2.3"
+# 	local-data-ptr: "192.0.2.3 www.example.com"
+#	view-first: no
+# view:
+#	name: "anotherview"
+#	local-zone: "example.com" refuse
+
+# Fedora: DNSCrypt support not enabled since it requires linking to
+#         another crypto library
+#
+# DNSCrypt
+# Caveats:
+# 1. the keys/certs cannot be produced by unbound. You can use dnscrypt-wrapper
+#   for this: https://github.com/cofyc/dnscrypt-wrapper/blob/master/README.md#usage
+# 2. dnscrypt channel attaches to an interface. you MUST set interfaces to
+#   listen on `dnscrypt-port` with the follo0wing snippet:
+# server:
+#     interface: 0.0.0.0@443
+#     interface: ::0@443
+#
+# Finally, `dnscrypt` config has its own section.
+# dnscrypt:
+#     dnscrypt-enable: yes
+#     dnscrypt-port: 443
+#     dnscrypt-provider: 2.dnscrypt-cert.example.com.
+#     dnscrypt-secret-key: /path/unbound-conf/keys1/1.key
+#     dnscrypt-secret-key: /path/unbound-conf/keys2/1.key
+#     dnscrypt-provider-cert: /path/unbound-conf/keys1/1.cert
+#     dnscrypt-provider-cert: /path/unbound-conf/keys2/1.cert
+
+# CacheDB
+# Enable external backend DB as auxiliary cache.  Specify the backend name
+# (default is "testframe", which has no use other than for debugging and
+# testing) and backend-specific options.  The 'cachedb' module must be
+# included in module-config.
+# cachedb:
+#     backend: "testframe"
+#     # secret seed string to calculate hashed keys
+#     secret-seed: "default"
+#     # For "redis" backend:
+#     # redis server's IP address or host name
+#     redis-server-host: 127.0.0.1
+#     # redis server's TCP port
+#     redis-server-port: 6379
+#     # timeout (in ms) for communication with the redis server
+#     redis-timeout: 100
+
+# Adding DNS-Over-TLS Support
+#tls-cert-bundle: /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
+forward-zone:
+  name: "."
+{% if dns_over_https == true %}
+  forward-ssl-upstream: yes
+  forward-addr: {{ dns_primary }}@853
+  forward-addr: {{ dns_secondary }}@853
+{% else %}
+  forward-addr: {{ dns_primary}}@53
+  forward-addr: {{ dns_secondary }}@53
+{% endif %}
+

+ 23 - 0
roles/name-resolution/templates/unbound.service.j2

@@ -0,0 +1,23 @@
+[Unit]
+Description=Unbound recursive Domain Name Server
+After=network.target
+After=unbound-keygen.service
+Wants=unbound-keygen.service
+Wants=unbound-anchor.timer
+Before=nss-lookup.target
+Wants=nss-lookup.target
+
+[Service]
+Type=simple
+EnvironmentFile=-/etc/sysconfig/unbound
+ExecStartPre=/usr/sbin/unbound-checkconf
+ExecStartPre=-/usr/sbin/unbound-anchor -a /var/lib/unbound/root.key -c /etc/unbound/icannbundle.pem -f /etc/resolv.conf -R
+ExecStart=/usr/sbin/unbound -d $UNBOUND_OPTIONS
+ExecReload=/usr/sbin/unbound-control reload
+Restart=on-failure
+RestartSec=5s
+StartLimitIntervalSec=30
+StartLimitBurst=5
+
+[Install]
+WantedBy=multi-user.target

+ 2 - 0
roles/name-resolution/vars/main.yml

@@ -0,0 +1,2 @@
+---
+dhcp_hosts: "gateway"

+ 326 - 0
vars/vault.yaml

@@ -0,0 +1,326 @@
+$ANSIBLE_VAULT;1.1;AES256
+33653932363638363732323534343764343237336236363934336236643739326433393130393065
+6466303838623637636366653166323966646134383261340a313739633433393662333232333439
+34326633313862643231653333316565373664343237333835343932633431636362343566383266
+6631633038326230340a393465633963376566363237333635616366373930303930636464653032
+38353063613665613630316338633634313336643238663737306166333065383462363237346663
+31663265303064376539613532326463346163396339393762393236643433356536313633373533
+62646638653039373266386237383336313834623464346137613134323864343961663039646134
+64636532313331323163323235376364333435316363643535623136393031316436333466323835
+31623739356333336330373833613937613864633335383234383635313430383336653737326139
+37373338343731383161346161613736646164373731353137343364313032333233306337326665
+34356432343337323632373365346665303530613466353037373566636562346561373239383632
+32653231366535383961653563343436633635323737333863366563323338363133346130623961
+66353531326461633838663535316635343232393230383863313165396631363261303433636334
+30343236303034346634366362356330643034363734636437613738666432373362656537633562
+39626533336232626134366662353635363230306336613266393830306133346664613332363265
+37646162323331653533393936306362346663343734646461376135393038323462353364353032
+63366365616462653732336331653231393739376662646661373463373036383239613934333162
+31653332396133383735616362636363386330303634353065346233623261643561313039663162
+33643534353535306137343734653630633935623736646465653335363462356636396330323738
+37366535623430656366323330616665663330613031376362396238663061663534376364643130
+64373463616633333536313166666262666666383234646262643439336561376135303261353334
+66343236666539623034643563333664613637343164393339316236326239363336396163633134
+64333763326663623036306638333636623962306134316432313334613166336635623937666136
+33663564303732653634373332623037333830313631323365343130373133333330623734653130
+62346138613765333862633063666237393635616366663961343131386666393739343135326339
+66313232303137333966396132656566346139636466303235346361343737326261626633633764
+36616230393464373133623965366330323065653939616638326666323437386266613961366364
+39343837303531303738303165636237396635373338336532616339616632643331383638653832
+34373462643539313731626332333132306539653363333831623936613035656364383262643139
+35333633356536366263303864396432393265386233653634633965653631353631346434353039
+64633161663537336461313931643934376139353837343239326637636130666565663430663866
+34653764623932646638336639383161643439393735383938373366336665626133626162666136
+66663266633936663962363165636135353332613236323363306631666365303239636637616132
+37613334373235656562353365343163386264336331393738666639626132633831616463313566
+65306332316235663430663566333764393836643037386331653636636562353734393334386534
+33626135343438363334396331336331623330316464653530353564333363373835323334343736
+36643731346632613834613265383636653532383539343965333437363530336136613739303863
+61316462313635316139663065306661623966646662303361386333333238333433373131333663
+62306638376538313334383231646662626364343133316335393434373837653038623531373362
+63366134356262363362666666613139383638343661373439343766383062386466396564313634
+62623431313136346463383938643762356233663739633533396365643664376530326232383462
+34303532396565633837626132346531636431346633376530386166376331303038336266346634
+64306633633733363534343033643639373535626139373236356561656266636666333230323133
+64623235383862306337613336376231373532613066663832326634663032333866386565313336
+34313237313833333561393330393830396634323762323130643738373738623563666531343632
+39633531356438653637383339366231373861666264343365393434313533633131303539613464
+39353766336233646638653365323265613230356635366335353339663862343966636634616139
+37313030626366363339653839623838303063636533623736393334353730323235633762643235
+63386334393461653035393865353235656132313434666338393432383938646435336531613361
+66613431663465376264663738623639633266626330616135366634646239383231663331343762
+37353763303634646562616164636162366664363265633837333731653464333362643338616131
+66643939336363666433663838326133306263383637316333613834306262356336646235333835
+38353466396138633530343433633731353037333334313964356664643734386439363831366462
+30336236366164653663663535323237613635396130343466316165303665386163646234333131
+34663565616164643764323236663538343336336266653435336664366138613233323036663966
+31316436393539323439323730386539306231363839643466633535306234643435646130386137
+38666630366365306533353861623431313265333635373861616665323530643361316264633932
+30373532636635316137633765653035323438316665346338613937396566663466333430333739
+62383134636635393035323037383766306133313165666436393030333264323431653437656439
+62363238656338396532323763646236383239383632646439363739373135323235356633396235
+31623462636363343838666632383366363430326465333265646231646536386661303333306539
+62303336663536363761646638373961383065613736353939653363323330346532326130343838
+32366538626164393965373630346162373537363733643133386365333761363336323265613731
+63343330343238336236623633393564616338663136656337366362373762363436663338396562
+61643733396631363937336465326138353438386437656339656539323134356139386166316534
+35323630646332363063363265656231323730386233633863386564313037653932386134326238
+66653766396364653164313565363531646364363865333565613239633966313764666339326565
+38643761626636666333396135343861623565643737653165643830306239373138366335303333
+35323439643439376139646364623738343565613838303236323265393330376562333632373965
+30613731373830646638346631636462663032656631306162643835363566323639323736386138
+63336138656532343831333162363834383638356130313365306466656164303834663365383438
+66613662623161633035326165626566363439663433383638663037303266353637313461636432
+62316363653064366136616437383262393430643037343365306639636563323437396662666263
+35633662353633663638613964376539616631393166356333623332626164373331306635393439
+66643761383333646163343138343239393332626637306630653236376465656263333436333464
+31373133336432393931363938396338653866616132616436343365353133376538353233623865
+36646165323635373963616231386164353536623339363862333731363533393534633137616231
+63653134666135306266343238653439663037643061346338303337363962363138633764623362
+62646431643263316366396564626434616239643239613462656437626337333638326233636664
+32633339343162306365623232366132323933343035326436383435616464306165393733386136
+37353931663430653564326361666562366163666638366262613139616633616666353733333663
+63316530623661636336653863393634636430636266333539633133316438643434363061376661
+36613739393934666561363334346132613463383838376537666162306439366237376264646239
+64393562303363353366383638373865396166323331646332626634303539323530313738313835
+61316262663838353639306264656661306330326537616366333432353737366137353331303663
+65643365613939653130656238376261653031613030626362303230353361623731343961333934
+62623332643639373161303730373166663131336139613437306439383564343332616564383535
+65313535303639643335323730633665646662306565613831303962646366333839343462326539
+65623633633433383530653837376235373063383334633635646266333934393335353732663938
+36343665636130383033383634653735363163666137353834366662326532653930343166393162
+39323532643966343462656232363138383461643064663264636133363839326634643462323863
+35306432653562353466343136373932663063613634366634353833663866626664653435326362
+36346138626135626164306164626139363763333339656533363330346133663062396233353333
+34303138636436656462633731646438383665666335653237323632626538326430323537623365
+65366564346461316439636334663838313465313938376264343437613032633862626438343035
+37363539653263373963363038643832373136633032633137623361623832643139303236646230
+34636164383732323931626164643166363663623163633237323161653133656538643836333361
+34633237373063663963646634313038343733363631323436653936346165313234666632316666
+32313238623562323533323965336337313939643063333134636539633764633239353063653432
+36616265663631326535623732353766313265386238383633653364353336393134303133626164
+36353662636530633266303964386531393433396533613964333164313963326637373364383763
+62613533383835313733333039616438316265373538623465613437336237336332646634306335
+31366531373064616330326330656263613332343632323732383337306130303764326164386264
+62666234633762336530626337623936373665306664356666333934343965666332373632383333
+36376137303133623363646264396466336365623362346162356564646363333864386336616566
+32343037613465613738333264636436656362626337343863373530323533393039656332643862
+34383735323063613564373764633737363938333461363036646337653864633431643334656164
+64323264333237316435303963656363363334646532633463656236343935386434336166313530
+37373636396234656465383531646530363231633330323637383062326564616430393836616364
+34336436363235383264363063633762356465323964383766343034613730656135323832643364
+37323031396536643633343665626439356136363563643733393762343938656134333866373434
+61643033393036626330323762356635386533653361626163613962396132373936656265353666
+66383962393330396332393431383439326337356161326331343935663133326534373639306639
+30623938626363313563363934666561323462393935623730393130346334343132666263373339
+36313039623561376238663062393832343034383066353666393938653833353730343964666438
+37313966363166333262356563356435653735333736366131393561353833666334386537396333
+35653566666663353864323131653738306337356664323637373964353430383661646135306561
+37386434613137663861613738333139616237643630376632363462303939373532313838303030
+64303036313931336138363362373631653537633035306462656465366531643261303062376539
+64323631643333323965653638646466623666626135623138613563613639376663396333303966
+39646337333862393362646164616332303661666534383636323933313865353034656532326662
+66373264383831613631333238316338643934636339326463373963363534316430316430356538
+36633931616630303237396135313830363339613639376262373534396438636234363562313864
+35343133386230373939363437323233323035666137646165373332643833643637396434616531
+36623832383636346636636539623665623365653763373664333966613537623537376132626438
+30336438613161366134616437346131326630666337383630313135613962323333333665623839
+35613133333138376535383938376536333731626337373837623135303864363361386536626431
+32323464666235333063313434323937613566393130373334616561306335333061613163643335
+64303263373735303631636538643863626537616438663663316665623462613931316438663139
+37656262363834346262623330383161326563323636343965303062396330623136626566373662
+39663763363033613236303830616335333265303933373136373138333361616361393366333563
+33326232313530656536623364656163333236646637303065353836373561323334643238656139
+62393633613733613764343764633634396137613534333061313636316430373562333564373933
+65626433313138623530646230353432633561613636336432393233336165663436323639623065
+34663063333737646161373633313338306664316136616530363232343233316135353532366663
+61366161613363393839653561316239303837653531303466313761353835656531653636343262
+64633830633333623662653037623137366164613266326133373536333261643935323461373462
+36363164303666626130386136313063616561636564636334316431636465396235633563356631
+61663232656137303437333466643732663563643564653164313064333262633661623465626230
+33353661626565633362383462326564316262333866633639326230376433653433633661646330
+63363838663130343563373763663838656661323465313963333966613132353362333664646265
+37656337613235633138316531373036336262663361353933396166323165373435633365393735
+36653538336266343462656235636130323163626231336662396165353836336434653130303061
+32633531313131623134393836373834653661366438633931626166616265373465616365636362
+30663663363763636434343733386433346265306132323739346236343864353038333332356361
+34366238353730633534303831666238616266663332393531336532626534353632326639356333
+66663135393862323262633032376261303538306530306336356636383330613936383165313765
+65656135333364363637646266623164326337623237613134633161396239386138386232316632
+63353163386362343134326336373535656565336135333661343763643938356635643863316264
+31646666323630396463626665636137613833316231616437323163326633666339393632373332
+30613535643135626432356639316163653966326138306230373461323061303339323962366134
+35383863366565623962636362633639333233663438396634633162636134393666393038653133
+34373662383034353032386361356438383732323362333164646263623464316261373930616632
+30663962366238303434643736393239366635386261306534383264663631343462656466343032
+33336630336135613163316330613835653232363466663964393738623763303165353138363964
+31333830643766383162663335393062666537623461346337356236323066343164633930343961
+65656530633937663966383233303462333439633137636262643138376561663032346434666463
+36336637633335383237663033633232326534636266373830613336653239313338633932613438
+63626662303235313237666639313762353639316166376363306163393966396338626566366336
+33336536376431393835656262386236313531623836383666356537613533653861333432343133
+34353962356139626262353931653530343964326563346434356536343137353466303462353166
+30383638623434646363353536336638636138386231393361633734646364623466353833303337
+61613737363530633136323739343031383966636539303536623039303037353938373166623134
+33643336323336663433313263356664663338336562313734373131303663656633316536336333
+63306536666564633039373963623562636133316563356464646561303633303730373964373733
+32306436366233636238363339643934366232663061333432353963323561313136623465326537
+35323636336564303165636139343062636631376666643236366336326363356232336633623334
+35656661653935653338323933323665353035346366633265623838386437386631663066643637
+66376137313830646266613933653961396433303965366138633039323032633233386264626135
+62323432336233313037366535323766636430656333356233313236636632323164326561356163
+61656430346133363639363135376337633632393637393364303533626630353533313631336161
+39636639363634373232383232376436666437303533613931666433396137393833636161643838
+36343533323835616161313933383530656136653336363063326463323863343439636666336631
+36616631326337373131623132306335646561666139303662653763653636343730333365346632
+39386437613737376236353365323933623335313164663930663535626261313765613963343466
+30323037656462653635326334363833316562623766386464636165653364333132376463343037
+34373331343836366364313763626465626632636436383730313038646534663464636331656439
+34613063376362303834326264396530313931353661363633363233396132643564646663313438
+39613131666437333736656165663037613736393835653135306135333933366263633636633934
+66393236306335353736636438353130343435373030396139373765386366373330666666626437
+33363539383261353764323239636661353463373733643437323933366462353466376432333239
+39613466303034623561613065326235373633303362626136376462346264343466393536643162
+35633066353731323333346161363263346532396265323038313261613465356638333562373664
+32613764313562643963633564303338663861363464353333666632613932396437333836643331
+38626261336633636130376231336330326334313361373636643230323333313063333638646134
+64636639623431613265636439326166353631356336323466363166303139366161633830353733
+32616562376233393239373736623539326165306636313236396335656439373762636236383564
+39386163623662303131343031663666366565343562626530333232353162373036316562376536
+30343431323764336337373962313931353132396231353234353762653764643336623061376337
+36653639373662633638316137616434613861393235646430376366663862323062623565303635
+39333738663931643436316533326663646261376637376136316130613139313536346137663532
+31336235666131623633646531663764313764303334623335653330636637626230633239646437
+64333061363364636565343165656436666461623262333537613438353630326665323335306365
+35333536636462396562666666626535616265313464383635366161633537356264656330656363
+39646334313135383138636663336233366130616533373333656536393462653338363339363161
+36353430353365646166363165346236373163353632356532663463616637633736306437316564
+37666339646165386136313232613365366535326639346461363366343337633338383030356435
+34306630633832376239313334353539623434323836373265303038363932333830373836346231
+30653735323363366434663839383737323231366231373036333530626638613862663664373961
+31363062383866393830373266613066343865353863616633666236306230313536396661326434
+66376630373631313763353133366431373962633333616439363633323063646531326239353966
+38623465346239333161343335326462393137366537666332373966356233666438643036313663
+64373539626136643737636664376631316166353366633339346133356339653134666430653535
+38383531396665616135663031363862396131376133623230396633373566636565316230353530
+37376335313238303136373463373432356365663164366230613435616132363230666364613434
+37303334343265633432613934636538306339643063353735333036376332643833373236636438
+66613735376235666564306437613137643266653132663531356636333762663831656462336230
+35613535346664383037303138336464663166316164393463653064353364653966353139326534
+66386536663338323939383230366165326437313434663230373964336237396638303461373038
+35313365383930343632633139666165633765313334643562626530323932636363323138333735
+34663965383738623137313332353335613338666330313531616339313066666166323663333432
+61326362663332616163356333313537313064633238613733396530303237613533383737623864
+65366130366565633962303862366265313035653138313139633761636532656431303934393165
+34353739326232373533393863376635393237366365303538366438656664616164623832363338
+35633331333965636235396664363834313538363231616137633263396533356463323939383831
+64383463636438393661393831323730303536383737396433353533626664623433323365373461
+38373136336132653335316139316436643631643336643630393438613061383436633530343265
+66353431383337613531356438376366316166656536386532356266333531383930353737366330
+38623430343034636364613735303161356330633733643962383863353765333431386163343365
+65393133376438363231343430326330356365306462386632623562323935393430343334666234
+37623837363466613934323465653064303164646436336237306462663530303438616138376462
+33366662643961383530646563353066376630653561633834613733373831623866613037643666
+39303333376234613163333633313731306461306438616438616164643962353438303530393535
+35396334646565313434616435393633313564616534393166373561623363373438616637343162
+63393065623663626234666435363532383338373862653939306562366263303864643332333465
+38336232343039306532396461613334343339386633626630333863386138393039396437393263
+61363730656561666364353533366636356565646130626364636233636338396133383363396165
+64623661636561396130386435373061633339303035613633666139393632633165373235393765
+65636161656636356436376239306661646132316330336533326138356466663361396161666533
+66623631646561393466663065383332336332343539316330343339633961633262363732646462
+38613764633662666437633238346566396131313638656561663333653265303734626564393439
+36633234346466656339333564623337396133363162376263633261623563373662336534306633
+66326262613865616634323233373261636261616631656232366530616662316338306136663937
+61326361336563343038363230656435376139333332333132623339313038636236633732306232
+62643838333861346633376333363135643564633636336431396134663466306432643330656662
+61623238656464356264316462653239303362663936313337326239643539633938306235613963
+33616138306134303533656637393838316463633931663962363536653235333534616364366166
+65316466326335306133396461613835363237663463333539393364656166363933326131386465
+63636463333463656462323038336332373131316133643963656463633238656265663832613261
+34393565613563666130313961373632636464343366636264346630636366646363643730333631
+33653865666339616236656134333534376466393062633566623464613730313565303165623666
+64613834383130373664373637383036666266316631393662323936636166363336353731663632
+32333336636166303437393935653037616237333530353763306266653034313731653362613535
+35623562613332616531346535656536316233366230303935333361303536636636656563343665
+32626232653365616233353836656264653438313239313462646535386133666533333730623338
+61303731326435373536393337626439373233646162653038666130656634366333633761613261
+65393836353333613433623761653962323961623361316339373830663132366137646664316136
+31376566643535653763653962313965396464386138373862636435396330356438623533316665
+39373738396432373463633966396135643265396130333733633932313037666664353738633266
+62653736383339373536633762646563376562636131306537663131383565363232643734643233
+66373066373230656461643934363534613732303962363834353463663732643263346338633334
+33396539613761376437623765636662663734626230653035633635303832663265376166366333
+38353461386563656265353065646233333034623330636361383863663132316533326463653863
+32323466323036653165626531656336393338343761636361633162383438656363623630326563
+31303037393734623736373661333735306639653335666564623564306332656161663463313934
+39386266616632363933326536653234313031356164333430636234353466353134656135356134
+64376438383462623866633530346639306161653830313937353464633764336131666638343536
+32353639346431616362653364333031336461333030373433643062376234643038333862386233
+65656334383839343533353933396533663533336533643333613361636664356238323639386537
+64646531643066396530386466383637326232656433336662393735653964313338303661616132
+31616464306166656266313261396532636634653930336431323438306362356330663632663534
+36333961393530386531356435346262346131383831373237336664323133323061346338663662
+37373030666565316637633636346364643562653462336166363835656535303265396134373231
+39626131306362616233333538363830383562666161383432343061303636373334336139626365
+35616536653032313834666530336235623061366439303731303039313636353665333861303666
+61663332383731663233663334333836366636313364653837613734353735303733346636363432
+66646630373036353035303332643436326166633333636436336439643931663835383636363465
+63643138623032326632613962313936353361313362316466303430353364366439386432366565
+64643964646432366561653431356663633335386136363234333565306638336363336163646235
+65613262663130363262323233373337303966633735656431326665343366343639646663363964
+31363465363762653464626363616463623737623431333330323138653335633133353965376237
+38656163623534633237396633333563363164373238343462646130393839636631343832663335
+65343763326465613130383162356161363939323739663939666338663038343266363239336233
+35623966633861643864353835663635353132373930333133333365643332336133353865313034
+33343530343732376162316232316233303135343133386637613335623537303339303366643837
+65613436306237623230316664346538366630346133393433303235383364653862633434343561
+30353737323335363165626436383664663438353134656663303932363334666239303039613164
+33653731363663613766393831653465613333643138306331396338646333383866366630636233
+38386138623135366138393737616231383162353766626339363262393433363163383064643164
+39613039343039616134396230386465643063613232363536313465653033643565313436363332
+39643938663665383730393765353462373936613637663338366436613162313031376130623138
+37666161633933666636633339343837393736616661313937636332323331386163653432326461
+31356430613134343966613934336130646563636331393737383161613539653531623135663262
+39613465376664336338633564346130636364393637303738613963336334653430383038323032
+64336363643631353733616537333461343437646233353137313837396465313266623065393964
+66613764613031626462613037383939313731306362323437376238313464636634316465343332
+66303064313633636336353666636439336531316430663732643463616133353232303265333339
+66343833613738343566343863396465353333363032303064653835643763633638333964646339
+30323862623933356464323237623066396439396230393735373635663339343830396136346235
+63373634333565383039343962336536663863643030333335613431336665383466386138313034
+66363131333538616563643835373638666361363763356464393635323138333532333234613434
+65343337636465636638356361616339656561633431313466396563626630323233613661393835
+39633263303434613264636532346165303534636466653563393866646332396534393061623531
+34303938313534303961353130353933306663613663343139646630643037386139353530396166
+32633238316361376562616535353661633635393931613865323338333431626262343661613733
+31393632313831353036353731306638336663303430306565626636376663623132633135636162
+36643266353463376635333139633637303762333138663264373963356136653338616634636463
+32363465343365636638353732623361653833656333663135653765313335376432376535643838
+65653630616639343639646234626466313633303965643530306163333735323830663762663037
+35616430623836363730366630643034633765373937336133353138623533346337373635636638
+36616236616234343661333661643936343030653365653130376633613562383864663534633561
+30353132303237313161353961303537366164386531656139333761616333356666333831393962
+63333164303062313165353131633463666234323665336666613763373831646233393334326233
+35633636353135396336613866353961633463333038373839353964346138383832383135326237
+30623438313861353166353534346161386135313962353262326133326538336163653335306664
+66613030666637363638613664323638626566633230343531653533336563366536336564613638
+34666237373430303964626331373030356462386535373132393763646361306231363937313430
+39613762323337383665396539643261663336643339373333623031353332373937306661623734
+61323965313332313632316231623166346365353631653665383264633634623564623731656435
+32323462636565663532373763343637613466393663393164353036323766643334623531393734
+66623063623839643130343630366162373731336461366165353932613563363231633732383531
+63393939393362633336333836356439313735666161616561623737333566333935363866653639
+62663937313134316333326461313764336236613231393966323466643639663861373463326464
+35313531393933316238353735666531333135303263633266623465313262343939373234376664
+66306630303933653761363439646366613432373562656263346633616538306263656431366631
+36313238333033303636346564383330303666336539363962386233623362333034366638653139
+30623964373838333931346134353964326563656430656635336332363961333932323661653631
+37343635353861333032316564303933616438323933653238343831613631333037643637393165
+34313466393638303833316130303234646132346533656465643632376538393065343663383430
+61313831396164333134363264616566353361633136376637613235626266666438633831303362
+31376362343561383462633264653961636365326465616133633735363934373737633166316435
+63613039666439306631616631306631633734346534313535353231633032666439613861643335
+61363362643336303236383433366233663036386132636433626233613365326637353733316139
+37653831363763366631356632386538623331643163633065613332346431633935393462303031
+3336