mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-27 11:13:24 +02:00
unbound: Test upstream name servers before using
unbound has some trouble with validating DNSSEC-enabled domains when the upstream name server is stripping signatures from the authoritative responses. This script now checks that, removes any broken upstream name servers from the list and prints a warning. If all name servers fail the test, unbound falls back into recursor mode. Signed-off-by: Arne Fitzenreiter <arne_f@ipfire.org>
This commit is contained in:
@@ -7,6 +7,11 @@
|
|||||||
. /etc/sysconfig/rc
|
. /etc/sysconfig/rc
|
||||||
. ${rc_functions}
|
. ${rc_functions}
|
||||||
|
|
||||||
|
TEST_DOMAIN="ipfire.org"
|
||||||
|
|
||||||
|
# This domain will never validate
|
||||||
|
TEST_DOMAIN_FAIL="dnssec-failed.org"
|
||||||
|
|
||||||
USE_FORWARDERS=1
|
USE_FORWARDERS=1
|
||||||
|
|
||||||
# Cache any local zones for 60 seconds
|
# Cache any local zones for 60 seconds
|
||||||
@@ -53,18 +58,45 @@ config_header() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update_forwarders() {
|
update_forwarders() {
|
||||||
local forwarders="$(read_name_servers)"
|
if [ "${USE_FORWARDERS}" = "1" -a -e "/var/ipfire/red/active" ]; then
|
||||||
|
local forwarders
|
||||||
|
local broken_forwarders
|
||||||
|
|
||||||
if [ "${USE_FORWARDERS}" = "1" ] && [ -n "${forwarders}" ]; then
|
local ns
|
||||||
boot_mesg "Using Name Server(s): ${forwarders}"
|
for ns in $(read_name_servers); do
|
||||||
boot_mesg_flush
|
test_name_server ${ns} &>/dev/null
|
||||||
|
case "$?" in
|
||||||
|
# Only use DNSSEC-validating or DNSSEC-aware name servers
|
||||||
|
0|2)
|
||||||
|
forwarders="${forwarders} ${ns}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
broken_forwarders="${broken_forwarders} ${ns}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
unbound-control -q forward ${forwarders}
|
# Show warning for any broken upstream name servers
|
||||||
|
if [ -n "${broken_forwarders}" ]; then
|
||||||
|
boot_mesg "Ignoring broken upstream name server(s): ${broken_forwarders:1}" ${WARNING}
|
||||||
|
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
|
||||||
|
boot_mesg "Configuring upstream name server(s): ${forwarders:1}" ${INFO}
|
||||||
|
echo_ok
|
||||||
|
|
||||||
|
unbound-control -q forward ${forwarders}
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# If forwarders cannot be used we run in recursor mode
|
# If forwarders cannot be used we run in recursor mode
|
||||||
else
|
unbound-control -q forward off
|
||||||
unbound-control -q forward off
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_hosts() {
|
update_hosts() {
|
||||||
@@ -179,6 +211,77 @@ get_memory_amount() {
|
|||||||
done < /proc/meminfo
|
done < /proc/meminfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_name_server() {
|
||||||
|
local ns=${1}
|
||||||
|
|
||||||
|
# Return codes:
|
||||||
|
# 0 DNSSEC validating
|
||||||
|
# 1 Error: unreachable, etc.
|
||||||
|
# 2 DNSSEC aware
|
||||||
|
# 3 NOT DNSSEC-aware
|
||||||
|
|
||||||
|
# Exit when the server is not reachable
|
||||||
|
ns_is_online ${ns} || return 1
|
||||||
|
|
||||||
|
# Return 0 if validating
|
||||||
|
ns_is_validating ${ns} && return 0
|
||||||
|
|
||||||
|
local errors
|
||||||
|
for rr in DNSKEY DS RRSIG; do
|
||||||
|
if ! ns_forwards_${rr} ${ns}; then
|
||||||
|
errors="${errors} ${rr}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "${errors}" ]; then
|
||||||
|
echo >&2 "Unable to retrieve the following resource records from ${ns}: ${errors:1}"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Is DNSSEC-aware
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sends an A query to the nameserver w/o DNSSEC
|
||||||
|
ns_is_online() {
|
||||||
|
local ns=${1}
|
||||||
|
|
||||||
|
dig @${ns} +nodnssec A ${TEST_DOMAIN} >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Resolving ${TEST_DOMAIN_FAIL} will fail if the nameserver is validating
|
||||||
|
ns_is_validating() {
|
||||||
|
local ns=${1}
|
||||||
|
|
||||||
|
dig @${ns} A ${TEST_DOMAIN_FAIL} | grep -q SERVFAIL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Checks if we can retrieve the DNSKEY for this domain.
|
||||||
|
# dig will print the SOA if nothing was found
|
||||||
|
ns_forwards_DNSKEY() {
|
||||||
|
local ns=${1}
|
||||||
|
|
||||||
|
dig @${ns} DNSKEY ${TEST_DOMAIN} | grep -qv SOA
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_forwards_DS() {
|
||||||
|
local ns=${1}
|
||||||
|
|
||||||
|
dig @${ns} DS ${TEST_DOMAIN} | grep -qv SOA
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_forwards_RRSIG() {
|
||||||
|
local ns=${1}
|
||||||
|
|
||||||
|
dig @${ns} +dnssec A ${TEST_DOMAIN} | grep -q RRSIG
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_supports_tcp() {
|
||||||
|
local ns=${1}
|
||||||
|
|
||||||
|
dig @${ns} +tcp A ${TEST_DOMAIN} >/dev/null || return 1
|
||||||
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
# Print a nicer messagen when unbound is already running
|
# Print a nicer messagen when unbound is already running
|
||||||
@@ -228,8 +331,38 @@ case "$1" in
|
|||||||
update_forwarders
|
update_forwarders
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
test-name-server)
|
||||||
|
ns=${2}
|
||||||
|
|
||||||
|
test_name_server ${ns}
|
||||||
|
ret=${?}
|
||||||
|
|
||||||
|
case "${ret}" in
|
||||||
|
0)
|
||||||
|
echo "${ns} is validating"
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
echo "${ns} is DNSSEC-aware"
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
echo "${ns} is NOT DNSSEC-aware"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Test failed for an unknown reason"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if ns_supports_tcp ${ns}; then
|
||||||
|
echo "${ns} supports TCP fallback"
|
||||||
|
else
|
||||||
|
echo "${ns} does not support TCP fallback"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit ${ret}
|
||||||
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "Usage: $0 {start|stop|restart|status|update-forwarders}"
|
echo "Usage: $0 {start|stop|restart|status|update-forwarders|test-name-server}"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Reference in New Issue
Block a user