├── .gitignore ├── roles ├── network │ ├── templates │ │ ├── hostname.cnmac1.j2 │ │ ├── hostname.cnmac2.j2 │ │ ├── hostname.vether0.j2 │ │ ├── hostname.cnmac0.j2 │ │ ├── hostname.bridge0.j2 │ │ └── dhclient.conf.j2 │ └── tasks │ │ └── main.yml ├── router │ ├── templates │ │ ├── rad.conf.j2 │ │ └── resolv.conf.tail.j2 │ └── tasks │ │ └── main.yml ├── dhcp6c │ ├── templates │ │ ├── dhcp6c.j2 │ │ └── dhcp6c.conf.j2 │ └── tasks │ │ └── main.yml ├── pf │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── pf.conf.j2 ├── install │ └── tasks │ │ └── main.yml ├── dhcpd │ ├── templates │ │ └── dhcpd.conf.j2 │ └── tasks │ │ └── main.yml ├── unbound │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── unbound.conf.j2 └── dhcpcd │ └── tasks │ └── main.yml ├── Pipfile ├── ansible.cfg ├── hosts ├── ssh_config.example ├── LICENSE ├── Makefile ├── play-example.yml ├── README.md └── Pipfile.lock /.gitignore: -------------------------------------------------------------------------------- 1 | play-sensitive* 2 | *.retry 3 | prod 4 | -------------------------------------------------------------------------------- /roles/network/templates/hostname.cnmac1.j2: -------------------------------------------------------------------------------- 1 | up 2 | -------------------------------------------------------------------------------- /roles/network/templates/hostname.cnmac2.j2: -------------------------------------------------------------------------------- 1 | up 2 | -------------------------------------------------------------------------------- /roles/router/templates/rad.conf.j2: -------------------------------------------------------------------------------- 1 | interface vether0 2 | -------------------------------------------------------------------------------- /roles/network/templates/hostname.vether0.j2: -------------------------------------------------------------------------------- 1 | inet {{ vether0_ip }} {{ vether0_netmask }} {{ vether0_broadcast }} 2 | -------------------------------------------------------------------------------- /roles/router/templates/resolv.conf.tail.j2: -------------------------------------------------------------------------------- 1 | search {{ domain }} 2 | nameserver ::1 3 | nameserver 127.0.0.1 4 | lookup file bind 5 | -------------------------------------------------------------------------------- /roles/network/templates/hostname.cnmac0.j2: -------------------------------------------------------------------------------- 1 | dhcp lladdr {{ cnmac0_override_mac }} 2 | up 3 | inet6 autoconf 4 | !/usr/sbin/rcctl start dhcpcd 5 | -------------------------------------------------------------------------------- /roles/network/templates/hostname.bridge0.j2: -------------------------------------------------------------------------------- 1 | add vether0 2 | add cnmac1 3 | add cnmac2 4 | blocknonip vether0 5 | blocknonip cnmac1 6 | blocknonip cnmac2 7 | up 8 | -------------------------------------------------------------------------------- /roles/dhcp6c/templates/dhcp6c.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | daemon="/usr/local/sbin/dhcp6c" 4 | 5 | . /etc/rc.d/rc.subr 6 | 7 | rc_reload=NO 8 | 9 | rc_cmd $1 10 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | 3 | url = "https://pypi.python.org/simple" 4 | verify_ssl = true 5 | name = "pypi" 6 | 7 | 8 | [packages] 9 | 10 | ansible = "*" 11 | 12 | 13 | [dev-packages] 14 | 15 | -------------------------------------------------------------------------------- /roles/dhcp6c/templates/dhcp6c.conf.j2: -------------------------------------------------------------------------------- 1 | interface cnmac0 { 2 | send ia-pd 0; 3 | }; 4 | 5 | id-assoc pd 0 { 6 | prefix ::/64 infinity; 7 | prefix-interface vether0 { 8 | sla-id 1; 9 | sla-len 0; 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /roles/network/templates/dhclient.conf.j2: -------------------------------------------------------------------------------- 1 | send host-name "{{ hostname }}"; 2 | ignore domain-name-servers; 3 | supersede domain-name-servers 127.0.0.1; 4 | ignore domain-name; 5 | supersede domain-name "{{ domain }}"; 6 | supersede host-name "{{ hostname }}"; 7 | -------------------------------------------------------------------------------- /roles/pf/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: copy pf rules 3 | template: 4 | src: pf.conf.j2 5 | dest: /etc/pf.conf 6 | register: pfrules 7 | become: yes 8 | 9 | - name: reload pf config 10 | shell: pfctl -f /etc/pf.conf 11 | when: pfrules.changed 12 | become: yes 13 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory=./hosts 3 | #hosts=ubnts 4 | remote_user=ubnt 5 | host_key_checking=False 6 | # increase timeout as ssh can be really, really slow on erl 7 | timeout=45 8 | transport=smart 9 | 10 | [paramiko] 11 | record_host_keys=True 12 | 13 | [privilege_escalation] 14 | become_method=su 15 | become_user=root 16 | become_ask_pass=True 17 | -------------------------------------------------------------------------------- /hosts: -------------------------------------------------------------------------------- 1 | [example-init] 2 | example-setup ansible_python_interpreter=/usr/local/bin/python3 3 | 4 | [example] 5 | example-admin ansible_python_interpreter=/usr/local/bin/python3 6 | 7 | [erls-init] 8 | erl-setup ansible_python_interpreter=/usr/local/bin/python3 9 | 10 | [erls] 11 | erl-admin ansible_python_interpreter=/usr/local/bin/python3 12 | 13 | [usgs-init] 14 | usg-setup ansible_python_interpreter=/usr/local/bin/python3 15 | 16 | [usgs] 17 | usg-admin ansible_python_interpreter=/usr/local/bin/python3 18 | -------------------------------------------------------------------------------- /roles/install/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dhcpcd 3 | openbsd_pkg: 4 | state: latest 5 | name: dhcpcd 6 | become: yes 7 | 8 | - name: install curl 9 | openbsd_pkg: 10 | state: latest 11 | name: curl 12 | become: yes 13 | 14 | # ntpd doesn't start if ntpd_flags=YES is in /etc/rc.conf.local 15 | - name: remove ntpd_flags=YES from /etc/rc.conf.local 16 | lineinfile: 17 | state: absent 18 | path: /etc/rc.conf.local 19 | regexp: '^ntpd_flags=YES' 20 | become: yes 21 | 22 | - name: enable ntpd 23 | shell: rcctl enable ntpd 24 | become: yes 25 | -------------------------------------------------------------------------------- /roles/dhcpd/templates/dhcpd.conf.j2: -------------------------------------------------------------------------------- 1 | authoritative; 2 | option domain-name "{{ domain }}"; 3 | option routers {{ vether0_ip }}; 4 | option broadcast-address {{ vether0_broadcast }}; 5 | option domain-name-servers {{ vether0_ip }}; 6 | default-lease-time 43200; 7 | max-lease-time 90000; 8 | 9 | subnet {{ vether0_octet_1 }}.{{ vether0_octet_2 }}.{{ vether0_octet_3 }}.0 netmask {{ vether0_netmask }} { 10 | range {{ vether0_octet_1 }}.{{ vether0_octet_2 }}.{{ vether0_octet_3 }}.21 {{ vether0_octet_1 }}.{{ vether0_octet_2 }}.{{ vether0_octet_3 }}.200; 11 | } 12 | 13 | {% for item in dns_records %} 14 | host {{ item.hostname }} { 15 | hardware ethernet {{ item.macaddr }}; 16 | fixed-address {{ item.ipv4addr }}; 17 | } 18 | 19 | {% endfor %} 20 | -------------------------------------------------------------------------------- /ssh_config.example: -------------------------------------------------------------------------------- 1 | Host erl-setup 2 | HostName CHANGEME 3 | Port 22 4 | User ubnt 5 | AddressFamily inet 6 | CheckHostIP no 7 | StrictHostKeyChecking no 8 | IdentityFile ~/.ssh/id_rsa 9 | 10 | Host erl-admin 11 | HostName CHANGEME 12 | Port 22 13 | User ubnt 14 | AddressFamily inet 15 | CheckHostIP no 16 | StrictHostKeyChecking no 17 | IdentityFile ~/.ssh/id_rsa 18 | 19 | Host usg-setup 20 | HostName CHANGEME 21 | Port 22 22 | User ubnt 23 | AddressFamily inet 24 | CheckHostIP no 25 | StrictHostKeyChecking no 26 | IdentityFile ~/.ssh/id_rsa 27 | 28 | Host usg-admin 29 | HostName CHANGEME 30 | Port 22 31 | User ubnt 32 | AddressFamily inet 33 | CheckHostIP no 34 | StrictHostKeyChecking no 35 | IdentityFile ~/.ssh/id_rsa 36 | -------------------------------------------------------------------------------- /roles/dhcp6c/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: touch file /etc/rc.conf.local 3 | file: 4 | dest: /etc/rc.conf.local 5 | owner: root 6 | group: wheel 7 | state: touch 8 | become: yes 9 | 10 | - name: insert dhcp6c_flags=cnmac0 in /etc/rc.conf.local 11 | lineinfile: 12 | state: present 13 | dest: /etc/rc.conf.local 14 | regexp: '^dhcp6c_flags=' 15 | line: 'dhcp6c_flags=cnmac0' 16 | become: yes 17 | 18 | - name: insert dhcp6c restart in /etc/hostname.cnmac0 19 | lineinfile: 20 | state: present 21 | dest: /etc/hostname.cnmac0 22 | insertafter: EOF 23 | line: '!/usr/sbin/rcctl restart dhcp6c' 24 | become: yes 25 | 26 | - name: copy dhcp6c.conf 27 | template: 28 | src: dhcp6c.conf.j2 29 | dest: /etc/dhcp6c.conf 30 | become: yes 31 | 32 | - name: copy dhcp6c 33 | template: 34 | src: dhcp6c.j2 35 | dest: /etc/rc.d/dhcp6c 36 | mode: "0555" 37 | become: yes 38 | 39 | - name: enable dhcp6c 40 | shell: rcctl enable dhcp6c 41 | become: yes 42 | 43 | - name: restart dhcp6c 44 | shell: rcctl restart dhcp6c 45 | become: yes 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Hamza Sheikh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /roles/unbound/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: insert unbound_flags="" in /etc/rc.conf.local 3 | lineinfile: 4 | state: present 5 | path: /etc/rc.conf.local 6 | regexp: '^unbound_flags=' 7 | line: 'unbound_flags=""' 8 | register: unboundflags 9 | become: yes 10 | 11 | - name: copy unbound conf 12 | template: 13 | src: unbound.conf.j2 14 | dest: /var/unbound/etc/unbound.conf 15 | owner: root 16 | group: wheel 17 | mode: "0644" 18 | register: unboundconf 19 | become: yes 20 | 21 | - name: enable unbound 22 | shell: rcctl enable unbound 23 | when: unboundconf.changed or unboundflags.changed 24 | become: yes 25 | 26 | - name: check unbound is running 27 | shell: rcctl check unbound 28 | register: unboundisup 29 | ignore_errors: True 30 | become: yes 31 | 32 | - name: start unbound 33 | shell: rcctl start unbound 34 | when: unboundisup.rc|int != 0 35 | register: startunbound 36 | become: yes 37 | 38 | - name: restart unbound 39 | shell: rcctl restart rad 40 | when: unboundisup.rc|int == 0 and (unboundflags.changed or unboundconf.changed) 41 | register: restartunbound 42 | become: yes 43 | -------------------------------------------------------------------------------- /roles/dhcpd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: copy dhcpd conf 3 | template: 4 | src: dhcpd.conf.j2 5 | dest: /etc/dhcpd.conf 6 | register: dhcpdconf 7 | become: yes 8 | 9 | - name: touch /etc/rc.conf.local 10 | file: 11 | path: /etc/rc.conf.local 12 | owner: root 13 | group: wheel 14 | state: touch 15 | become: yes 16 | 17 | - name: insert dhcpd_flags="vether0" in /etc/rc.conf.local 18 | lineinfile: 19 | state: present 20 | path: /etc/rc.conf.local 21 | regexp: '^dhcpd_flags=' 22 | line: 'dhcpd_flags="vether0"' 23 | register: dhcpdflags 24 | become: yes 25 | 26 | - name: enable dhcpd 27 | shell: rcctl enable dhcpd 28 | when: dhcpdconf.changed or dhcpdflags.changed 29 | become: yes 30 | 31 | 32 | - name: check dhcpd is running 33 | shell: rcctl check dhcpd 34 | register: dhcpdisup 35 | ignore_errors: True 36 | become: yes 37 | 38 | - name: start dhcpd 39 | shell: rcctl start dhcpd 40 | when: dhcpdisup.rc|int != 0 41 | register: startdhcpd 42 | become: yes 43 | 44 | - name: restart dhcpd 45 | shell: rcctl restart dhcpd 46 | when: dhcpdisup.rc|int == 0 and (dhcpdconf.changed or dhcpdflags.changed) 47 | register: restartdhcpd 48 | become: yes 49 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: usage 2 | usage: 3 | @echo make init 4 | @echo make example-setup 5 | @echo make example 6 | @echo make erl-setup 7 | @echo make erl 8 | @echo make usg-setup 9 | @echo make usg 10 | 11 | .PHONY: init 12 | init: 13 | pipenv install 14 | 15 | .PHONY: example-setup 16 | example-setup: 17 | ssh-copy-id -i ~/.ssh/id_rsa example-setup 18 | pipenv run ansible --module-name raw --args "python3 --version || /usr/sbin/pkg_add -U -I -x python%3" --become example-init 19 | # https://stackoverflow.com/a/40866911 20 | pipenv run ansible-playbook play-sensitive-erl.yml --extra-vars "host_group=example-init" 21 | 22 | .PHONY: example 23 | example: 24 | pipenv run ansible-playbook play-example.yml --extra-vars "host_group=example" 25 | 26 | .PHONY: erl-setup 27 | erl-setup: 28 | ssh-copy-id -i ~/.ssh/id_rsa erl-setup 29 | pipenv run ansible --module-name raw --args "python3 --version || /usr/sbin/pkg_add -U -I -x python-3.7.4" --become erls-init 30 | # https://stackoverflow.com/a/40866911 31 | pipenv run ansible-playbook play-sensitive-erl.yml --extra-vars "host_group=erls-init" 32 | 33 | .PHONY: erl 34 | erl: 35 | pipenv run ansible-playbook play-sensitive-erl.yml --extra-vars "host_group=erls" 36 | 37 | .PHONY: usg-setup 38 | usg-setup: 39 | ssh-copy-id -i ~/.ssh/id_rsa usg-setup 40 | pipenv run ansible --module-name raw --args "/usr/sbin/pkg_add -U -I -x python%3" --become usgs-init 41 | # https://stackoverflow.com/a/40866911 42 | pipenv run ansible-playbook play-sensitive-usg.yml --extra-vars "host_group=usgs-init" 43 | 44 | .PHONY: usg 45 | usg: 46 | pipenv run ansible-playbook play-sensitive-usg.yml --extra-vars "host_group=usgs" 47 | -------------------------------------------------------------------------------- /play-example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: "{{ host_group }}" 3 | roles: 4 | - role: install 5 | - role: network 6 | - role: dhcpcd 7 | - role: unbound 8 | interfaces: 9 | - "127.0.0.1" 10 | - "::1" 11 | - "{{ vether0_ip }}" 12 | - "::0" 13 | - role: dhcpd 14 | - role: router 15 | - role: pf 16 | vars: 17 | hostname: "erl" 18 | domain: "home.lan" 19 | cnmac0_override_mac: "OV:ER:RI:DE:00:00" 20 | cnmac0_original_mac: "OR:IG:IN:AL:00:00" 21 | vether0_octet_1: "192" 22 | vether0_octet_2: "168" 23 | vether0_octet_3: "1" 24 | vether0_ip: "192.168.1.1" 25 | vether0_netmask: "255.255.255.0" 26 | vether0_broadcast: "192.168.1.255" 27 | dns_forwarders_mixed: 28 | - ipaddr: "1.0.0.1" 29 | org: "CloudFlare" 30 | - ipaddr: "9.9.9.9" 31 | org: "Quad9" 32 | - ipaddr: "2001:558:FEED::2" 33 | org: "Comcast" 34 | - ipaddr: "149.112.112.112" 35 | org: "Quad9" 36 | - ipaddr: "8.8.8.8" 37 | org: "Google" 38 | - ipaddr: "1.1.1.1" 39 | org: "CloudFlare" 40 | - ipaddr: "75.75.76.76" 41 | org: "Comcast" 42 | - ipaddr: "2001:4860:4860::8844" 43 | org: "Google" 44 | - ipaddr: "37.235.1.174" 45 | org: "freedns.zone" 46 | - ipaddr: "208.67.222.222" 47 | org: "OpenDNS - https://en.wikipedia.org/wiki/OpenDNS" 48 | - ipaddr: "2001:1608:10:25::9249:d69b" 49 | org: "dns.watch" 50 | - ipaddr: "84.200.69.80" 51 | org: "dns.watch" 52 | dns_records: 53 | - hostname: "device1" 54 | ipv4addr: "192.168.1.55" 55 | macaddr: "00:00:00:00:be:ef" 56 | - hostname: "device2" 57 | macaddr: "00:00:00:01:be:ef" 58 | ipv4addr: "192.168.1.97" 59 | -------------------------------------------------------------------------------- /roles/network/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: copy dhclient.conf 3 | template: 4 | src: dhclient.conf.j2 5 | dest: /etc/dhclient.conf 6 | mode: 0640 7 | become: yes 8 | 9 | # Helped by 10 | # http://openbsd-archive.7691.n7.nabble.com/Adding-default-IPv6-route-fails-on-6-1-td316186.html 11 | - name: copy hostname.cnmac0 12 | template: 13 | src: hostname.cnmac0.j2 14 | dest: /etc/hostname.cnmac0 15 | mode: 0640 16 | register: cnmac0conf 17 | become: yes 18 | 19 | - name: copy hostname.cnmac1 20 | template: 21 | src: hostname.cnmac1.j2 22 | dest: /etc/hostname.cnmac1 23 | mode: 0640 24 | register: cnmac1conf 25 | become: yes 26 | 27 | - name: copy hostname.cnmac2 28 | template: 29 | src: hostname.cnmac2.j2 30 | dest: /etc/hostname.cnmac2 31 | mode: 0640 32 | register: cnmac2conf 33 | become: yes 34 | 35 | - name: copy hostname.vether0 36 | template: 37 | src: hostname.vether0.j2 38 | dest: /etc/hostname.vether0 39 | mode: 0640 40 | register: vether0conf 41 | become: yes 42 | 43 | - name: copy hostname.bridge0 44 | template: 45 | src: hostname.bridge0.j2 46 | dest: /etc/hostname.bridge0 47 | mode: 0640 48 | register: bridge0conf 49 | become: yes 50 | 51 | - name: restart cnmac1 52 | shell: sh /etc/netstart cnmac1 53 | ignore_errors: false 54 | when: cnmac1conf.changed 55 | become: yes 56 | 57 | - name: restart cnmac2 58 | shell: sh /etc/netstart cnmac2 59 | ignore_errors: false 60 | when: cnmac2conf.changed 61 | become: yes 62 | 63 | - name: restart vether0 64 | shell: sh /etc/netstart vether0 65 | ignore_errors: false 66 | when: vether0conf.changed 67 | become: yes 68 | 69 | - name: restart bridge0 70 | shell: sh /etc/netstart bridge0 71 | ignore_errors: false 72 | when: bridge0conf.changed 73 | become: yes 74 | -------------------------------------------------------------------------------- /roles/router/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: copy resolv.conf.tail 3 | template: 4 | src: resolv.conf.tail.j2 5 | dest: /etc/resolv.conf.tail 6 | become: yes 7 | 8 | - name: touch file /etc/sysctl.conf 9 | file: 10 | dest: /etc/sysctl.conf 11 | owner: root 12 | group: wheel 13 | state: touch 14 | become: yes 15 | 16 | - name: insert net.inet.ip.forwarding=1 in /etc/sysctl.conf 17 | lineinfile: 18 | state: present 19 | path: /etc/sysctl.conf 20 | regexp: '^net.inet.ip.forwarding=1' 21 | line: 'net.inet.ip.forwarding=1' 22 | register: ipv4forward 23 | become: yes 24 | 25 | - name: insert net.inet6.ip6.forwarding=1 in /etc/sysctl.conf 26 | lineinfile: 27 | state: present 28 | path: /etc/sysctl.conf 29 | regexp: '^net.inet6.ip6.forwarding=1' 30 | line: 'net.inet6.ip6.forwarding=1' 31 | register: ipv6forward 32 | become: yes 33 | 34 | - name: load newly added sysctl values 35 | shell: xargs sysctl < /etc/sysctl.conf 36 | when: ipv4forward.changed or ipv6forward.changed 37 | become: yes 38 | 39 | - name: insert rad_flags="" in /etc/rc.conf.local 40 | lineinfile: 41 | state: present 42 | path: /etc/rc.conf.local 43 | regexp: '^rad_flags=' 44 | line: 'rad_flags=' 45 | register: radflags 46 | become: yes 47 | 48 | - name: copy rad conf 49 | template: 50 | src: rad.conf.j2 51 | dest: /etc/rad.conf 52 | owner: root 53 | group: wheel 54 | mode: "0644" 55 | register: radconf 56 | become: yes 57 | 58 | - name: enable rad 59 | shell: rcctl enable rad 60 | when: radflags.changed or radconf.changed 61 | become: yes 62 | 63 | - name: check rad is running 64 | shell: rcctl check rad 65 | register: radisup 66 | ignore_errors: True 67 | become: yes 68 | 69 | - name: start rad 70 | shell: rcctl start rad 71 | when: radisup.rc|int != 0 72 | register: startrad 73 | become: yes 74 | 75 | - name: restart rad 76 | shell: rcctl restart rad 77 | when: radisup.rc|int == 0 and (radflags.changed or radconf.changed) 78 | register: restartrad 79 | become: yes 80 | 81 | # This may not actually be needed because OpenBSD moved away from rtadvd to rad 82 | # Adding it here because of superstitious reasons because adding this file 83 | # appeared to make IPv6 prefix delegation and SLAAC work on the LAN 84 | - name: touch /etc/rtadvd.conf 85 | file: 86 | path: /etc/rtadvd.conf 87 | state: touch 88 | owner: root 89 | group: wheel 90 | mode: '0664' 91 | become: yes 92 | -------------------------------------------------------------------------------- /roles/dhcpcd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ignore resolv.conf in /etc/dhcpcd.conf 3 | lineinfile: 4 | state: present 5 | path: /etc/dhcpcd.conf 6 | regexp: '^nohook resolv.conf' 7 | line: 'nohook resolv.conf' 8 | insertafter: EOF 9 | register: dhcpcdconf1 10 | become: yes 11 | 12 | - name: enable lease release on dhcpd shutdown in /etc/dhcpcd.conf 13 | lineinfile: 14 | state: present 15 | path: /etc/dhcpcd.conf 16 | regexp: '^release' 17 | line: 'release' 18 | insertafter: '^nohook resolv.conf' 19 | register: dhcpcdconf2 20 | become: yes 21 | 22 | - name: ignore cnmac1 and cnmac2 handling in /etc/dhcpcd.conf 23 | lineinfile: 24 | state: present 25 | path: /etc/dhcpcd.conf 26 | regexp: '^denyinterfaces cnmac1 cnmac2 vether0' 27 | line: 'denyinterfaces cnmac1 cnmac2 vether0' 28 | insertafter: '^release' 29 | register: dhcpcdconf3 30 | become: yes 31 | 32 | - name: disable ipv4 handling in /etc/dhcpcd.conf 33 | lineinfile: 34 | state: present 35 | path: /etc/dhcpcd.conf 36 | regexp: '^noipv4' 37 | line: 'noipv4' 38 | insertafter: '^denyinterfaces cnmac1 cnmac2 vether0' 39 | register: dhcpcdconf4 40 | become: yes 41 | 42 | - name: disable ipv6rs in /etc/dhcpcd.conf 43 | lineinfile: 44 | state: present 45 | path: /etc/dhcpcd.conf 46 | regexp: '^noipv6rs' 47 | line: 'noipv6rs' 48 | insertafter: '^noipv4' 49 | register: dhcpcdconf5 50 | become: yes 51 | 52 | - name: insert cnmac0 line 1 in /etc/dhcpcd.conf 53 | lineinfile: 54 | state: present 55 | path: /etc/dhcpcd.conf 56 | regexp: '^interface cnmac0' 57 | line: 'interface cnmac0' 58 | insertafter: '^noipv6rs' 59 | register: dhcpcdconf6 60 | become: yes 61 | 62 | - name: insert cnmac0 line 2 in /etc/dhcpcd.conf 63 | lineinfile: 64 | state: present 65 | path: /etc/dhcpcd.conf 66 | regexp: '^ ipv6rs' 67 | line: ' ipv6rs' 68 | insertafter: '^interface cnmac0' 69 | register: dhcpcdconf7 70 | become: yes 71 | 72 | - name: insert cnmac0 line 3 in /etc/dhcpcd.conf 73 | lineinfile: 74 | state: present 75 | path: /etc/dhcpcd.conf 76 | regexp: '^ ia_na 1' 77 | line: ' ia_na 1' 78 | insertafter: '^ ipv6rs' 79 | register: dhcpcdconf8 80 | become: yes 81 | 82 | - name: insert internal interface line 1 in /etc/dhcpcd.conf 83 | lineinfile: 84 | state: present 85 | path: /etc/dhcpcd.conf 86 | regexp: '^ ia_pd 2 vether0/0/64' 87 | line: ' ia_pd 2 vether0/0/64' 88 | insertafter: '^ ia_na 1' 89 | register: dhcpcdconf9 90 | become: yes 91 | 92 | - name: touch /etc/rc.conf.local 93 | file: 94 | path: /etc/rc.conf.local 95 | owner: root 96 | group: wheel 97 | state: touch 98 | become: yes 99 | 100 | - name: insert pkg_scripts=dhcpcd in /etc/rc.conf.local 101 | lineinfile: 102 | state: present 103 | path: /etc/rc.conf.local 104 | regexp: '^pkg_scripts=' 105 | line: 'pkg_scripts=dhcpcd' 106 | register: dhcpcdflags 107 | become: yes 108 | 109 | - name: enable dhcpcd 110 | shell: rcctl enable dhcpcd 111 | when: dhcpcdconf1.changed or dhcpcdconf2.changed or dhcpcdconf3.changed or dhcpcdconf4.changed or dhcpcdconf5.changed or dhcpcdconf6.changed or dhcpcdconf7.changed or dhcpcdconf8.changed or dhcpcdconf9.changed 112 | become: yes 113 | 114 | - name: check dhcpcd is running 115 | shell: rcctl check dhcpcd 116 | register: dhcpcdisup 117 | ignore_errors: True 118 | become: yes 119 | 120 | - name: start dhcpcd 121 | shell: rcctl start dhcpcd 122 | when: dhcpcdisup.rc|int != 0 123 | register: startdhcpcd 124 | ignore_errors: True 125 | become: yes 126 | 127 | - name: restart dhcpcd 128 | shell: rcctl restart dhcpcd 129 | # when: (startdhcpcd.rc|int != 0 and "dhcpcd(failed)" in startdhcpcd.stdout) or (dhcpcdisup.rc|int == 0 and (dhcpcdconf1.changed or dhcpcdconf2.changed or dhcpcdconf3.changed or dhcpcdconf4.changed or dhcpcdconf5.changed or dhcpcdconf6.changed or dhcpcdconf7.changed or dhcpcdconf8.changed)) 130 | when: dhcpcdisup.rc|int == 0 and (dhcpcdconf1.changed or dhcpcdconf2.changed or dhcpcdconf3.changed or dhcpcdconf4.changed or dhcpcdconf5.changed or dhcpcdconf6.changed or dhcpcdconf7.changed or dhcpcdconf8.changed or dhcpcdconf9.changed) 131 | register: restartdhcpcd 132 | become: yes 133 | -------------------------------------------------------------------------------- /roles/pf/templates/pf.conf.j2: -------------------------------------------------------------------------------- 1 | ### ~~~ Interface layout ~~~ ### 2 | 3 | # cnmac0: 802.3ab (ethernet) to cable modem 4 | # cnmac1: 802.3ab (ethernet) to internal switch 5 | # cnmac2: 802.3ab (ethernet) to internal switch 6 | # vether0: persists address {{ vether0_octet_1 }}.{{ vether0_octet_2 }}.{{ vether0_octet_3 }}.0/{{ vether0_netmask }} 7 | # bridge0: Ethernet bridge over cnmac1 and cnmac2 8 | # pflog0: target interface for blocked packets 9 | 10 | ### ~~~ Constants and variables ~~~ ### 11 | 12 | # All addresses associated with this host 13 | self = "{ (egress), (vether0) }" 14 | 15 | self_lan = "{ (vether0) }" 16 | 17 | # RFC 6890: Special-Purpose IP Address Registries: 18 | # https://www.iana.org/assignments/iana-ipv4-special-registry/ 19 | # https://www.iana.org/assignments/iana-ipv6-special-registry/ 20 | 21 | # Included below are all address blocks with either Forwardable = False, 22 | # Global = False, or both, but excluding 2001::/23 because it is often 23 | # superseded by more specific allocations, as of 2015-08-05. 24 | 25 | table const { \ 26 | 0.0.0.0/8, \ 27 | 10.0.0.0/8, \ 28 | 100.64.0.0/10, \ 29 | 127.0.0.0/8, \ 30 | 169.254.0.0/16, \ 31 | 172.16.0.0/12, \ 32 | 192.0.0.0/24, \ 33 | 192.0.2.0/24, \ 34 | 192.168.0.0/16, \ 35 | 198.18.0.0/15, \ 36 | 198.51.100.0/24, \ 37 | 203.0.113.0/24, \ 38 | 240.0.0.0/4, \ 39 | 255.255.255.255/32, \ 40 | ::1/128, \ 41 | ::/128, \ 42 | ::ffff:0:0/96, \ 43 | 100::/64, \ 44 | 2001::/32, \ 45 | 2001:2::/48, \ 46 | 2001:db8::/32, \ 47 | fc00::/7 \ 48 | } 49 | 50 | ### ~~~ Default rules ~~~ ### 51 | 52 | # Never touch loopback interfaces 53 | set skip on lo 54 | 55 | # Normalise packets, especially IPv4 DF and Identification 56 | match in all scrub (no-df random-id) 57 | 58 | # Limit the MSS on PPPoE to 1440 octets 59 | # match on pppoe0 scrub (max-mss 1440) 60 | 61 | # Block all packets by default, logging them to pflog0 62 | block log 63 | 64 | ### ~~~ Link-scoped services ~~~ ### 65 | 66 | # DHCPv6 client: make IA_PD requests and receive responses to them 67 | pass out log quick on egress inet6 proto udp from (egress) to ff02::1/16 port dhcpv6-server 68 | pass out log quick on egress inet6 proto udp from (egress) to ff02::2/16 port dhcpv6-server 69 | pass in log quick on egress inet6 proto udp from ff02::1/16 port dhcpv6-client 70 | pass in log quick on egress inet6 proto udp from ff02::2/16 port dhcpv6-client 71 | pass in quick on egress inet6 proto udp to (egress) port dhcpv6-client 72 | 73 | ### ~~~ Bulk pass rules ~~~ ### 74 | 75 | # Pass all traffic on internal interfaces 76 | # vether0 is necessary here, but bridge0 is not 77 | pass quick on { vether0 cnmac1 cnmac2 } 78 | 79 | # Pass all outbound IPv6 traffic 80 | pass out quick on egress inet6 from { egress, (vether0:network) } modulate state 81 | 82 | # Pass all outbound IPv4 traffic from this host 83 | pass out quick on egress inet from (egress) modulate state 84 | 85 | # NAT all outbound IPv4 traffic from the rest of our network 86 | pass out quick on egress inet from (vether0:network) nat-to (egress) modulate state 87 | 88 | ### ~~~ Block undesirable traffic ~~~ ### 89 | 90 | # These rules must not precede the DHCPv6 client or NAT rules above 91 | block log quick on egress from { no-route, urpf-failed, } 92 | block log quick on egress to { no-route, } 93 | 94 | ### ~~~ Pass some ICMP and ICMPv6 traffic ~~~ #### 95 | 96 | # Pass all inbound ICMP echo requests 97 | pass quick on { egress vether0 } inet proto icmp icmp-type { echoreq, echorep } 98 | pass quick on { egress vether0 } inet6 proto icmp6 icmp6-type { echoreq, echorep } 99 | 100 | # RFC 4890: Recommendations for Filtering ICMPv6 Messages in Firewalls 101 | pass log quick on { egress vether0 } inet6 proto icmp6 102 | 103 | pass log quick on egress inet6 proto udp from (egress) to fe80::d62c:44ff:fe 104 | pass log quick on egress inet6 proto udp from fe80::d62c:44ff:fe to (egress) 105 | 106 | ### ~~~ Open services on this router ~~~ ### 107 | 108 | # OpenSSH server 109 | pass in on egress proto { tcp, udp } to $self_lan port ssh 110 | 111 | # Allow LAN to access DNS, DHCP, and NTP 112 | pass quick on egress inet proto udp from (vether0:network) to any port { 53, 67, 123 } 113 | pass quick on egress inet proto udp from $self to any port { 53, 67, 123 } 114 | pass quick on egress inet6 proto udp from (vether0:network) to any port { 53, 67, 123, 546 } 115 | pass quick on egress inet6 proto udp from $self to any port { 53, 67, 123, 546 } 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Manage OpenBSD with Ansible 2 | 3 | This repo is a quick start way to begin configuration management with Ansible 4 | of OpenBSD on Ubiquiti EdgeRouter Lite (ERL 3) and/or USG, assuming these: 5 | 6 | - Ansible is installed on your local machine. 7 | - On ERL/USG: 8 | 9 | - You have installed the latest release (6.4 at time of writing) of OpenBSD. 10 | - *root* user has password set. 11 | - A user called *ubnt* exists. 12 | - Network and remote access through ssh on interface cnmac0 (eth0 port on ERL or wan1 on USG) is working. 13 | 14 | - Network 15 | 16 | - IPv4 and IPv6 are functioning and desired at the edge of the network (cable modem in my case). 17 | - You want to override the MAC address of cnmac0 to something else. I wanted to do it so I could swap in multiple gateway devices without needing to contact my service provider. 18 | 19 | # ssh Config 20 | 21 | Configure ssh client config on your local machine. Use *./ssh_config.example* 22 | as needed to configure your *~/.ssh/config* file. 23 | 24 | Modify the IP addresses of your hosts. 25 | 26 | *erl-setup* is a temporary host since it's provided by your existing network's 27 | DHCP on cnmac0 during initial setup on a fresh install of OpenBSD. After setup 28 | we'll use *erl-admin*, which uses the internal IP provided by DHCP from ERL to 29 | your machine when it's connected on cnmac1 or cnmac2 interfaces. 30 | 31 | Same is the case with *usg-setup* and *usg-admin*. 32 | 33 | Why do I differentiate between erl and usg? I have one device of each type and 34 | use two different IP subnets. I run one device in production at all times. Then 35 | I can run the other device as I work on it while still having internet access 36 | through the production network. I can easily swap them as needed. All I have to 37 | do is make sure all devices re-IP when I do so. 38 | 39 | Since I rebuild ERL many times I use **highly insecure** ssh settings. You may 40 | want to use more secure settings for *CheckHostIP*, *StrictHostKeyChecking*, 41 | and *UserKnownHostsFile*, especially when using production boxes. 42 | 43 | Copy ssh key to remote machine, using one or more of the following examples as 44 | needed. 45 | 46 | $ ssh-copy-id -i ~/.ssh/id_rsa erl-setup 47 | $ ssh-copy-id -i ~/.ssh/id_rsa erl-admin 48 | $ ssh-copy-id -i ~/.ssh/id_rsa usg-setup 49 | $ ssh-copy-id -i ~/.ssh/id_rsa usg-admin 50 | 51 | # Ansible Config 52 | 53 | Review my settings in *ansible.cfg* and *hosts* files in this repo. Edit them 54 | as desired. 55 | 56 | # Bootstrap 57 | 58 | Install Python 3 and pipenv on the box running Ansible. 59 | 60 | $ python3 -m pip install --user -U pipenv 61 | 62 | Python 3 is required on OpenBSD to run Ansible. This is done outside of a 63 | playbook because I like it that way. I have not tried running this in a 64 | playbook. 65 | 66 | $ ansible --module-name raw --args "/usr/sbin/pkg_add -U -I -x python%3" --become erl-setup 67 | $ ansible --module-name raw --args "/usr/sbin/pkg_add -U -I -x python%3" --become usg-setup 68 | 69 | Since you've bootstrapped ``pipenv``, you can run ``pipenv run ansible ...``. 70 | 71 | # Playbook 72 | 73 | Look at the example playbook and modify vars as needed before running it. 74 | 75 | $ ansible-playbook play-example.yml 76 | 77 | Since you've bootstrapped ``pipenv``, you can run 78 | ``pipenv run ansible-playbook ...``. 79 | 80 | If your assumptions are different from mine then read all the templates in 81 | various roles and modify them as desired. 82 | 83 | Finally, reboot the device. 84 | 85 | $ ssh erl-setup 86 | erl$ su - 87 | # reboot 88 | 89 | $ ssh usg-setup 90 | usg$ su - 91 | # reboot 92 | 93 | Once the router is working as expected you can use *erl-admin* and/or 94 | *usg-admin* thereafter. 95 | 96 | # Makefile 97 | 98 | If you have ``make`` installed, you can use the provided *Makefile*. Modify it as 99 | needed before continuing. 100 | 101 | Bootstrap ``pipenv``. 102 | 103 | $ make init 104 | 105 | Bootstrap ERL and/or USG by connecting through cnmac0 (WAN interface). 106 | 107 | $ make erl-setup 108 | $ make usg-setup 109 | 110 | Run playbook through cnmac1 or cnmac2 (LAN interface(s)) after initial setup. 111 | This will be required because ssh connections are blocked on WAN interface 112 | after initial setup. 113 | 114 | $ make erl 115 | $ make usg 116 | 117 | # Test the Configuration 118 | 119 | Once the router setup is complete, you may want to test that it's configured 120 | correctly. Below are some ways to test a macOS client after it's connected to 121 | the router. 122 | 123 | ## IPv6 address is assigned 124 | 125 | ifconfig en0 | grep inet6 126 | 127 | ## Find IPv6 gateways 128 | 129 | netstat -rn | grep default | grep '%en0' 130 | 131 | ## Find all IPv6 link-local addresses 132 | 133 | ping6 -c3 -n -I en0 ff02::1 134 | 135 | Source: https://serverfault.com/a/648143 136 | 137 | 138 | ## Find all DNS servers (IPv4 and IPv6) 139 | 140 | scutil --dns 141 | -------------------------------------------------------------------------------- /roles/unbound/templates/unbound.conf.j2: -------------------------------------------------------------------------------- 1 | ## Authoritative, validating, recursive caching DNS 2 | ## modified form of unbound.conf from https://calomel.org retrieved on 2016-10-24 3 | # 4 | server: 5 | # log verbosity 6 | verbosity: 1 7 | 8 | # specify the interfaces to answer queries from by ip-address. The default 9 | # is to listen to localhost (127.0.0.1 and ::1). specify 0.0.0.0 and ::0 to 10 | # bind to all available interfaces. specify every interface[@port] on a new 11 | # 'interface:' labeled line. The listen interfaces are not changed on 12 | # reload, only on restart. 13 | {% for iface in interfaces %} 14 | interface: {{ iface }} 15 | {% endfor %} 16 | 17 | # port to answer queries from 18 | port: 53 19 | 20 | # Enable IPv4, "yes" or "no". 21 | do-ip4: yes 22 | 23 | # Enable IPv6, "yes" or "no". 24 | do-ip6: yes 25 | 26 | prefer-ip6: yes 27 | 28 | # Enable UDP, "yes" or "no". 29 | do-udp: yes 30 | 31 | # Enable TCP, "yes" or "no". If TCP is not needed, Unbound is actually 32 | # quicker to resolve as the functions related to TCP checks are not done.i 33 | # NOTE: you may need tcp enabled to get the DNSSEC results from *.edu domains 34 | # due to their size. 35 | do-tcp: yes 36 | 37 | # control which client ips are allowed to make (recursive) queries to this 38 | # server. Specify classless netblocks with /size and action. By default 39 | # everything is refused, except for localhost. Choose deny (drop message), 40 | # refuse (polite error reply), allow (recursive ok), allow_snoop (recursive 41 | # and nonrecursive ok) 42 | access-control: 10.0.0.0/8 allow 43 | access-control: 127.0.0.0/8 allow 44 | access-control: 192.168.0.0/16 allow 45 | access-control: ::1 allow 46 | 47 | # Read the root hints from this file. Default is nothing, using built in 48 | # hints for the IN class. The file has the format of zone files, with root 49 | # nameserver names and addresses only. The default may become outdated, 50 | # when servers change, therefore it is good practice to use a root-hints 51 | # file. get one from ftp://FTP.INTERNIC.NET/domain/named.cache 52 | #root-hints: "/var/unbound/etc/root.hints" 53 | 54 | # enable to not answer id.server and hostname.bind queries. 55 | hide-identity: yes 56 | 57 | # enable to not answer version.server and version.bind queries. 58 | hide-version: yes 59 | 60 | # Will trust glue only if it is within the servers authority. 61 | # Harden against out of zone rrsets, to avoid spoofing attempts. 62 | # Hardening queries multiple name servers for the same data to make 63 | # spoofing significantly harder and does not mandate dnssec. 64 | harden-glue: yes 65 | 66 | # Require DNSSEC data for trust-anchored zones, if such data is absent, the 67 | # zone becomes bogus. Harden against receiving dnssec-stripped data. If you 68 | # turn it off, failing to validate dnskey data for a trustanchor will trigger 69 | # insecure mode for that zone (like without a trustanchor). Default on, 70 | # which insists on dnssec data for trust-anchored zones. 71 | harden-dnssec-stripped: yes 72 | 73 | # Use 0x20-encoded random bits in the query to foil spoof attempts. 74 | # http://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00 75 | # While upper and lower case letters are allowed in domain names, no significance 76 | # is attached to the case. That is, two names with the same spelling but 77 | # different case are to be treated as if identical. This means calomel.org is the 78 | # same as CaLoMeL.Org which is the same as CALOMEL.ORG. 79 | use-caps-for-id: yes 80 | 81 | # the time to live (TTL) value lower bound, in seconds. Default 0. 82 | # If more than an hour could easily give trouble due to stale data. 83 | cache-min-ttl: 3600 84 | 85 | # the time to live (TTL) value cap for RRsets and messages in the 86 | # cache. Items are not cached for longer. In seconds. 87 | cache-max-ttl: 86400 88 | 89 | # perform prefetching of close to expired message cache entries. If a client 90 | # requests the dns lookup and the TTL of the cached hostname is going to 91 | # expire in less than 10% of its TTL, unbound will (1st) return the ip of the 92 | # host to the client and (2nd) pre-fetch the dns request from the remote dns 93 | # server. This method has been shown to increase the amount of cached hits by 94 | # local clients by 10% on average. 95 | prefetch: yes 96 | 97 | # number of threads to create. 1 disables threading. This should equal the number 98 | # of CPU cores in the machine. Our example machine has 4 CPU cores. 99 | num-threads: 2 100 | 101 | 102 | ## Unbound Optimization and Speed Tweaks ### 103 | 104 | # the number of slabs to use for cache and must be a power of 2 times the 105 | # number of num-threads set above. more slabs reduce lock contention, but 106 | # fragment memory usage. 107 | #msg-cache-slabs: 4 108 | #rrset-cache-slabs: 4 109 | #infra-cache-slabs: 4 110 | #key-cache-slabs: 4 111 | 112 | # Increase the memory size of the cache. Use roughly twice as much rrset cache 113 | # memory as you use msg cache memory. Due to malloc overhead, the total memory 114 | # usage is likely to rise to double (or 2.5x) the total cache memory. The test 115 | # box has 4gig of ram so 256meg for rrset allows a lot of room for cacheed objects. 116 | #rrset-cache-size: 256m 117 | #msg-cache-size: 128m 118 | 119 | # buffer size for UDP port 53 incoming (SO_RCVBUF socket option). This sets 120 | # the kernel buffer larger so that no messages are lost in spikes in the traffic. 121 | #so-rcvbuf: 1m 122 | 123 | ## Unbound Optimization and Speed Tweaks ### 124 | 125 | 126 | # Enforce privacy of these addresses. Strips them away from answers. It may 127 | # cause DNSSEC validation to additionally mark it as bogus. Protects against 128 | # 'DNS Rebinding' (uses browser as network proxy). Only 'private-domain' and 129 | # 'local-data' names are allowed to have these private addresses. No default. 130 | private-address: 192.168.0.0/16 131 | private-address: 172.16.0.0/12 132 | private-address: 10.0.0.0/8 133 | 134 | # Allow the domain (and its subdomains) to contain private addresses. 135 | # local-data statements are allowed to contain private addresses too. 136 | private-domain: "{{ domain }}" 137 | 138 | # If nonzero, unwanted replies are not only reported in statistics, but also 139 | # a running total is kept per thread. If it reaches the threshold, a warning 140 | # is printed and a defensive action is taken, the cache is cleared to flush 141 | # potential poison out of it. A suggested value is 10000000, the default is 142 | # 0 (turned off). We think 10K is a good value. 143 | unwanted-reply-threshold: 10000 144 | 145 | # IMPORTANT FOR TESTING: If you are testing and setup NSD or BIND on 146 | # localhost you will want to allow the resolver to send queries to localhost. 147 | # Make sure to set do-not-query-localhost: yes . If yes, the above default 148 | # do-not-query-address entries are present. if no, localhost can be queried 149 | # (for testing and debugging). 150 | do-not-query-localhost: no 151 | 152 | # File with trusted keys, kept up to date using RFC5011 probes, initial file 153 | # like trust-anchor-file, then it stores metadata. Use several entries, one 154 | # per domain name, to track multiple zones. If you use forward-zone below to 155 | # query the Google DNS servers you MUST comment out this option or all DNS 156 | # queries will fail. 157 | # auto-trust-anchor-file: "/var/unbound/etc/root.key" 158 | 159 | # Should additional section of secure message also be kept clean of unsecure 160 | # data. Useful to shield the users of this validator from potential bogus 161 | # data in the additional section. All unsigned data in the additional section 162 | # is removed from secure messages. 163 | val-clean-additional: yes 164 | 165 | # Blocking Ad Server domains. Google's AdSense, DoubleClick and Yahoo 166 | # account for a 70 percent share of all advertising traffic. Block them. 167 | # local-zone: "doubleclick.net" redirect 168 | # local-data: "doubleclick.net A 127.0.0.1" 169 | # local-zone: "googlesyndication.com" redirect 170 | # local-data: "googlesyndication.com A 127.0.0.1" 171 | # local-zone: "googleadservices.com" redirect 172 | # local-data: "googleadservices.com A 127.0.0.1" 173 | # local-zone: "google-analytics.com" redirect 174 | # local-data: "google-analytics.com A 127.0.0.1" 175 | # local-zone: "ads.youtube.com" redirect 176 | # local-data: "ads.youtube.com A 127.0.0.1" 177 | # local-zone: "adserver.yahoo.com" redirect 178 | # local-data: "adserver.yahoo.com A 127.0.0.1" 179 | # local-zone: "ask.com" redirect 180 | # local-data: "ask.com A 127.0.0.1" 181 | 182 | 183 | # Unbound will not load if you specify the same local-zone and local-data 184 | # servers in the main configuration as well as in this "include:" file. We 185 | # suggest commenting out any of the local-zone and local-data lines above if 186 | # you suspect they could be included in the unbound_ad_servers servers file. 187 | #include: "/etc/unbound/unbound_ad_servers" 188 | 189 | # locally served zones can be configured for the machines on the LAN. 190 | 191 | local-zone: "{{ domain }}." static 192 | 193 | {% for item in dns_records %} 194 | local-data: "{{ item.hostname }}.{{ domain }}. IN A {{ item.ipv4addr }}" 195 | {% endfor %} 196 | 197 | {% for item in dns_records %} 198 | local-data-ptr: "{{ item.ipv4addr }} {{ item.hostname }}.{{ domain }}" 199 | {% endfor %} 200 | 201 | # Use the following forward-zone to forward all queries to Google DNS, 202 | # OpenDNS.com or your local ISP's dns servers for example. To test resolution 203 | # speeds use "drill calomel.org @8.8.8.8" and look for the "Query time:" in 204 | # milliseconds. 205 | # 206 | forward-zone: 207 | name: "." 208 | {% for item in dns_forwarders_mixed %} 209 | forward-addr: {{ item.ipaddr }} # {{ item.org }} 210 | {% endfor %} 211 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "014004bba412f1af7eea5fce95f020a6d4f9ef888ff17204b494326262114e81" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": {}, 8 | "sources": [ 9 | { 10 | "name": "pypi", 11 | "url": "https://pypi.python.org/simple", 12 | "verify_ssl": true 13 | } 14 | ] 15 | }, 16 | "default": { 17 | "ansible": { 18 | "hashes": [ 19 | "sha256:d87cb25df02284d59226ff1d935d7075a175f31d0db83564c2f1ca28bbbd4cb4" 20 | ], 21 | "index": "pypi", 22 | "version": "==2.9.1" 23 | }, 24 | "cffi": { 25 | "hashes": [ 26 | "sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42", 27 | "sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04", 28 | "sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5", 29 | "sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54", 30 | "sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba", 31 | "sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57", 32 | "sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396", 33 | "sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12", 34 | "sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97", 35 | "sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43", 36 | "sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db", 37 | "sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3", 38 | "sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b", 39 | "sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579", 40 | "sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346", 41 | "sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159", 42 | "sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652", 43 | "sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e", 44 | "sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a", 45 | "sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506", 46 | "sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f", 47 | "sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d", 48 | "sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c", 49 | "sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20", 50 | "sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858", 51 | "sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc", 52 | "sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a", 53 | "sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3", 54 | "sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e", 55 | "sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410", 56 | "sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25", 57 | "sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b", 58 | "sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d" 59 | ], 60 | "version": "==1.13.2" 61 | }, 62 | "cryptography": { 63 | "hashes": [ 64 | "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c", 65 | "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595", 66 | "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad", 67 | "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651", 68 | "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2", 69 | "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff", 70 | "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d", 71 | "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42", 72 | "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d", 73 | "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e", 74 | "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912", 75 | "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793", 76 | "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13", 77 | "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7", 78 | "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0", 79 | "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879", 80 | "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f", 81 | "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9", 82 | "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2", 83 | "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf", 84 | "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8" 85 | ], 86 | "version": "==2.8" 87 | }, 88 | "jinja2": { 89 | "hashes": [ 90 | "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", 91 | "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de" 92 | ], 93 | "version": "==2.10.3" 94 | }, 95 | "markupsafe": { 96 | "hashes": [ 97 | "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", 98 | "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", 99 | "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", 100 | "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", 101 | "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", 102 | "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", 103 | "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", 104 | "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", 105 | "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", 106 | "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", 107 | "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", 108 | "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", 109 | "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", 110 | "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", 111 | "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", 112 | "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", 113 | "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", 114 | "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", 115 | "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", 116 | "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", 117 | "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", 118 | "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", 119 | "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", 120 | "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", 121 | "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", 122 | "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", 123 | "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", 124 | "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" 125 | ], 126 | "version": "==1.1.1" 127 | }, 128 | "pycparser": { 129 | "hashes": [ 130 | "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3" 131 | ], 132 | "version": "==2.19" 133 | }, 134 | "pyyaml": { 135 | "hashes": [ 136 | "sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9", 137 | "sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4", 138 | "sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8", 139 | "sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696", 140 | "sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34", 141 | "sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9", 142 | "sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73", 143 | "sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299", 144 | "sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b", 145 | "sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae", 146 | "sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681", 147 | "sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41", 148 | "sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8" 149 | ], 150 | "version": "==5.1.2" 151 | }, 152 | "six": { 153 | "hashes": [ 154 | "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", 155 | "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" 156 | ], 157 | "version": "==1.13.0" 158 | } 159 | }, 160 | "develop": {} 161 | } 162 | --------------------------------------------------------------------------------