]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/commitdiff
DNS: Fall back to permissive mode if recursor mode is unavailable
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 27 Feb 2017 21:38:03 +0000 (21:38 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 27 Feb 2017 21:38:03 +0000 (21:38 +0000)
The tests when assigning DNS name servers has been extended so that
if no working forwarder can be found, we will test if the local recursor
mode is an option.

If not, we will configure unbound's validator module into permissive
mode so that at least some DNS functionality is available.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
config/rootfiles/core/110/filelists/files
lfs/unbound
src/initscripts/init.d/unbound
src/patches/unbound-allow-setting-validator-permissive-mode-at-runtime.patch [new file with mode: 0644]

index 670b9ae62cd65e716e1c36224ea7972d915c62b8..f4ce9898ef712e84539275bc8129b3eb304a6f9c 100644 (file)
@@ -1,5 +1,6 @@
 etc/system-release
 etc/issue
+etc/rc.d/init.d/unbound
 srv/web/ipfire/cgi-bin/index.cgi
 srv/web/ipfire/cgi-bin/vpnmain.cgi
 usr/lib/libssp.so.0
index 2b7745cd0a13b091961e5ac6c85692156cc5fd74..f361f24f0202bcb9547f38c484e2582afe49653f 100644 (file)
@@ -70,6 +70,7 @@ $(subst %,%_MD5,$(objects)) :
 $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
        @$(PREBUILD)
        @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/unbound-allow-setting-validator-permissive-mode-at-runtime.patch
        cd $(DIR_APP) && \
                ./configure \
                        --prefix=/usr \
index 880278150aed80fd557d32b3b1b944fbfc79e35c..bbf9c002e606a8c79acb551fd24c9a5dfe26f2bc 100644 (file)
@@ -114,17 +114,38 @@ update_forwarders() {
                        echo_warning
                fi
 
-               if [ -n "${broken_forwarders}" -a -z "${forwarders}" ]; then
-                       boot_mesg "Falling back to recursor mode" ${WARNING}
-                       echo_warning
-
-               elif [ -n "${forwarders}" ]; then
+               if [ -n "${forwarders}" ]; then
                        boot_mesg "Configuring upstream name server(s): ${forwarders:1}" ${INFO}
                        echo_ok
 
+                       # Make sure DNSSEC is activated
+                       enable_dnssec
+
                        echo "${forwarders}" > /var/ipfire/red/dns
                        unbound-control -q forward ${forwarders}
                        return 0
+
+               # In case we have found no working forwarders
+               else
+                       # Test if the recursor mode is available
+                       if can_resolve_root +bufsize=${new_edns_buffer_size}; then
+                               # Make sure DNSSEC is activated
+                               enable_dnssec
+
+                               boot_mesg "Falling back to recursor mode" ${WARNING}
+                               echo_warning
+
+                       # If not, we set DNSSEC in permissive mode and allow using all recursors
+                       elif [ -n "${broken_forwarders}" ]; then
+                               disable_dnssec
+
+                               boot_mesg "DNSSEC has been set to permissive mode" ${FAILURE}
+                               echo_failure
+
+                               echo "${broken_forwarders}" > /var/ipfire/red/dns
+                               unbound-control -q forward ${broken_forwarders}
+                               return 0
+                       fi
                fi
        fi
 
@@ -370,6 +391,42 @@ ns_determine_edns_buffer_size() {
        return 1
 }
 
+get_root_nameservers() {
+       while read -r hostname ttl record address; do
+               # Searching for A records
+               [ "${record}" = "A" ] || continue
+
+               echo "${address}"
+       done < /etc/unbound/root.hints
+}
+
+can_resolve_root() {
+       local ns
+       for ns in $(get_root_nameservers); do
+               if dig @${ns} +dnssec SOA . $@ >/dev/null; then
+                       return 0
+               fi
+       done
+
+       # none of the servers was reachable
+       return 1
+}
+
+enable_dnssec() {
+       local status=$(unbound-control get_option val-permissive-mode)
+
+       # Don't do anything if DNSSEC is already activated
+       [ "${status}" = "no" ] && return 0
+
+       # Activate DNSSEC and flush cache with any stale and unvalidated data
+       unbound-control -q set_option val-permissive-mode: no
+       unbound-control -q flush_zone .
+}
+
+disable_dnssec() {
+       unbound-control -q set_option val-permissive-mode: yes
+}
+
 case "$1" in
        start)
                # Print a nicer messagen when unbound is already running
diff --git a/src/patches/unbound-allow-setting-validator-permissive-mode-at-runtime.patch b/src/patches/unbound-allow-setting-validator-permissive-mode-at-runtime.patch
new file mode 100644 (file)
index 0000000..f476d08
--- /dev/null
@@ -0,0 +1,43 @@
+diff --git a/validator/validator.c b/validator/validator.c
+index 676dcdf..7c19f3d 100644
+--- a/validator/validator.c
++++ b/validator/validator.c
+@@ -113,7 +113,7 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env,
+       int c;
+       val_env->bogus_ttl = (uint32_t)cfg->bogus_ttl;
+       val_env->clean_additional = cfg->val_clean_additional;
+-      val_env->permissive_mode = cfg->val_permissive_mode;
++      val_env->permissive_mode = &cfg->val_permissive_mode;
+       if(!env->anchors)
+               env->anchors = anchors_create();
+       if(!env->anchors) {
+@@ -170,7 +170,6 @@ val_init(struct module_env* env, int id)
+       }
+       env->modinfo[id] = (void*)val_env;
+       env->need_to_validate = 1;
+-      val_env->permissive_mode = 0;
+       lock_basic_init(&val_env->bogus_lock);
+       lock_protect(&val_env->bogus_lock, &val_env->num_rrset_bogus,
+               sizeof(val_env->num_rrset_bogus));
+@@ -2084,7 +2083,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
+                       }
+               }
+               /* If we are in permissive mode, bogus gets indeterminate */
+-              if(ve->permissive_mode)
++              if(*ve->permissive_mode)
+                       vq->orig_msg->rep->security = sec_status_indeterminate;
+       }
+diff --git a/validator/validator.h b/validator/validator.h
+index 23d3072..f8464b8 100644
+--- a/validator/validator.h
++++ b/validator/validator.h
+@@ -104,7 +104,7 @@ struct val_env {
+        * This allows an operator to run validation 'shadow' without
+        * hurting responses to clients.
+        */
+-      int permissive_mode;
++      int* permissive_mode;
+       /**
+        * Number of entries in the NSEC3 maximum iteration count table.