diff --git a/.gitignore b/.gitignore index cf2926d..1d6ec4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .vagrant/ host_vars/ +/filter_plugins/__pycache__/ +/.ropeproject/ diff --git a/filter_plugins/sysconfig_filters.py b/filter_plugins/sysconfig_filters.py new file mode 100644 index 0000000..33f3fa8 --- /dev/null +++ b/filter_plugins/sysconfig_filters.py @@ -0,0 +1,23 @@ +from ansible.errors import AnsibleFilterTypeError +from ansible.module_utils.six import string_types + + +# Ansible's "quote" filter is only applied to shell module +def quote_single(str): + """ + Quote a string with single quote. + + Example: a string -> 'a string' + """ + if isinstance(str, string_types): + return "'" + str + "'" + else: + raise AnsibleFilterTypeError( + "|quote_single expects string, got %s instead." % type(str)) + + +class FilterModule(object): + """Custom Ansible jinja2 filters for sysconfig playbook.""" + + def filters(self): + return {'quote_single': quote_single} diff --git a/group_vars/all.yml b/group_vars/all.yml index bd59ebd..9648d79 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -10,7 +10,13 @@ usershell: fish repository: https://mirror.math.princeton.edu/pub/alpinelinux -# seatd or elogind +# Additional kernel command-line parameters +kernel_parameters: + - init_on_free=1 + - page_alloc.shuffle=1 + - lockdown=integrity + +# 'seatd' or 'elogind' seat_manager: seatd # busybox's mdev, skarnet's mdevd or eudev's udev @@ -18,11 +24,42 @@ device_manager: mdevd # Have no effect when seat_manager == 'elogind' # See use_polkit variable below -polkit: False +polkit: false # Should be a file name in /usr/share/consolefonts/ console_font: ter-h22b.psf.gz +# 'dnscrypt-proxy' or 'unbound' +dns_resolver: dnscrypt-proxy + +dnscrypt: + adblock: true + server_names: + - quad9-doh-ip4-port443-filter-pri + - quad9-doh-ip6-port443-filter-pri + - quad9-dnscrypt-ip4-filter-pri + ephemeral_keys: true + tls_disable_session_tickets: true + tls_cipher_suite: [52392, 49199] + bootstrap_resolvers: + - 9.9.9.9:53 + - 1.1.1.1:53 + netprobe_address: 9.9.9.9:53 + local_doh: + enabled: false + listen_addresses: + - 127.0.0.1:3012 + path: '/dns-query' + anonymized_dns: # not compatible with DoH and ODoH servers + enabled: false + routes: + - server_name: '*' + via: + - anon-tiarap + - anon-tiarap-ipv6 + - anon-cs-tokyo + - anon-cs-sk + unbound_upstream_nameservers: - 9.9.9.9@853#dns.quad9.net - 149.112.112.112@853#dns.quad9.net @@ -62,7 +99,7 @@ rootless_container_cli: podman # Configure waydroid base image waydroid: rom_type: lineage # lineage, bliss - system_type: FOSS # FOSS, GAPPS, VANILLA + system_type: VANILLA # FOSS, GAPPS, VANILLA # Secrets encrypted with ansible-vault ──────────────────────────────────────── diff --git a/requirements/collections.yml b/requirements/collections.yml index 9dbb90c..8a1167d 100644 --- a/requirements/collections.yml +++ b/requirements/collections.yml @@ -1,4 +1,5 @@ --- collections: - name: community.general + - name: community.crypto - name: ansible.posix diff --git a/roles/acpi/tasks/main.yml b/roles/acpi/tasks/main.yml index 9caabb8..61680db 100644 --- a/roles/acpi/tasks/main.yml +++ b/roles/acpi/tasks/main.yml @@ -5,6 +5,7 @@ service: name: acpid enabled: no + state: stopped - block: - name: acpi | Create custom config directory for logind.conf diff --git a/roles/apparmor/tasks/main.yml b/roles/apparmor/tasks/main.yml index bc6343c..304efb2 100644 --- a/roles/apparmor/tasks/main.yml +++ b/roles/apparmor/tasks/main.yml @@ -24,14 +24,14 @@ runlevel: boot enabled: yes -- name: apparmor | Check whether apparmor kernel parameters is presented in grub +- name: apparmor | Check whether apparmor kernel parameters is presented lineinfile: backup: yes path: /etc/default/grub - regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=".*page_alloc.shuffle=1 init_on_free=1 apparmor=1 security=apparmor' + regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=".*apparmor=.*' state: absent check_mode: yes - register: grub_cmdline_check + register: apparmor_cmdline_check changed_when: no - name: apparmor | Add apparmor to grub boot command if missing @@ -39,9 +39,9 @@ backrefs: yes path: /etc/default/grub regexp: '^(GRUB_CMDLINE_LINUX_DEFAULT=".*)"$' - line: '\1 page_alloc.shuffle=1 init_on_free=1 apparmor=1 security=apparmor"' + line: '\1 apparmor=1 security=apparmor"' owner: root group: root mode: 0644 - when: grub_cmdline_check.found == 0 + when: apparmor_cmdline_check.found == 0 notify: Update grub config diff --git a/roles/devd/templates/51-android.j2 b/roles/devd/templates/51-android.j2 new file mode 100644 index 0000000..6212153 --- /dev/null +++ b/roles/devd/templates/51-android.j2 @@ -0,0 +1,2 @@ +# Galaxy A5 2016 (a5xelte) +SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="6860", MODE="0660", OWNER="{{ username }}", ENV{ID_MTP_DEVICE}="1", SYMLINK+="libmtp" diff --git a/roles/devd/templates/70-uinput-wheel.j2 b/roles/devd/templates/70-uinput-wheel.j2 new file mode 100644 index 0000000..dec9c3f --- /dev/null +++ b/roles/devd/templates/70-uinput-wheel.j2 @@ -0,0 +1 @@ +KERNEL=="uinput", MODE="0660", OWNER="{{ username }}", OPTIONS+="static_node=uinput" diff --git a/roles/devd/templates/70-xp-pen.j2 b/roles/devd/templates/70-xp-pen.j2 new file mode 100644 index 0000000..f67897b --- /dev/null +++ b/roles/devd/templates/70-xp-pen.j2 @@ -0,0 +1 @@ +SUBSYSTEM=="usb", ATTR{idVendor}=="28bd", OWNERS="{{ username }}", TAG+="uaccess" diff --git a/roles/devd/templates/99-calibrate.j2 b/roles/devd/templates/99-calibrate.j2 new file mode 100644 index 0000000..b752191 --- /dev/null +++ b/roles/devd/templates/99-calibrate.j2 @@ -0,0 +1 @@ +ENV{ID_VENDOR_ID}=="10429", ENV{ID_MODEL_ID}=="63754", ENV{WL_OUTPUT}="HDMI-A-1", ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" diff --git a/roles/dns/defaults/main.yml b/roles/dns/defaults/main.yml new file mode 100644 index 0000000..5eb1327 --- /dev/null +++ b/roles/dns/defaults/main.yml @@ -0,0 +1,83 @@ +--- +# Lookup: https://dnscrypt.info/public-servers +# List of servers: +# - https://github.com/DNSCrypt/dnscrypt-resolvers +# - https://github.com/DNSCrypt/dnscrypt-proxy/wiki/DNS-server-sources + +dnscrypt_server_sources: + - name: public-resolvers + urls: + - https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md + - https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md + - https://dnsr.evilvibes.com/v3/public-resolvers.md + - https://cdn.staticaly.com/gh/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md + - https://ipv6.download.dnscrypt.info/resolvers-list/v3/public-resolvers.md + cache_file: /var/cache/dnscrypt-proxy/public-resolvers.md + minisign_key: RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3 + refresh_delay: 72 + prefix: '' + + - name: relays + urls: + - https://download.dnscrypt.info/resolvers-list/v3/relays.md + - https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/relays.md + - https://dnsr.evilvibes.com/v3/relays.md + - https://cdn.staticaly.com/gh/DNSCrypt/dnscrypt-resolvers/master/v3/relays.md + cache_file: /var/cache/dnscrypt-proxy/relays.md + minisign_key: RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3 + refresh_delay: 72 + prefix: '' + + - name: odoh-servers + urls: + - https://download.dnscrypt.info/resolvers-list/v3/odoh-servers.md + - https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-servers.md + - https://dnsr.evilvibes.com/v3/odoh-servers.md + - https://cdn.staticaly.com/gh/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-servers.md + cache_file: /var/cache/dnscrypt-proxy/odoh-servers.md + minisign_key: RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3 + refresh_delay: 24 + prefix: '' + + - name: odoh-relays + urls: + - https://download.dnscrypt.info/resolvers-list/v3/odoh-relays.md + - https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-relays.md + - https://dnsr.evilvibes.com/v3/odoh-relays.md + - https://cdn.staticaly.com/gh/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-relays.md + cache_file: /var/cache/dnscrypt-proxy/odoh-relays.md + minisign_key: RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3 + refresh_delay: 24 + prefix: '' + + - name: opennic + urls: + - https://download.dnscrypt.info/dnscrypt-resolvers/v3/opennic.md + - https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/opennic.md + - https://dnsr.evilvibes.com/v3/opennic.md + - https://cdn.staticaly.com/gh/DNSCrypt/dnscrypt-resolvers/master/v3/opennic.md + cache_file: /var/cache/dnscrypt-proxy/opennic.md + minisign_key: RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3 + refresh_delay: 72 + prefix: '' + + # - name: quad9-resolvers + # urls: + # - https://www.quad9.net/quad9-resolvers.md + # - https://raw.githubusercontent.com/Quad9DNS/dnscrypt-settings/main/dnscrypt/quad9-resolvers.md + # - https://quad9.net/dnscrypt/quad9-resolvers.md + # cache_file: /var/cache/dnscrypt-proxy/quad9.md + # minisign_key: RWQBphd2+f6eiAqBsvDZEBXBGHQBJfeG6G+wJPPKxCZMoEQYpmoysKUN + # refresh_delay: 72 + # prefix: 'quad9-' + + # - name: onion-services + # urls: + # - https://download.dnscrypt.info/dnscrypt-resolvers/v3/onion-services.md + # - https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/onion-services.md + # - https://dnsr.evilvibes.com/v3/onion-services.md + # - https://cdn.staticaly.com/gh/DNSCrypt/dnscrypt-resolvers/master/v3/onion-services.md + # cache_file: /var/cache/dnscrypt-proxy/onion-services.md + # minisign_key: RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3 + # refresh_delay: 72 + # prefix: '' diff --git a/roles/dns/files/blocked-ips.txt b/roles/dns/files/blocked-ips.txt new file mode 100644 index 0000000..660d443 --- /dev/null +++ b/roles/dns/files/blocked-ips.txt @@ -0,0 +1,27 @@ +############################## +# IP blocklist # +############################## + +# Localhost rebinding protection +0.0.0.0 +127.0.0.* + +# RFC1918 rebinding protection +10.* +172.16.* +172.17.* +172.18.* +172.19.* +172.20.* +172.21.* +172.22.* +172.23.* +172.24.* +172.25.* +172.26.* +172.27.* +172.28.* +172.29.* +172.30.* +172.31.* +192.168.* diff --git a/roles/dns/files/cloaking-rules.txt b/roles/dns/files/cloaking-rules.txt new file mode 100644 index 0000000..0ba7135 --- /dev/null +++ b/roles/dns/files/cloaking-rules.txt @@ -0,0 +1,6 @@ +################################ +# Cloaking rules # +################################ + +localhost 127.0.0.1 +localhost ::1 diff --git a/roles/dns/files/domains-blocklist-local-additions.txt b/roles/dns/files/domains-blocklist-local-additions.txt new file mode 100644 index 0000000..31bca2a --- /dev/null +++ b/roles/dns/files/domains-blocklist-local-additions.txt @@ -0,0 +1,31 @@ +# Local set of patterns to block + +ad.* +ads.* +banner.* +banners.* +creatives.* +oas.* +oascentral.* +tag.* +telemetry.* +tracker.* + +# eth0.me is hardcoded in tools such as Archey, but is not available any +# more, causing issues such as terminal sessions taking a long time to +# start. + +eth0.me + +# ibpxl.com is a tracker that seems to frequently have issues, causing +# page loads to stall. + +ibpxl.com + +# ditto for that one + +internetbrands.com + +# Ubuntu's motd script sends way too much information to Canonical + +motd.ubuntu.com diff --git a/roles/dns/files/domains-blocklist.conf b/roles/dns/files/domains-blocklist.conf new file mode 100644 index 0000000..403c35e --- /dev/null +++ b/roles/dns/files/domains-blocklist.conf @@ -0,0 +1,160 @@ +################################################################################## +# # +# Generate a block list of domains using public data sources, and the local # +# domains-blocklist-local-additions.txt file. # +# # +# The default configuration is just indicative, and corresponds to the one # +# used to produce the public "mybase" set. # +# # +# Comment out the URLs of the sources you wish to disable, leave the ones # +# you would like enabled uncommented. Then run the script to build the # +# dnscrypt-blocklist-domains.txt file: # +# # +# $ generate-domains-blocklist.py -o dnscrypt-blocklist-domains.txt # +# # +# Domains that should never be blocked can be put into a file named # +# domains-allowlist.txt. # +# # +# That blocklist file can then be used in the dnscrypt-proxy.toml file: # +# # +# [blocked_names] # +# # +# blocked_names_file = 'dnscrypt-blocklist-domains.txt' # +# # +################################################################################## + +# Local additions +file:/etc/dnscrypt-proxy/adblock/domains-blocklist-local-additions.txt + +# AdAway is an open source ad blocker for Android using the hosts file. +# https://raw.githubusercontent.com/AdAway/adaway.github.io/master/hosts.txt + +# EasyList +https://easylist-downloads.adblockplus.org/easylist_noelemhide.txt + +# EasyList China +# https://easylist-downloads.adblockplus.org/easylistchina.txt + +# RU AdList +# https://easylist-downloads.adblockplus.org/advblock.txt + +# Peter Lowe's Ad and tracking server list +https://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml + +# Spam404 +https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt + +# Malvertising filter list by Disconnect +# https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt + +# Ads filter list by Disconnect +# https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt + +# Basic tracking list by Disconnect +# https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt + +# KAD host file (fraud/adware) +# https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADomains.txt + +# BarbBlock list (spurious and invalid DMCA takedowns) +https://paulgb.github.io/BarbBlock/blacklists/domain-list.txt + +# Dan Pollock's hosts list +https://someonewhocares.org/hosts/hosts + +# NoTracking's list - blocking ads, trackers and other online garbage +https://raw.githubusercontent.com/notracking/hosts-blocklists/master/dnscrypt-proxy/dnscrypt-proxy.blacklist.txt + +# NextDNS CNAME cloaking list +https://raw.githubusercontent.com/nextdns/cname-cloaking-blocklist/master/domains + +# AdGuard Simplified Domain Names filter +https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt + +# Geoffrey Frogeye's block list of first-party trackers - https://hostfiles.frogeye.fr/ +https://hostfiles.frogeye.fr/firstparty-trackers.txt + +# CoinBlockerLists: blocks websites serving cryptocurrency miners - https://gitlab.com/ZeroDot1/CoinBlockerLists/ - Contains false positives +# https://gitlab.com/ZeroDot1/CoinBlockerLists/raw/master/list_browser.txt + +# Websites potentially publishing fake news +# https://raw.githubusercontent.com/marktron/fakenews/master/fakenews + +# Quidsup NoTrack Blocklist - Contains too many false positives to be enabled by default +# https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-blocklist.txt + +# Quidsup Malware Blocklist - Contains too many false positives to be enabled by default +# https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt + +# AntiSocial Blacklist is an extensive collection of potentially malicious domains +# https://theantisocialengineer.com/AntiSocial_Blacklist_Community_V1.txt + +# Steven Black hosts file +https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts + +# A list of adserving and tracking sites maintained by @lightswitch05 +https://www.github.developerdan.com/hosts/lists/ads-and-tracking-extended.txt + +# A list of adserving and tracking sites maintained by @anudeepND +https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt + +# Anudeep's Blacklist (CoinMiner) - Blocks cryptojacking sites +# https://raw.githubusercontent.com/anudeepND/blacklist/master/CoinMiner.txt + +### Spark < Blu Go < Blu < Basic < Ultimate +### (With pornware blocking) Porn < Unified +# Energized Ultimate +# https://block.energized.pro/ultimate/formats/domains.txt + +# Energized Basic +# https://block.energized.pro/basic/formats/domains.txt + +# Energized BLU +# https://block.energized.pro/blu/formats/domains.txt + +# OISD.NL - Blocks ads, phishing, malware, tracking and more. WARNING: this is a huge list. +# https://dblw.oisd.nl/ + +# OISD.NL (smaller subset) - Blocks ads, phishing, malware, tracking and more. Tries to miminize false positives. +https://dblw.oisd.nl/basic/ + +# OISD.NL (extra) - Blocks ads, phishing, malware, tracking and more. Protection over functionality. +# https://dblw.oisd.nl/extra/ + +# Captain Miao ad list - Block ads and trackers, especially Chinese and Android trackers +# https://raw.githubusercontent.com/jdlingyu/ad-wars/master/sha_ad_hosts + +# Phishing Army - https://phishing.army/ +# https://phishing.army/download/phishing_army_blocklist.txt + +# Block pornography +# https://raw.githubusercontent.com/Clefspeare13/pornhosts/master/0.0.0.0/hosts +# https://raw.githubusercontent.com/Sinfonietta/hostfiles/master/pornography-hosts +# https://raw.githubusercontent.com/cbuijs/shallalist/master/porn/domains +# https://raw.githubusercontent.com/olbat/ut1-blacklists/master/blacklists/adult/domains +# https://block.energized.pro/porn/formats/domains.txt +# https://raw.githubusercontent.com/mhxion/pornaway/master/hosts/porn_sites.txt +# https://dblw.oisd.nl/nsfw/ + +# Block gambling sites +# https://raw.githubusercontent.com/Sinfonietta/hostfiles/master/gambling-hosts +# https://raw.githubusercontent.com/olbat/ut1-blacklists/master/blacklists/gambling/domains + +# Block dating websites +# https://raw.githubusercontent.com/olbat/ut1-blacklists/master/blacklists/dating/domains +# https://www.github.developerdan.com/hosts/lists/dating-services-extended.txt + +# Block social media sites +# https://raw.githubusercontent.com/Sinfonietta/hostfiles/master/social-hosts +# https://block.energized.pro/extensions/social/formats/domains.txt +# https://raw.githubusercontent.com/olbat/ut1-blacklists/master/blacklists/social_networks/domains +# https://www.github.developerdan.com/hosts/lists/facebook-extended.txt + +# Goodbye Ads - Specially designed for mobile ad protection +# https://raw.githubusercontent.com/jerryn70/GoodbyeAds/master/Hosts/GoodbyeAds.txt + +# NextDNS BitTorrent blocklist +# https://raw.githubusercontent.com/nextdns/bittorrent-blocklist/master/domains + +# Block spying and tracking on Windows +# https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/dnscrypt/spy.txt diff --git a/roles/unbound/files/hosts b/roles/dns/files/hosts similarity index 100% rename from roles/unbound/files/hosts rename to roles/dns/files/hosts diff --git a/roles/dns/files/update_dnscrypt_blocklist b/roles/dns/files/update_dnscrypt_blocklist new file mode 100644 index 0000000..4e99d10 --- /dev/null +++ b/roles/dns/files/update_dnscrypt_blocklist @@ -0,0 +1,11 @@ +#!/bin/sh + +dnscrypt_dir="/etc/dnscrypt-proxy" +adblock_dir="${dnscrypt_dir}/adblock" + +/usr/bin/python3 "${adblock_dir}"/generate-domains-blocklist.py \ + -i -a /dev/null -r /dev/null \ + -c "${adblock_dir}"/domains-blocklist.conf \ + -o "${dnscrypt_dir}"/blocked-names.txt + +/bin/chmod 0644 "${dnscrypt_dir}"/blocked-names.txt diff --git a/roles/dns/tasks/dnscrypt-proxy.yml b/roles/dns/tasks/dnscrypt-proxy.yml new file mode 100644 index 0000000..618b5a0 --- /dev/null +++ b/roles/dns/tasks/dnscrypt-proxy.yml @@ -0,0 +1,111 @@ +--- +# Firefox needs to be setup manually: +# https://github.com/DNSCrypt/dnscrypt-proxy/wiki/Local-DoH +- name: dnscrypt-proxy | Prerequisite setup for local DoH server + block: + - name: dnscrypt-proxy | Generate private key for local DoH server + community.crypto.openssl_privatekey: + path: '/etc/dnscrypt-proxy/{{ ansible_hostname }}.pem' + type: Ed25519 + mode: 0640 + owner: root + group: dnscrypt + state: present + + - name: dnscrypt-proxy | Generate self-signed certificate for local DoH server + community.crypto.x509_certificate: + path: '/etc/dnscrypt-proxy/{{ ansible_hostname }}.crt' + privatekey_path: '/etc/dnscrypt-proxy/{{ ansible_hostname }}.pem' + provider: selfsigned + selfsigned_not_after: +5000d + selfsigned_digest: sha512 + mode: 0640 + owner: root + group: dnscrypt + state: present + when: dnscrypt.local_doh.enabled + +- name: dnscrypt-proxy | Copy blocked-ips.txt for rebinding protection + copy: + src: blocked-ips.txt + dest: /etc/dnscrypt-proxy/blocked-ips.txt + mode: 0644 + owner: root + group: root + +- name: dnscrypt-proxy | Copy cloaking-rules.txt + copy: + src: cloaking-rules.txt + dest: /etc/dnscrypt-proxy/cloaking-rules.txt + mode: 0644 + owner: root + group: root + +- name: dnscrypt-proxy | Configure DNS-based adblocking + block: + - name: dnscrypt-proxy | Create adblock directory for blocklist configurations + file: + path: /etc/dnscrypt-proxy/adblock + owner: root + group: root + mode: 0755 + state: directory + + - name: dnscrypt-proxy | Copy blocklists + copy: + src: '{{ item }}' + dest: '/etc/dnscrypt-proxy/adblock/{{ item }}' + owner: root + group: root + mode: 0644 + loop: + - domains-blocklist.conf + - domains-blocklist-local-additions.txt + + - name: dnscrypt-proxy | Download generate-domains-blocklist.py + get_url: + url: https://raw.githubusercontent.com/DNSCrypt/dnscrypt-proxy/master/utils/generate-domains-blocklist/generate-domains-blocklist.py + dest: /etc/dnscrypt-proxy/adblock/generate-domains-blocklist.py + mode: 0644 + owner: root + group: root + + - name: dnscrypt-proxy | Generate domain blocklist the 1st time + command: + cmd: /usr/bin/python3 generate-domains-blocklist.py -i -a /dev/null -r /dev/null -c domains-blocklist.conf -o /etc/dnscrypt-proxy/blocked-names.txt + chdir: /etc/dnscrypt-proxy/adblock + creates: /etc/dnscrypt-proxy/blocked-names.txt + failed_when: no + + - name: dnscrypt-proxy | Ensure proper permission on blocked-names.txt file + file: + path: /etc/dnscrypt-proxy/blocked-names.txt + mode: 0644 + owner: root + group: root + state: file + + - name: dnscrypt-proxy | Add daily cron job to update the blocklist + copy: + src: update_dnscrypt_blocklist + dest: /etc/periodic/daily/update_dnscrypt_blocklist + mode: 0755 + owner: root + group: root + when: dnscrypt.adblock + +- name: dnscrypt-proxy | Copy dnscrypt-proxy config + template: + src: dnscrypt-proxy.j2 + dest: /etc/dnscrypt-proxy/dnscrypt-proxy.toml + mode: 0644 + owner: root + group: root + validate: /usr/bin/dnscrypt-proxy -check -config %s + +- name: dnscrypt-proxy | Start dnscrypt-proxy service on runlevel 'default' + service: + name: dnscrypt-proxy + enabled: yes + state: started + runlevel: default diff --git a/roles/dns/tasks/main.yml b/roles/dns/tasks/main.yml new file mode 100644 index 0000000..0519220 --- /dev/null +++ b/roles/dns/tasks/main.yml @@ -0,0 +1,33 @@ +--- +- name: dns | Install openresolv and {{ dns_resolver }} + apk: + name: openresolv, {{ dns_resolver }} + state: present + +# Static import_tasks doesn't work here +- name: dns | Configure {{ dns_resolver }} + include_tasks: '{{ dns_resolver }}.yml' + +- name: dns | Update resolvconf config + template: + src: resolvconf.j2 + dest: /etc/resolvconf.conf + owner: root + group: root + mode: 0644 + +- name: dns | Overwrite /etc/netconfig/interfaces + template: + src: interfaces.j2 + dest: /etc/network/interfaces + owner: root + group: root + mode: 0644 + +- name: dns | Overwrite /etc/hosts to support IPv6 + copy: + src: hosts + dest: /etc/hosts + owner: root + group: root + mode: 0644 diff --git a/roles/unbound/tasks/main.yml b/roles/dns/tasks/unbound.yml similarity index 80% rename from roles/unbound/tasks/main.yml rename to roles/dns/tasks/unbound.yml index 7551a02..6fcca08 100644 --- a/roles/unbound/tasks/main.yml +++ b/roles/dns/tasks/unbound.yml @@ -1,7 +1,7 @@ --- -- name: unbound | Install unbound, openresolv and dns-root-hints +- name: unbound | Install dns-root-hints apk: - name: openresolv, unbound, dns-root-hints + name: dns-root-hints state: present - name: unbound | Create /dev directory inside unbound chroot @@ -16,8 +16,8 @@ # copy module doesn't seem to work - name: unbound | Copy needed devices to unbound chroot command: - cmd: /bin/cp -a /dev/random /dev/urandom /dev/null /etc/unbound/dev/ - creates: /etc/unbound/dev/random + cmd: /bin/cp -a /dev/urandom /dev/null /etc/unbound/dev/ + creates: /etc/unbound/dev/urandom # unbound user needs write permission to the anchor file, and also for the # directory it is in (to create a temporary file) @@ -42,7 +42,7 @@ state: file owner: unbound group: unbound - mode: 0644 + mode: 0640 - name: unbound | Gather package facts package_facts: @@ -70,8 +70,8 @@ src: /usr/share/dns-root-hints/named.root dest: /etc/unbound/var/named.root owner: root - group: root - mode: 0644 + group: unbound + mode: 0640 - name: unbound | Let dns-root-hints cron job copy root hints to unbound chroot blockinfile: @@ -84,8 +84,11 @@ if [ "$drh_new_ver" != "$drh_current_ver" ]; then /bin/cp -f $updated_file $current_file + /bin/chown root:unbound $current_file + /bin/chmod 0640 $current_file fi marker: '# {mark} COPY THE UPDATED ROOT HINTS TO UNBOUND CHROOT' + insertafter: 'EOF' owner: root group: root mode: 0755 @@ -105,27 +108,3 @@ runlevel: default enabled: yes state: started - -- name: unbound | Update resolvconf config - copy: - src: resolvconf.conf - dest: /etc/resolvconf.conf - owner: root - group: root - mode: 0644 - -- name: unbound | Rewrite network interface settings - template: - src: interfaces.j2 - dest: /etc/network/interfaces - owner: root - group: root - mode: 0644 - -- name: unbound | Rewrite /etc/hosts to support IPv6 - copy: - src: hosts - dest: /etc/hosts - owner: root - group: root - mode: 0644 diff --git a/roles/dns/templates/dnscrypt-proxy.j2 b/roles/dns/templates/dnscrypt-proxy.j2 new file mode 100644 index 0000000..ac39297 --- /dev/null +++ b/roles/dns/templates/dnscrypt-proxy.j2 @@ -0,0 +1,763 @@ +################################## +# Global settings # +################################## + +## List of servers to use +## +## Servers from the "public-resolvers" source (see down below) can +## be viewed here: https://dnscrypt.info/public-servers +## +## The proxy will automatically pick working servers from this list. +## Note that the require_* filters do NOT apply when using this setting. +## +## By default, this list is empty and all registered servers matching the +## require_* filters will be used instead. +## +## Remove the leading # first to enable this; lines starting with # are ignored. + +server_names = [{{ dnscrypt.server_names | map('quote_single') | join(', ') }}] + + +## List of local addresses and ports to listen to. Can be IPv4 and/or IPv6. +## Example with both IPv4 and IPv6: +## listen_addresses = ['127.0.0.1:53', '[::1]:53'] +## +## To listen to all IPv4 addresses, use `listen_addresses = ['0.0.0.0:53']` +## To listen to all IPv4+IPv6 addresses, use `listen_addresses = ['[::]:53']` + +listen_addresses = ['127.0.0.1:53', '[::1]:53'] + + +## Maximum number of simultaneous client connections to accept + +max_clients = 250 + + +## Switch to a different system user after listening sockets have been created. +## Note (1): this feature is currently unsupported on Windows. +## Note (2): this feature is not compatible with systemd socket activation. +## Note (3): when using -pidfile, the PID file directory must be writable by the new user + +# user_name = 'dnscrypt' + + +## Require servers (from remote sources) to satisfy specific properties + +# Use servers reachable over IPv4 +ipv4_servers = true + +# Use servers reachable over IPv6 -- Do not enable if you don't have IPv6 connectivity +ipv6_servers = true + +# Use servers implementing the DNSCrypt protocol +dnscrypt_servers = true + +# Use servers implementing the DNS-over-HTTPS protocol +doh_servers = {{ dnscrypt.anonymized_dns.enabled | ternary('false', 'true') }} + +# Use servers implementing the Oblivious DoH protocol +odoh_servers = {{ dnscrypt.anonymized_dns.enabled | ternary('false', 'true') }} + + +## Require servers defined by remote sources to satisfy specific properties + +# Server must support DNS security extensions (DNSSEC) +require_dnssec = true + +# Server must not log user queries (declarative) +require_nolog = true + +# Server must not enforce its own blocklist (for parental control, ads blocking...) +require_nofilter = false + +# Server names to avoid even if they match all criteria +disabled_server_names = [] + + +## Always use TCP to connect to upstream servers. +## This can be useful if you need to route everything through Tor. +## Otherwise, leave this to `false`, as it doesn't improve security +## (dnscrypt-proxy will always encrypt everything even using UDP), and can +## only increase latency. + +force_tcp = false + + +## SOCKS proxy +## Uncomment the following line to route all TCP connections to a local Tor node +## Tor doesn't support UDP, so set `force_tcp` to `true` as well. + +# proxy = 'socks5://127.0.0.1:9050' + + +## HTTP/HTTPS proxy +## Only for DoH servers + +# http_proxy = 'http://127.0.0.1:8888' + + +## How long a DNS query will wait for a response, in milliseconds. +## If you have a network with *a lot* of latency, you may need to +## increase this. Startup may be slower if you do so. +## Don't increase it too much. 10000 is the highest reasonable value. + +timeout = 5000 + + +## Keepalive for HTTP (HTTPS, HTTP/2) queries, in seconds + +keepalive = 30 + + +## Add EDNS-client-subnet information to outgoing queries +## +## Multiple networks can be listed; they will be randomly chosen. +## These networks don't have to match your actual networks. + +# edns_client_subnet = ['0.0.0.0/0', '2001:db8::/32'] + + +## Response for blocked queries. Options are `refused`, `hinfo` (default) or +## an IP response. To give an IP response, use the format `a:,aaaa:`. +## Using the `hinfo` option means that some responses will be lies. +## Unfortunately, the `hinfo` option appears to be required for Android 8+ + +blocked_query_response = 'refused' + + +## Load-balancing strategy: 'p2' (default), 'ph', 'p', 'first' or 'random' +## Randomly choose 1 of the fastest 2, half, n, 1 or all live servers by latency. +## The response quality still depends on the server itself. + +lb_strategy = 'p2' + +## Set to `true` to constantly try to estimate the latency of all the resolvers +## and adjust the load-balancing parameters accordingly, or to `false` to disable. +## Default is `true` that makes 'p2' `lb_strategy` work well. + +lb_estimator = true + + +## Log level (0-6, default: 2 - 0 is very verbose, 6 only contains fatal errors) + +log_level = 2 + + +## Log file for the application, as an alternative to sending logs to +## the standard system logging service (syslog/Windows event log). +## +## This file is different from other log files, and will not be +## automatically rotated by the application. + +log_file = '/var/log/dnscrypt-proxy/dnscrypt-proxy.log' + + +## When using a log file, only keep logs from the most recent launch. + +log_file_latest = true + + +## Use the system logger (syslog on Unix, Event Log on Windows) + +use_syslog = true + + +## Delay, in minutes, after which certificates are reloaded + +cert_refresh_delay = 240 + + +## DNSCrypt: Create a new, unique key for every single DNS query +## This may improve privacy but can also have a significant impact on CPU usage +## Only enable if you don't have a lot of network load + +dnscrypt_ephemeral_keys = {{ dnscrypt.ephemeral_keys | lower }} + + +## DoH: Disable TLS session tickets - increases privacy but also latency + +tls_disable_session_tickets = {{ dnscrypt.tls_disable_session_tickets | lower }} + + +## DoH: Use a specific cipher suite instead of the server preference +## 49199 = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +## 49195 = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +## 52392 = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 +## 52393 = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 +## 4865 = TLS_AES_128_GCM_SHA256 +## 4867 = TLS_CHACHA20_POLY1305_SHA256 +## +## On non-Intel CPUs such as MIPS routers and ARM systems (Android, Raspberry Pi...), +## the following suite improves performance. +## This may also help on Intel CPUs running 32-bit operating systems. +## +## Keep tls_cipher_suite empty if you have issues fetching sources or +## connecting to some DoH servers. Google and Cloudflare are fine with it. + +tls_cipher_suite = {{ dnscrypt.tls_cipher_suite }} + + +## Bootstrap resolvers +## +## These are normal, non-encrypted DNS resolvers, that will be only used +## for one-shot queries when retrieving the initial resolvers list and the +## the system DNS configuration doesn't work. +## +## No user queries will ever be leaked through these resolvers, and they will +## not be used after IP addresses of DoH resolvers have been found (if you are +## using DoH). +## +## They will never be used if lists have already been cached, and if the stamps +## of the configured servers already include IP addresses (which is the case for +## most of DoH servers, and for all DNSCrypt servers and relays). +## +## They will not be used if the configured system DNS works, or after the +## proxy already has at least one usable secure resolver. +## +## Resolvers supporting DNSSEC are recommended, and, if you are using +## DoH, bootstrap resolvers should ideally be operated by a different entity +## than the DoH servers you will be using, especially if you have IPv6 enabled. +## +## People in China may want to use 114.114.114.114:53 here. +## Other popular options include 8.8.8.8, 9.9.9.9 and 1.1.1.1. +## +## If more than one resolver is specified, they will be tried in sequence. +## +## TL;DR: put valid standard resolver addresses here. Your actual queries will +## not be sent there. If you're using DNSCrypt or Anonymized DNS and your +## lists are up to date, these resolvers will not even be used. + +bootstrap_resolvers = {{ dnscrypt.bootstrap_resolvers }} + + +## Always use the bootstrap resolver before the system DNS settings. + +ignore_system_dns = true + + +## Maximum time (in seconds) to wait for network connectivity before +## initializing the proxy. +## Useful if the proxy is automatically started at boot, and network +## connectivity is not guaranteed to be immediately available. +## Use 0 to not test for connectivity at all (not recommended), +## and -1 to wait as much as possible. + +netprobe_timeout = 60 + +## Address and port to try initializing a connection to, just to check +## if the network is up. It can be any address and any port, even if +## there is nothing answering these on the other side. Just don't use +## a local address, as the goal is to check for Internet connectivity. +## On Windows, a datagram with a single, nul byte will be sent, only +## when the system starts. +## On other operating systems, the connection will be initialized +## but nothing will be sent at all. + +netprobe_address = '{{ dnscrypt.netprobe_address }}' + + +## Offline mode - Do not use any remote encrypted servers. +## The proxy will remain fully functional to respond to queries that +## plugins can handle directly (forwarding, cloaking, ...) + +offline_mode = false + + +## Additional data to attach to outgoing queries. +## These strings will be added as TXT records to queries. +## Do not use, except on servers explicitly asking for extra data +## to be present. +## encrypted-dns-server can be configured to use this for access control +## in the [access_control] section + +# query_meta = ['key1:value1', 'key2:value2', 'token:MySecretToken'] + + +## Automatic log files rotation + +# Maximum log files size in MB - Set to 0 for unlimited. +log_files_max_size = 10 + +# How long to keep backup files, in days +log_files_max_age = 7 + +# Maximum log files backups to keep (or 0 to keep all backups) +log_files_max_backups = 1 + + + +######################### +# Filters # +######################### + +## Note: if you are using dnsmasq, disable the `dnssec` option in dnsmasq if you +## configure dnscrypt-proxy to do any kind of filtering (including the filters +## below and blocklists). +## You can still choose resolvers that do DNSSEC validation. + + +## Immediately respond to IPv6-related queries with an empty response +## This makes things faster when there is no IPv6 connectivity, but can +## also cause reliability issues with some stub resolvers. + +block_ipv6 = false + + +## Immediately respond to A and AAAA queries for host names without a domain name + +block_unqualified = true + + +## Immediately respond to queries for local zones instead of leaking them to +## upstream resolvers (always causing errors or timeouts). + +block_undelegated = true + + +## TTL for synthetic responses sent when a request has been blocked (due to +## IPv6 or blocklists). + +reject_ttl = 10 + + + +################################################################################## +# Route queries for specific domains to a dedicated set of servers # +################################################################################## + +## See the `/usr/share/dnscrypt-proxy/example-forwarding-rules.txt` file for an example + +# forwarding_rules = '/etc/dnscrypt-proxy/forwarding-rules.txt' + + + +############################### +# Cloaking rules # +############################### + +## Cloaking returns a predefined address for a specific name. +## In addition to acting as a HOSTS file, it can also return the IP address +## of a different name. It will also do CNAME flattening. +## +## See the `/usr/share/dnscrypt-proxy/example-cloaking-rules.txt` file for an example + +cloaking_rules = '/etc/dnscrypt-proxy/cloaking-rules.txt' + +## TTL used when serving entries in cloaking-rules.txt + +cloak_ttl = 600 + + + +########################### +# DNS cache # +########################### + +## Enable a DNS cache to reduce latency and outgoing traffic + +cache = true + + +## Cache size + +cache_size = 4096 + + +## Minimum TTL for cached entries + +cache_min_ttl = 2400 + + +## Maximum TTL for cached entries + +cache_max_ttl = 86400 + + +## Minimum TTL for negatively cached entries + +cache_neg_min_ttl = 60 + + +## Maximum TTL for negatively cached entries + +cache_neg_max_ttl = 600 + + + +######################################## +# Captive portal handling # +######################################## + +[captive_portals] + +## A file that contains a set of names used by operating systems to +## check for connectivity and captive portals, along with hard-coded +## IP addresses to return. +## see '/usr/share/dnscrypt-proxy/example-captive-portals.txt' file for an example + +# map_file = '/etc/dnscrypt-proxy/captive-portals.txt' + + + +################################## +# Local DoH server # +################################## + +[local_doh] + +{% if dnscrypt.local_doh.enabled %} +## dnscrypt-proxy can act as a local DoH server. By doing so, web browsers +## requiring a direct connection to a DoH server in order to enable some +## features will enable these, without bypassing your DNS proxy. + +## Addresses that the local DoH server should listen to + +listen_addresses = {{ dnscrypt.local_doh.listen_addresses }} + + +## Path of the DoH URL. This is not a file, but the part after the hostname +## in the URL. By convention, `/dns-query` is frequently chosen. +## For each `listen_address` the complete URL to access the server will be: +## `https://` (ex: `https://127.0.0.1/dns-query`) + +path = '{{ dnscrypt.local_doh.path }}' + + +## Certificate file and key - Note that the certificate has to be trusted. +## See the documentation (wiki) for more information. + +cert_file = '{{ ansible_hostname }}.crt' +cert_key_file = '{{ ansible_hostname }}.pem' +{% endif %} + + + +############################### +# Query logging # +############################### + +## Log client queries to a file + +[query_log] + + ## Path to the query log file (absolute, or relative to the same directory as the config file) + ## Can be set to /dev/stdout in order to log to the standard output. + + file = '/var/log/dnscrypt-proxy/query.log' + + + ## Query log format (currently supported: tsv and ltsv) + + format = 'tsv' + + + ## Do not log these query types, to reduce verbosity. Keep empty to log everything. + + ignored_qtypes = ['DNSKEY', 'NS'] + + + +############################################ +# Suspicious queries logging # +############################################ + +## Log queries for nonexistent zones +## These queries can reveal the presence of malware, broken/obsolete applications, +## and devices signaling their presence to 3rd parties. + +[nx_log] + + ## Path to the query log file (absolute, or relative to the same directory as the config file) + + file = '/var/log/dnscrypt-proxy/nx.log' + + + ## Query log format (currently supported: tsv and ltsv) + + format = 'tsv' + + + +###################################################### +# Pattern-based blocking (blocklists) # +###################################################### + +## Blocklists are made of one pattern per line. Example of valid patterns: +## +## example.com +## =example.com +## *sex* +## ads.* +## ads*.example.* +## ads*.example[0-9]*.com +## +## Example blocklist files can be found at https://download.dnscrypt.info/blocklists/ +## A script to build blocklists from public feeds can be found in the +## `utils/generate-domains-blocklists` directory of the dnscrypt-proxy source code. + +[blocked_names] + +{% if dnscrypt.adblock %} + ## Path to the file of blocking rules (absolute, or relative to the same directory as the config file) + + blocked_names_file = '/etc/dnscrypt-proxy/blocked-names.txt' + + + ## Optional path to a file logging blocked queries + + log_file = '/var/log/dnscrypt-proxy/blocked-names.log' + + + ## Optional log format: tsv or ltsv (default: tsv) + + log_format = 'tsv' +{% endif %} + + + +########################################################### +# Pattern-based IP blocking (IP blocklists) # +########################################################### + +## IP blocklists are made of one pattern per line. Example of valid patterns: +## +## 127.* +## fe80:abcd:* +## 192.168.1.4 + +[blocked_ips] + + ## Path to the file of blocking rules (absolute, or relative to the same directory as the config file) + + blocked_ips_file = '/etc/dnscrypt-proxy/blocked-ips.txt' + + + ## Optional path to a file logging blocked queries + + log_file = '/var/log/dnscrypt-proxy/blocked-ips.log' + + + ## Optional log format: tsv or ltsv (default: tsv) + + log_format = 'tsv' + + + +###################################################### +# Pattern-based allow lists (blocklists bypass) # +###################################################### + +## Allowlists support the same patterns as blocklists +## If a name matches an allowlist entry, the corresponding session +## will bypass names and IP filters. +## +## Time-based rules are also supported to make some websites only accessible at specific times of the day. + +[allowed_names] + + ## Path to the file of allow list rules (absolute, or relative to the same directory as the config file) + + # allowed_names_file = '/etc/dnscrypt-proxy/allowed-names.txt' + + + ## Optional path to a file logging allowed queries + + # log_file = '/var/log/dnscrypt-proxy/allowed-names.log' + + + ## Optional log format: tsv or ltsv (default: tsv) + + # log_format = 'tsv' + + + +######################################################### +# Pattern-based allowed IPs lists (blocklists bypass) # +######################################################### + +## Allowed IP lists support the same patterns as IP blocklists +## If an IP response matches an allow ip entry, the corresponding session +## will bypass IP filters. +## +## Time-based rules are also supported to make some websites only accessible at specific times of the day. + +[allowed_ips] + + ## Path to the file of allowed ip rules (absolute, or relative to the same directory as the config file) + + # allowed_ips_file = '/etc/dnscrypt-proxy/allowed-ips.txt' + + + ## Optional path to a file logging allowed queries + + # log_file = '/var/log/dnscrypt-proxy/allowed-ips.log' + + ## Optional log format: tsv or ltsv (default: tsv) + + # log_format = 'tsv' + + + +########################################## +# Time access restrictions # +########################################## + +## One or more weekly schedules can be defined here. +## Patterns in the name-based blocked_names file can optionally be followed with @schedule_name +## to apply the pattern 'schedule_name' only when it matches a time range of that schedule. +## +## For example, the following rule in a blocklist file: +## *.youtube.* @time-to-sleep +## would block access to YouTube during the times defined by the 'time-to-sleep' schedule. +## +## {after='21:00', before= '7:00'} matches 0:00-7:00 and 21:00-0:00 +## {after= '9:00', before='18:00'} matches 9:00-18:00 + +[schedules] + + # [schedules.'time-to-sleep'] + # mon = [{after='21:00', before='7:00'}] + # tue = [{after='21:00', before='7:00'}] + # wed = [{after='21:00', before='7:00'}] + # thu = [{after='21:00', before='7:00'}] + # fri = [{after='23:00', before='7:00'}] + # sat = [{after='23:00', before='7:00'}] + # sun = [{after='21:00', before='7:00'}] + + # [schedules.'work'] + # mon = [{after='9:00', before='18:00'}] + # tue = [{after='9:00', before='18:00'}] + # wed = [{after='9:00', before='18:00'}] + # thu = [{after='9:00', before='18:00'}] + # fri = [{after='9:00', before='17:00'}] + + + +######################### +# Servers # +######################### + +## Remote lists of available servers +## Multiple sources can be used simultaneously, but every source +## requires a dedicated cache file. +## +## Refer to the documentation for URLs of public sources. +## +## A prefix can be prepended to server names in order to +## avoid collisions if different sources share the same for +## different servers. In that case, names listed in `server_names` +## must include the prefixes. +## +## If the `urls` property is missing, cache files and valid signatures +## must already be present. This doesn't prevent these cache files from +## expiring after `refresh_delay` hours. +## Cache freshness is checked every 24 hours, so values for 'refresh_delay' +## of less than 24 hours will have no effect. +## A maximum delay of 168 hours (1 week) is imposed to ensure cache freshness. + +[sources] +{% for source in dnscrypt_server_sources %} + + [sources.'{{ source.name }}'] + urls = [{{ source.urls | map('quote_single') | join(', ') }}] + cache_file = '{{ source.cache_file }}' + minisign_key = '{{ source.minisign_key }}' + refresh_delay = {{ source.refresh_delay }} + prefix = '{{ source.prefix }}' +{% endfor %} + + +######################################### +# Servers with known bugs # +######################################### + +[broken_implementations] + +# Cisco servers currently cannot handle queries larger than 1472 bytes, and don't +# truncate reponses larger than questions as expected by the DNSCrypt protocol. +# This prevents large responses from being received over UDP and over relays. +# +# Older versions of the `dnsdist` server software had a bug with queries larger +# than 1500 bytes. This is fixed since `dnsdist` version 1.5.0, but +# some server may still run an outdated version. +# +# The list below enables workarounds to make non-relayed usage more reliable +# until the servers are fixed. + +fragments_blocked = ['cisco', 'cisco-ipv6', 'cisco-familyshield', 'cisco-familyshield-ipv6', 'cleanbrowsing-adult', 'cleanbrowsing-adult-ipv6', 'cleanbrowsing-family', 'cleanbrowsing-family-ipv6', 'cleanbrowsing-security', 'cleanbrowsing-security-ipv6'] + + + +################################################################# +# Certificate-based client authentication for DoH # +################################################################# + +# Use a X509 certificate to authenticate yourself when connecting to DoH servers. +# This is only useful if you are operating your own, private DoH server(s). +# 'creds' maps servers to certificates, and supports multiple entries. +# If you are not using the standard root CA, an optional "root_ca" +# property set to the path to a root CRT file can be added to a server entry. + +[doh_client_x509_auth] + +# +# creds = [ +# { server_name='*', client_cert='client.crt', client_key='client.key' } +# ] + + + +################################ +# Anonymized DNS # +################################ + +[anonymized_dns] + +## Routes are indirect ways to reach DNSCrypt servers. +## +## A route maps a server name ("server_name") to one or more relays that will be +## used to connect to that server. +## +## A relay can be specified as a DNS Stamp (either a relay stamp, or a +## DNSCrypt stamp) or a server name. +## +## The following example routes "example-server-1" via `anon-example-1` or `anon-example-2`, +## and "example-server-2" via the relay whose relay DNS stamp is +## "sdns://gRIxMzcuNzQuMjIzLjIzNDo0NDM". +## +## !!! THESE ARE JUST EXAMPLES !!! +## +## Review the list of available relays from the "relays.md" file, and, for each +## server you want to use, define the relays you want connections to go through. +## +## Carefully choose relays and servers so that they are run by different entities. +## +## "server_name" can also be set to "*" to define a default route, for all servers: +## { server_name='*', via=['anon-example-1', 'anon-example-2'] } +## +## If a route is ["*"], the proxy automatically picks a relay on a distinct network. +## { server_name='*', via=['*'] } is also an option, but is likely to be suboptimal. +## +## Manual selection is always recommended over automatic selection, so that you can +## select (relay,server) pairs that work well and fit your own criteria (close by or +## in different countries, operated by different entities, on distinct ISPs...) + +{% if dnscrypt.anonymized_dns.enabled %} +routes = [ +{% for route in dnscrypt.anonymized_dns.routes %} + { server_name='{{ route.server_name }}', via=[{{ route.via | map('quote_single') | join(', ') }}]}, +{% endfor %} +] + + +# Skip resolvers incompatible with anonymization instead of using them directly + +skip_incompatible = true + + +# If public server certificates for a non-conformant server cannot be +# retrieved via a relay, try getting them directly. Actual queries +# will then always go through relays. + +direct_cert_fallback = false +{% endif %} diff --git a/roles/unbound/templates/interfaces.j2 b/roles/dns/templates/interfaces.j2 similarity index 100% rename from roles/unbound/templates/interfaces.j2 rename to roles/dns/templates/interfaces.j2 diff --git a/roles/unbound/files/resolvconf.conf b/roles/dns/templates/resolvconf.j2 similarity index 76% rename from roles/unbound/files/resolvconf.conf rename to roles/dns/templates/resolvconf.j2 index dc156ac..75e24fb 100644 --- a/roles/unbound/files/resolvconf.conf +++ b/roles/dns/templates/resolvconf.j2 @@ -5,3 +5,6 @@ resolv_conf=/etc/resolv.conf # If you run a local name server, you should uncomment the below line and # configure your subscribers configuration files below. name_servers="127.0.0.1 ::1" +{% if dns_resolver == 'dnscrypt-proxy' %} +resolv_conf_options="edns0" +{% endif %} diff --git a/roles/unbound/templates/unbound.j2 b/roles/dns/templates/unbound.j2 similarity index 99% rename from roles/unbound/templates/unbound.j2 rename to roles/dns/templates/unbound.j2 index 3c3bcbf..6a9f54a 100644 --- a/roles/unbound/templates/unbound.j2 +++ b/roles/dns/templates/unbound.j2 @@ -390,6 +390,7 @@ remote-control: forward-zone: name: "." forward-tls-upstream: yes + forward-no-cache: no {% for item in unbound_upstream_nameservers %} forward-addr: {{ item }} {% endfor %} diff --git a/roles/essential/tasks/main.yml b/roles/essential/tasks/main.yml index c99b9d7..e3ee383 100644 --- a/roles/essential/tasks/main.yml +++ b/roles/essential/tasks/main.yml @@ -44,14 +44,6 @@ mode: 0644 when: seat_manager != 'elogind' -- name: essential | Start services on runlevel 'default' - service: - name: '{{ item }}' - runlevel: default - enabled: yes - state: started - loop: [ dbus, ntpd, cgroups ] - - name: essential | Change the default motd template: src: motd.j2 @@ -105,9 +97,20 @@ group: root mode: 0644 -- name: essential | Start consolefont service on runlevel 'boot' +- name: essential | Start services on runlevel 'boot' service: - name: consolefont + name: '{{ item }}' runlevel: boot enabled: yes state: started + loop: + - consolefont + - syslog + +- name: essential | Start services on runlevel 'default' + service: + name: '{{ item }}' + runlevel: default + enabled: yes + state: started + loop: ['dbus', 'ntpd', 'cgroups'] diff --git a/roles/grub/tasks/main.yml b/roles/grub/tasks/main.yml index e831f87..82da975 100644 --- a/roles/grub/tasks/main.yml +++ b/roles/grub/tasks/main.yml @@ -35,18 +35,42 @@ group: root mode: 0644 -- name: grub | Add font and background configurations to /etc/default/grub - blockinfile: +- name: grub | Add font and background configurations + lineinfile: path: /etc/default/grub - insertafter: '^GRUB_CMDLINE_LINUX_DEFAULT=' - block: | - GRUB_DISABLE_OS_PROBER=true - GRUB_GFXMODE=1920x1080x32,1280x720x32,auto - GRUB_GFXPAYLOAD_LINUX=keep - GRUB_BACKGROUND=/boot/grub/background.png - GRUB_FONT=/boot/grub/fonts/hack.pf2 - marker: '# {mark} CUSTOM SETTINGS BLOCK' + line: '{{ item }}' + search_string: '{{ item | regex_replace("=.*", "") }}' owner: root group: root mode: 0644 + loop: + - GRUB_DISABLE_OS_PROBER=true + - GRUB_GFXMODE=1920x1080x32,1280x720x32,auto + - GRUB_GFXPAYLOAD_LINUX=keep + - GRUB_BACKGROUND=/boot/grub/background.png + - GRUB_FONT=/boot/grub/fonts/hack.pf2 notify: Update grub config + +- name: grub | Check whether additional kernel parameters is presented + lineinfile: + backup: yes + path: /etc/default/grub + regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=".*{{ item | regex_replace("=.*", "=") }}.*' + state: absent + check_mode: yes + register: grub_cmdline_check + changed_when: no + loop: '{{ kernel_parameters }}' + +- name: apparmor | Add defined kernel parameters to grub boot command-line + lineinfile: + backrefs: yes + path: /etc/default/grub + regexp: '^(GRUB_CMDLINE_LINUX_DEFAULT=".*)"$' + line: '\1 {{ item.item }}"' + owner: root + group: root + mode: 0644 + when: item.found == 0 + notify: Update grub config + loop: '{{ grub_cmdline_check.results }}' diff --git a/roles/user/defaults/main.yml b/roles/user/defaults/main.yml index 0cb2c58..0816b31 100644 --- a/roles/user/defaults/main.yml +++ b/roles/user/defaults/main.yml @@ -15,6 +15,7 @@ shells_list: bash: /bin/bash fish: /usr/bin/fish hilbish: /usr/bin/hilbish + ion-shell: /usr/bin/ion nushell: /usr/bin/nu sh: /bin/sh xonsh: /usr/bin/xonsh diff --git a/setup.yml b/setup.yml index e3282da..5446238 100644 --- a/setup.yml +++ b/setup.yml @@ -8,11 +8,22 @@ fail: msg: This playbook should only be run as 'root' when: ansible_real_user_id != 0 - - name: Check seat manager name fail: msg: seat_manager needs to be 'elogind' or 'seatd' - when: not seat_manager in [ 'elogind', 'seatd' ] + when: not seat_manager in ['elogind', 'seatd'] + - name: Check device manager name + fail: + msg: device_manager needs to be 'mdev', 'mdevd' or 'udev' + when: not device_manager in ['mdev', 'mdevd', 'udev'] + - name: Check DNS resolver name + fail: + msg: dns_resolver needs to be 'dnscrypt-proxy' or 'unbound' + when: not dns_resolver in ['dnscrypt-proxy', 'unbound'] + - name: Check rootless container CLI application + fail: + msg: rootless_container_cli needs to be 'podman' or 'nerdctl' + when: not rootless_container_cli in ['podman', 'nerdctl'] - name: Setup the system hosts: all @@ -36,13 +47,13 @@ - role: grub tags: grub - role: iwd - tags: [ laptop, iwd ] + tags: [laptop, iwd] - role: libvirt tags: libvirt - role: tlp - tags: [ laptop, tlp ] - - role: unbound - tags: unbound + tags: [laptop, tlp] + - role: dns + tags: dns - role: usbguard tags: usbguard - role: zram