]> git.ipfire.org Git - ipfire-2.x.git/commitdiff
unbound: Add option to force using TCP for upstream servers
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 1 Oct 2019 11:36:16 +0000 (12:36 +0100)
committerArne Fitzenreiter <arne_f@ipfire.org>
Tue, 8 Oct 2019 18:42:18 +0000 (18:42 +0000)
Some users have problems to reach DNS servers. This change adds an option
which allows to force using TCP for upstream name servers.

This is a good workaround for users behind a broken Fritz!Box in modem
mode which does not allow resolving any records of the root zone.

The name server tests in the script will also only use TCP.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Signed-off-by: Arne Fitzenreiter <arne_f@ipfire.org>
src/initscripts/system/unbound

index dbcfc951f0d83a0e7870c27f32bf2eec6cc287ef..d195fd3256dc695cef32dd36615ff99a78359c8f 100644 (file)
@@ -15,6 +15,7 @@ TEST_DOMAIN_FAIL="dnssec-failed.org"
 INSECURE_ZONES=
 USE_FORWARDERS=1
 ENABLE_SAFE_SEARCH=off
+FORCE_TCP=off
 
 # Cache any local zones for 60 seconds
 LOCAL_TTL=60
@@ -25,6 +26,12 @@ EDNS_DEFAULT_BUFFER_SIZE=4096
 # Load optional configuration
 [ -e "/etc/sysconfig/unbound" ] && . /etc/sysconfig/unbound
 
+DIG_ARGS=()
+
+if [ "${FORCE_TCP}" = "on" ]; then
+       DIG_ARGS+=( "+tcp" )
+fi
+
 ip_address_revptr() {
        local addr=${1}
 
@@ -199,6 +206,14 @@ write_forward_conf() {
        (
                config_header
 
+               # Force using TCP for upstream servers only
+               if [ "${FORCE_TCP}" = "on" ]; then
+                       echo "# Force using TCP for upstream servers only"
+                       echo "server:"
+                       echo "  tcp-upstream: yes"
+                       echo
+               fi
+
                local insecure_zones="${INSECURE_ZONES}"
 
                local enabled zone server servers remark disable_dnssec rest
@@ -391,7 +406,7 @@ ns_is_online() {
        local ns=${1}
        shift
 
-       dig @${ns} +nodnssec A ${TEST_DOMAIN} $@ >/dev/null
+       dig "${DIG_ARGS[@]}" @${ns} +nodnssec A ${TEST_DOMAIN} $@ >/dev/null
 }
 
 # Resolving ${TEST_DOMAIN_FAIL} will fail if the nameserver is validating
@@ -399,11 +414,11 @@ ns_is_validating() {
        local ns=${1}
        shift
 
-       if ! dig @${ns} A ${TEST_DOMAIN_FAIL} $@ | grep -q SERVFAIL; then
+       if ! dig "${DIG_ARGS[@]}" @${ns} A ${TEST_DOMAIN_FAIL} $@ | grep -q SERVFAIL; then
                return 1
        else
                # Determine if NS replies with "ad" data flag if DNSSEC enabled
-               dig @${ns} +dnssec SOA ${TEST_DOMAIN} $@ | awk -F: '/\;\;\ flags\:/ { s=1; if (/\ ad/) s=0; exit s }'
+               dig "${DIG_ARGS[@]}" @${ns} +dnssec SOA ${TEST_DOMAIN} $@ | awk -F: '/\;\;\ flags\:/ { s=1; if (/\ ad/) s=0; exit s }'
        fi
 }
 
@@ -413,28 +428,33 @@ ns_forwards_DNSKEY() {
        local ns=${1}
        shift
 
-       dig @${ns} DNSKEY ${TEST_DOMAIN} $@ | grep -qv SOA
+       dig "${DIG_ARGS[@]}" @${ns} DNSKEY ${TEST_DOMAIN} $@ | grep -qv SOA
 }
 
 ns_forwards_DS() {
        local ns=${1}
        shift
 
-       dig @${ns} DS ${TEST_DOMAIN} $@ | grep -qv SOA
+       dig "${DIG_ARGS[@]}" @${ns} DS ${TEST_DOMAIN} $@ | grep -qv SOA
 }
 
 ns_forwards_RRSIG() {
        local ns=${1}
        shift
 
-       dig @${ns} +dnssec A ${TEST_DOMAIN} $@ | grep -q RRSIG
+       dig "${DIG_ARGS[@]}" @${ns} +dnssec A ${TEST_DOMAIN} $@ | grep -q RRSIG
 }
 
 ns_supports_tcp() {
        local ns=${1}
        shift
 
-       dig @${ns} +tcp A ${TEST_DOMAIN} $@ >/dev/null || return 1
+       # If TCP is forced we know by now if the server responds to it
+       if [ "${FORCE_TCP}" = "on" ]; then
+               return 0
+       fi
+
+       dig "${DIG_ARGS[@]}" @${ns} +tcp A ${TEST_DOMAIN} $@ >/dev/null || return 1
 }
 
 ns_determine_edns_buffer_size() {
@@ -443,7 +463,7 @@ ns_determine_edns_buffer_size() {
 
        local b
        for b in 4096 2048 1500 1480 1464 1400 1280 512; do
-               if dig @${ns} +dnssec +bufsize=${b} A ${TEST_DOMAIN} $@ >/dev/null; then
+               if dig "${DIG_ARGS[@]}" @${ns} +dnssec +bufsize=${b} A ${TEST_DOMAIN} $@ >/dev/null; then
                        echo "${b}"
                        return 0
                fi
@@ -464,7 +484,7 @@ get_root_nameservers() {
 can_resolve_root() {
        local ns
        for ns in $(get_root_nameservers); do
-               if dig @${ns} +dnssec SOA . $@ >/dev/null; then
+               if dig "${DIG_ARGS[@]}" @${ns} +dnssec SOA . $@ >/dev/null; then
                        return 0
                fi
        done
@@ -514,7 +534,7 @@ resolve() {
        local ns
        for ns in $(read_name_servers); do
                local answer
-               for answer in $(dig +short "@${ns}" A "${hostname}"); do
+               for answer in $(dig "${DIG_ARGS[@]}" +short "@${ns}" A "${hostname}"); do
                        found=1
 
                        # Filter out non-IP addresses