diff --git a/01-dnssec-trigger-hook b/01-dnssec-trigger-hook index 6bc6a19..1d4953e 100755 --- a/01-dnssec-trigger-hook +++ b/01-dnssec-trigger-hook @@ -1,107 +1,546 @@ -#!/bin/sh -# -# NetworkManager trigger for in dispatcher.d -# config items -alias unbound-control="/usr/sbin/unbound-control" -alias dnssec-trigger-control="/usr/sbin/dnssec-trigger-control" -alias pidof="/usr/sbin/pidof" -alias nmcli="/usr/bin/nmcli" - -state_dir="/var/run/dnssec-trigger" -validate_forward_zones="no" - -# implementation -ifname="$1" -action="$2" -domains="" -nameservers="" -global_nameservers="" -conn_zones_file="$state_dir/$CONNECTION_UUID" - -################################################################ -# get domains and nameservers if provided by connection going up -case "$action" in - "vpn-up" ) - domains="`echo $VPN_IP4_DOMAINS $VPN_IP6_DOMAINS | tr " " "\n" | sort -u | tr "\n" " " | sed '$s/.$//'`" - nameservers="`echo $VPN_IP4_NAMESERVERS $VPN_IP6_NAMESERVERS`" - ;; - "up" ) - domains="`echo $IP4_DOMAINS $IP6_DOMAINS | tr " " "\n" | sort -u | tr "\n" " " | sed '$s/.$//'`" - nameservers="`echo $IP4_NAMESERVERS $IP6_NAMESERVERS`" - ;; -esac - -######################### -# get global nameservers -# try to get nmcli version -NMCLI_VER="`nmcli -v 2> /dev/null | sed 's/.*version \([0-9]\)\.\([0-9]\)\.\([0-9]\)\.\([0-9]\).*/\1\2\3\4/'`" -# if nmcli exists -if [ -n $NMCLI_VER ]; then - # if the version is greater or equal 0.9.9.0 - if [ $NMCLI_VER -ge 0990 ]; then - global_nameservers="`nmcli -f IP4,IP6 dev show | fgrep 'DNS' | awk '{print $2;}'`" - else - global_nameservers="`nmcli -f IP4,IP6 dev list | fgrep 'DNS' | awk '{print $2;}'`" - fi -# nmcli does not exist -else - global_nameservers="`nm-tool | grep 'DNS:' | awk '{print $2;}'`" -fi -# fix whitespaces -global_nameservers="`echo $global_nameservers`" - - -############################################################ -# configure global nameservers using dnssec-trigger-control -if [ -n "`pidof dnssec-triggerd`" ] ; then - dnssec-trigger-control submit "$global_nameservers" &> /dev/null - logger "dnssec-trigger-hook(networkmanager) $ifname $action added global DNS $global_nameservers" -else - logger "dnssec-trigger-hook(networkmanager) $ifname $action NOT added global DNS - dnssec-triggerd is not running" -fi - -###################################################### -# add forward zones into unbound using unbound-control -if [ -n "`pidof unbound`" ]; then - if [ -r "$conn_zones_file" ]; then - for domain in `cat $conn_zones_file`; do - # Remove forward zone from unbound - if [ "$validate_forward_zones" == "no" ]; then - unbound-control forward_remove +i $domain &> /dev/null - else - unbound-control forward_remove $domain &> /dev/null - fi - unbound-control flush_zone $domain &> /dev/null - unbound-control flush_requestlist &> /dev/null - - logger "dnssec-trigger-hook(networkmanager) $ifname $action removed forward DNS zone $domain" - done - - # Remove file with zones for this connection - rm -f $conn_zones_file &> /dev/null - fi - - if [ "$action" == "vpn-up" ] || [ "$action" == "up" ]; then - if [ -n "$domains" ]; then - for domain in $domains; do - # Add forward zone into unbound - if [ "$validate_forward_zones" == "no" ]; then - unbound-control forward_add +i $domain $nameservers &> /dev/null - else - unbound-control forward_add $domain $nameservers &> /dev/null - fi - unbound-control flush_zone $domain &> /dev/null - unbound-control flush_requestlist &> /dev/null - - # Create zone info file - echo $domain >> $conn_zones_file - - logger "dnssec-trigger-hook(networkmanager) $ifname $action added forward DNS zone $domain $nameservers" - done - fi - fi -else - logger "dnssec-trigger-hook(networkmanager) $ifname $action NOT added forward DNS zone(s) - unbound is not running" -fi - -exit 0 +#!/usr/bin/python2 +# -*- coding: utf-8 -*- +""" +@author: Tomas Hozza +""" + +from gi.repository import NMClient +import socket +import struct +import subprocess +import os +import os.path +import syslog +import sys + + +# DO NOT CHANGE THE VALUE HERE, CHANGE IT IN **DNSSEC_CONF** file +DEFAULT_VALIDATE_FORWARD_ZONES = True +DEFAULT_ADD_WIFI_PROVIDED_ZONES = False + +STATE_DIR = "/var/run/dnssec-trigger" +DNSSEC_CONF = "/etc/dnssec.conf" + +UNBOUND = "/usr/sbin/unbound" +UNBOUND_CONTROL = "/usr/sbin/unbound-control" +DNSSEC_TRIGGER = "/usr/sbin/dnssec-triggerd" +DNSSEC_TRIGGER_CONTROL = "/usr/sbin/dnssec-trigger-control" +PIDOF = "/usr/sbin/pidof" + + +class FZonesConfig: + + """ + Class representing dnssec-trigger script forward zones behaviour + configuration. + """ + + def __init__(self): + self.validate_fzones = DEFAULT_VALIDATE_FORWARD_ZONES + self.add_wifi_zones = DEFAULT_ADD_WIFI_PROVIDED_ZONES + + +class ActiveConnection: + + """ + Simple class representing NM Active Connection with information relevant + for this script. + """ + + TYPE_WIFI = "WIFI" + TYPE_VPN = "VPN" + TYPE_OTHER = "OTHER" + + def __init__(self): + self.type = self.TYPE_OTHER + self.is_default = False + self.nameservers = [] + self.domains = [] + self.uuid = "" + pass + + def __str__(self): + string = "UUID: " + self.get_uuid() + "\n" + string += "TYPE: " + str(self.get_type()) + "\n" + string += "DEFAULT: " + str(self.get_is_default()) + "\n" + string += "NS: " + str(self.get_nameservers()) + "\n" + string += "DOMAINS: " + str(self.get_domains()) + return string + + def get_uuid(self): + return self.uuid + + def get_type(self): + return self.type + + def get_is_default(self): + return self.is_default + + def get_nameservers(self): + return self.nameservers + + def get_domains(self): + return self.domains + + def set_uuid(self, uuid=""): + self.uuid = uuid + + def set_type(self, conn_type=TYPE_OTHER): + if conn_type == self.TYPE_VPN: + self.type = self.TYPE_VPN + elif conn_type == self.TYPE_WIFI: + self.type = self.TYPE_WIFI + else: + self.type = self.TYPE_OTHER + + def set_is_default(self, is_default=True): + self.is_default = is_default + + def set_nameservers(self, servers=[]): + self.nameservers = servers + + def set_domains(self, domains=[]): + self.domains = domains + + +def ip4_to_str(ip4): + """ + Converts IPv4 address from integer to string. + """ + return socket.inet_ntop(socket.AF_INET, struct.pack("=I", ip4)) + + +def ip6_to_str(ip6): + """ + Converts IPv6 address from integer to string. + """ + addr_struct = ip6 + return socket.inet_ntop(socket.AF_INET6, addr_struct) + + +def get_fzones_settings_from_conf(conf_file=""): + """ + Reads the forward zones behaviour config from file. + """ + config = FZonesConfig() + + try: + with open(conf_file, "r") as f: + lines = [l.strip() + for l in f.readlines() if l.strip() and not l.strip().startswith("#")] + for line in lines: + option_line = line.split("=") + if option_line: + if option_line[0].strip() == "validate_connection_provided_zones": + if option_line[1].strip() == "yes": + config.validate_fzones = True + else: + config.validate_fzones = False + elif option_line[0].strip() == "add_wifi_provided_zones": + if option_line[1].strip() == "yes": + config.add_wifi_zones = True + else: + config.add_wifi_zones = False + except IOError: + # we don't mind if the config file does not exist + pass + + return config + + +def get_nm_active_connections(): + """ + Process Active Connections from NM and return list of ActiveConnection + objects. Active Connections from NM without nameservers are ignored. + """ + result = [] + client = NMClient.Client() + ac = client.get_active_connections() + + for connection in ac: + new_connection = ActiveConnection() + + # get the UUID + new_connection.set_uuid(connection.get_uuid()) + + # Find out if the ActiveConnection is VPN, WIFI or OTHER + try: + connection.get_vpn_state() + except AttributeError: + # We don't need to change anything + pass + else: + new_connection.set_type(ActiveConnection.TYPE_VPN) + + # if the connection is NOT VPN, then check if it's WIFI + if new_connection.get_type() != ActiveConnection.TYPE_VPN: + try: + device_type = connection.get_devices()[ + 0].get_device_type().value_name + except AttributeError: + # We don't need to change anything + pass + else: + if device_type == "NM_DEVICE_TYPE_WIFI": + new_connection.set_type(ActiveConnection.TYPE_WIFI) + + # Finc out if default connection for IP4 or IP6 + if connection.get_default() or connection.get_default6(): + new_connection.set_is_default(True) + else: + new_connection.set_is_default(False) + + # Get nameservers (IP4 + IP6) + ips = [] + try: + ips4_int = connection.get_ip4_config().get_nameservers() + except AttributeError: + # we don't mind if there are no IP4 nameservers + pass + else: + for ip4 in ips4_int: + ips.append(ip4_to_str(ip4)) + try: + num = connection.get_ip6_config().get_num_nameservers() + for i in range(0,num): + ips.append(ip6_to_str(connection.get_ip6_config().get_nameserver(i))) + except AttributeError: + # we don't mind if there are no IP6 nameservers + pass + new_connection.set_nameservers(ips) + + # Get domains (IP4 + IP6) + domains = [] + try: + domains.extend(connection.get_ip4_config().get_domains()) + except AttributeError: + # we don't mind if there are no IP6 domains + pass + try: + domains.extend(connection.get_ip6_config().get_domains()) + except AttributeError: + # we don't mind if there are no IP6 domains + pass + new_connection.set_domains(domains) + + # If there are no nameservers in the connection, it is useless + if new_connection.get_nameservers(): + result.append(new_connection) + + return result + + +def is_running(binary=""): + """ + Checks if the given binary is running. + """ + if binary: + sp = subprocess.Popen(PIDOF + " " + binary, + stdout=subprocess.PIPE, + stderr=open(os.devnull, "wb"), + shell=True) + sp.wait() + if sp.returncode == 0: + # pidof returns "0" if at least one program with the name runs + return True + return False + + +def dnssec_trigger_set_global_ns(servers=[]): + """ + Configures global nameservers into dnssec-trigger. + """ + if servers: + servers_list = " ".join(servers) + ret = subprocess.call( + DNSSEC_TRIGGER_CONTROL + " submit " + servers_list, + stdout=open(os.devnull, "wb"), + stderr=subprocess.STDOUT, + shell=True) + if ret == 0: + syslog.syslog( + syslog.LOG_INFO, "Global forwarders added: " + servers_list) + else: + syslog.syslog( + syslog.LOG_ERR, "Global forwarders NOT added: " + servers_list) + + +def unbound_add_forward_zone(domain="", servers=[], secure=DEFAULT_VALIDATE_FORWARD_ZONES): + """ + Adds a forward zone into the unbound. + """ + if domain and servers: + servers_list = " ".join(servers) + # build the command + cmd = UNBOUND_CONTROL + " forward_add" + if not secure: + cmd += " +i" + cmd += " " + domain + " " + servers_list + # Add the forward zone + ret = subprocess.call(cmd, + stdout=open(os.devnull, "wb"), + stderr=subprocess.STDOUT, + shell=True) + # Flush cache + subprocess.call(UNBOUND_CONTROL + " flush_zone " + domain, + stdout=open(os.devnull, "wb"), + stderr=subprocess.STDOUT, + shell=True) + subprocess.call(UNBOUND_CONTROL + " flush_requestlist", + stdout=open(os.devnull, "wb"), + stderr=subprocess.STDOUT, + shell=True) + + if secure: + validated = "(DNSSEC validated)" + else: + validated = "(*NOT* DNSSEC validated)" + + if ret == 0: + syslog.syslog( + syslog.LOG_INFO, "Added " + validated + " connection provided forward zone '" + domain + "' with NS: " + servers_list) + else: + syslog.syslog( + syslog.LOG_ERR, "NOT added connection provided forward zone '" + domain + "' with NS: " + servers_list) + + +def unbound_del_forward_zone(domain="", secure=DEFAULT_VALIDATE_FORWARD_ZONES): + """ + Deletes a forward zone from the unbound. + """ + if domain: + cmd = UNBOUND_CONTROL + " forward_remove" + if not secure: + cmd += " +i" + cmd += " " + domain + # Remove the forward zone + ret = subprocess.call(cmd, + stdout=open(os.devnull, "wb"), + stderr=subprocess.STDOUT, + shell=True) + # Flush cache + subprocess.call(UNBOUND_CONTROL + " flush_zone " + domain, + stdout=open(os.devnull, "wb"), + stderr=subprocess.STDOUT, + shell=True) + subprocess.call(UNBOUND_CONTROL + " flush_requestlist", + stdout=open(os.devnull, "wb"), + stderr=subprocess.STDOUT, + shell=True) + if ret == 0: + syslog.syslog( + syslog.LOG_INFO, "Removed connection provided forward zone '" + domain + "'") + else: + syslog.syslog( + syslog.LOG_ERR, "NOT removed connection provided forward zone '" + domain + "'") + + +def unbound_get_forward_zones(): + """ + Returns list of currently configured forward zones from the unbound. + """ + zones = [] + # get all configured forward zones + sp = subprocess.Popen(UNBOUND_CONTROL + " list_forwards", + stdout=subprocess.PIPE, + stderr=open(os.devnull, "wb"), + shell=True) + + sp.wait() + + if sp.returncode == 0: + for line in sp.stdout.readlines(): + zones.append(line.strip().split(" ")[0][:-1]) + + return zones + +############################################################################## + + +def append_fzone_to_file(uuid="", zone=""): + """ + Append forward zones from connection with UUID to the disk file. + """ + if uuid and zone: + with open(os.path.join(STATE_DIR, uuid), "a") as f: + f.write(zone + "\n") + + +def write_fzones_to_file(uuid="", zones=[]): + """ + Write forward zones from connection with UUID to the disk file. + """ + if uuid and zones: + with open(os.path.join(STATE_DIR, uuid), "w") as f: + for zone in zones: + f.write(zone + "\n") + + +def get_fzones_from_file(uuid=""): + """ + Gets all zones from a file with specified UUID name din STATE_DIR + """ + zones = [] + if uuid: + with open(os.path.join(STATE_DIR, uuid), "r") as f: + zones = [line.strip() for line in f.readlines()] + return zones + + +def get_fzones_from_disk(): + """ + Gets all forward zones from the disk STATE_DIR. + Return a dict of "zone" : "connection UUID" + """ + zones = {} + conn_files = os.listdir(STATE_DIR) + for uuid in conn_files: + for zone in get_fzones_from_file(uuid): + zones[zone] = uuid + return zones + + +def del_all_fzones_from_file(uuid="", secure=DEFAULT_VALIDATE_FORWARD_ZONES): + """ + Removes all forward zones contained in file with UUID name in STATE_DIR. + """ + if uuid: + with open(os.path.join(STATE_DIR, uuid), "r") as f: + for line in f.readlines(): + unbound_del_forward_zone(line.strip(), secure) + + +def del_fzones_for_nonexisting_conn(ac=[], secure=DEFAULT_VALIDATE_FORWARD_ZONES): + """ + Removes all forward zones contained in file (in STATE_DIR) for non-existing + active connections. + """ + ac_uuid_list = [conn.get_uuid() for conn in ac] + conn_files = os.listdir(STATE_DIR) + # Remove all non-existing connections zones + for uuid in conn_files: + if uuid not in ac_uuid_list: + # remove all zones from the file + del_all_fzones_from_file(uuid, secure) + # remove the file + os.unlink(os.path.join(STATE_DIR, uuid)) + + +def del_fzone_from_file(uuid="", zone=""): + """ + Deletes a zone from file and writes changes into it. If there are no zones + left, the file is deleted. + """ + if uuid and zone: + zones = get_fzones_from_file(uuid) + zones.remove(zone) + if zones: + write_fzones_to_file(uuid, zones) + else: + os.unlink(os.path.join(STATE_DIR, uuid)) + + +############################################################################## + + +def configure_global_forwarders(active_connections=[]): + """ + Configure global forwarders using dnssec-trigger-control + """ + # get only default connections + default_conns = filter(lambda x: x.get_is_default(), active_connections) + # get forwarders from default connections + default_forwarders = [] + for conn in default_conns: + default_forwarders.extend(conn.get_nameservers()) + + if default_forwarders: + dnssec_trigger_set_global_ns(default_forwarders) + +############################################################################## + + +def configure_forward_zones(active_connections=[], fzones_config=None): + """ + Configures forward zones in the unbound using unbound-control. + """ + # Filter out WIFI connections if desirable + if not fzones_config.add_wifi_zones: + connections = filter( + lambda x: x.get_type() != ActiveConnection.TYPE_WIFI, active_connections) + else: + connections = active_connections + # If validate forward zones + secure = fzones_config.validate_fzones + + # Filter active connections with domain(s) + conns_with_domains = filter(lambda x: x.get_domains(), connections) + fzones_from_ac = {} + # Construct dict of domain -> active connection + for conn in conns_with_domains: + # iterate through all domains in the active connection + for domain in conn.get_domains(): + # if there is already such a domain + if domain in fzones_from_ac: + # if the "conn" is VPN and the conn for existing domain is not + if fzones_from_ac[domain].get_type() != ActiveConnection.TYPE_VPN and conn.get_type() == ActiveConnection.TYPE_VPN: + fzones_from_ac[domain] = conn + # if none of there connections are VPNs or both are VPNs, + # prefer the default one + elif not fzones_from_ac[domain].get_is_default() and conn.get_is_default(): + fzones_from_ac[domain] = conn + else: + fzones_from_ac[domain] = conn + + # Remove all zones which connection UUID does not match any existing AC + del_fzones_for_nonexisting_conn(conns_with_domains, secure) + + # Remove all zones which connection UUID is different than the current AC + # UUID for the zone + fzones_from_disk = get_fzones_from_disk() + for zone, uuid in fzones_from_disk.iteritems(): + connection = fzones_from_ac[zone] + # if the AC UUID is NOT the same as from the disk, remove the zone + if connection.get_uuid() != uuid: + unbound_del_forward_zone(zone, secure) + del_fzone_from_file(uuid, zone) + + # get zones from unbound and delete them from fzones_from_ac + # there may be zones manually configured in unbound.conf and we + # don't want to replace them + unbound_zones = unbound_get_forward_zones() + for zone in unbound_zones: + try: + del fzones_from_ac[zone] + except KeyError: + # we don't mind if there is no such zone + pass + + # Add forward zones that are not already configured + fzones_from_disk = get_fzones_from_disk() + for zone, connection in fzones_from_ac.iteritems(): + if zone not in fzones_from_disk: + unbound_add_forward_zone( + zone, connection.get_nameservers(), secure) + append_fzone_to_file(connection.get_uuid(), zone) + + +############################################################################## + + +if __name__ == "__main__": + if not is_running(DNSSEC_TRIGGER): + syslog.syslog(syslog.LOG_ERR, "dnssec-triggerd daemon is not running!") + sys.exit(1) + if not is_running(UNBOUND): + syslog.syslog(syslog.LOG_ERR, "unbound server daemon is not running!") + sys.exit(1) + + fzones_config = get_fzones_settings_from_conf(DNSSEC_CONF) + + # Get all actove connections from NM + ac = get_nm_active_connections() + # Configure global forwarders + configure_global_forwarders(ac) + # Configure forward zones + configure_forward_zones(ac, fzones_config) diff --git a/dnssec-trigger.spec b/dnssec-trigger.spec index 07e5e5b..595bfaa 100644 --- a/dnssec-trigger.spec +++ b/dnssec-trigger.spec @@ -1,7 +1,7 @@ Summary: NetworkManager plugin to update/reconfigure DNSSEC resolving Name: dnssec-trigger Version: 0.11 -Release: 18%{?dist} +Release: 19%{?dist} License: BSD Url: http://www.nlnetlabs.nl/downloads/dnssec-trigger/ Source: http://www.nlnetlabs.nl/downloads/dnssec-trigger/%{name}-%{version}.tar.gz @@ -9,11 +9,14 @@ Source1:dnssec-triggerd.service Source2: dnssec-triggerd-keygen.service Source3: dnssec-trigger.conf # Latest NM dispatcher hook from upstream SVN -# http://www.nlnetlabs.nl/svn/dnssec-trigger/trunk/01-dnssec-trigger-hook.sh.in +# http://www.nlnetlabs.nl/svn/dnssec-trigger/trunk/contrib/01-dnssec-trigger-hook-new_nm Source4: 01-dnssec-trigger-hook Source5: dnssec-trigger.tmpfiles.d Source6: dnssec-triggerd-resolvconf-handle.sh Source7: dnssec-triggerd-resolvconf-handle.service +# http://www.nlnetlabs.nl/svn/dnssec-trigger/trunk/contrib/dnssec.conf.sample +# we turned the validation of forward zones off, to not break existing installations. +Source8: dnssec.conf.sample Patch1: dnssec-trigger-0.11-improve_dialog_texts.patch Patch2: dnssec-trigger-842455.patch # https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=489 @@ -21,7 +24,7 @@ Patch3: dnssec-trigger-0.11-nl489.patch Patch4: dnssec-trigger-0.11-coverity_scan.patch Requires(postun): initscripts -Requires: ldns >= 1.6.10, NetworkManager, unbound, xdg-utils +Requires: ldns >= 1.6.10, NetworkManager, NetworkManager-glib, unbound, xdg-utils Requires(pre): shadow-utils BuildRequires: desktop-file-utils systemd-units, openssl-devel, ldns-devel BuildRequires: gtk2-devel, NetworkManager-devel @@ -71,8 +74,10 @@ install -m 0644 %{SOURCE7} %{buildroot}%{_unitdir}/%{name}d-resolvconf-handle.se desktop-file-install --dir=%{buildroot}%{_datadir}/applications dnssec-trigger-panel.desktop -# overwrite the stock NM hook since there is new one in upstream SVN that has not been released yet -cp -p %{SOURCE4} %{buildroot}/%{_sysconfdir}/NetworkManager/dispatcher.d/01-dnssec-trigger-hook +# overwrite the stock NM hook since there is new and improved one in upstream SVN contrib/ +install -p -m 0755 %{SOURCE4} %{buildroot}/%{_sysconfdir}/NetworkManager/dispatcher.d/01-dnssec-trigger-hook +# install the /etc/dnssec.conf +install -p -m 0644 %{SOURCE8} %{buildroot}/%{_sysconfdir}/dnssec.conf # install the configuration for /var/run/dnssec-trigger into tmpfiles.d dir mkdir -p %{buildroot}%{_tmpfilesdir} @@ -103,6 +108,7 @@ rm -rf ${RPM_BUILD_ROOT} %attr(0755,root,root) %dir %{_sysconfdir}/%{name} %attr(0755,root,root) %{_sysconfdir}/NetworkManager/dispatcher.d/01-dnssec-trigger-hook +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/dnssec.conf %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/dnssec-trigger.conf %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/xdg/autostart/dnssec-trigger-panel.desktop %dir %{_localstatedir}/run/%{name} @@ -132,6 +138,9 @@ fi %systemd_postun_with_restart %{name}d.service %changelog +* Wed Jan 29 2014 Tomas Hozza - 0.11-19 +- Use new Python dispatcher script and ship /etc/dnssec.conf + * Tue Jan 28 2014 Tomas Hozza - 0.11-18 - Use systemd macros instead of directly calling systemctl - simplify the systemd unit file for generating keys diff --git a/dnssec.conf.sample b/dnssec.conf.sample new file mode 100644 index 0000000..ef29603 --- /dev/null +++ b/dnssec.conf.sample @@ -0,0 +1,54 @@ +# validate_connection_provided_zones: +# ----------------------------------- +# Setts if forward zones added into unbound by dnssec-trigger script +# will be DNSSEC validated or NOT. Note that this setting is global +# for all added forward zones.. +# Possible options are: +# +# validate_connection_provided_zones=yes - All connection provided zones +# configured as forward zones into +# unbound WILL BE DNSSEC validated +# (NOTE: If connection provided DNS +# servers are NOT DNSSEC capable, the +# resolving of provided zones will +# NOT work!) +# +# validate_connection_provided_zones=no - All connection provided zones +# configured as forward zones into +# unbound will NOT be DNSSEC validated +# +# +# NOTICE: if you turn the validation OFF then all forward zones added by +# dnssec-trigger script will NOT be DNSSEC validated. If you turn the +# validation ON, only newly added forward zones will be DNSSEC validated. +# Forward zones added before the change will still NOT be DNSSEC validated. +# To force validation of previously added forward zone you need to restart +# it. For VPNs this can be done by restart NetworkManager. +validate_connection_provided_zones=no + +# add_wifi_provided_zones: +# ------------------------ +# Setts if domains provided by WiFi connection are configured as forward zones +# into unbound. +# Possible options are: +# +# add_wifi_provided_zones=yes - Domains provided by ANY WiFi connection will +# be configured as forward zones into unbound. +# (NOTE: See the possible security implications +# stated below!) +# +# add_wifi_provided_zones=no - Domains provided by ANY WiFi connection will +# NOT be configured as forward zones into unbound. +# (NOTE: Forward zones will be still configured +# for any other type of connection!) +# +# NOTICE: Turning ON the addition of WiFi provided domains as forward zones +# into unbound may have SECURITY implications such as: +# - A WiFi access point can intentionally provide you a domain via DHCP for +# which it does not have authority and route all your DNS queries to its +# DNS servers. +# - In addition to the previous point, if you have the DNSSEC validation +# of forward zones turned OFF, the WiFi provided DNS servers can spoof +# the IP address for domain names from the provided domain WITHOUT YOU +# KNOWING IT! +add_wifi_provided_zones=no