Test for DNSSEC and DNS over TLS (DoT) via command line

How can I test for DNSSEC and/or DNS over TLS (DoT) via command line? I know I can add Servers in IPFire and then click Check DNS Servers but I wanted to test via a command.

Hi Jon,
kdig is already in the IPFires basis system and can be used for this. If you set the DO-Flag in the request the AD-Flag (authentication answer) should be seen in the returned header if DNSSEC works properly.
So let´s say we want to check the DoT resolver from Lightningwirelabs with a kdig command.

DoT IP = 81.3.27.54
TLS Hostname = recursor01.dns.ipfire.org
GnuTLS bundled cert directory = /etc/ssl/certs/ca-bundle.crt
DO-Flag = +dnssec
With a query to = www.isoc.org

Let´s get the parameters to a command together:

kdig -d @81.3.27.54 +dnssec +tls-ca=/etc/ssl/certs/ca-bundle.crt +tls-host=recursor01.dns.lightningwirelabs.com www.isoc.org

which can generates the following output.

;; DEBUG: Querying for owner(www.isoc.org.), class(1), type(1), server(81.3.27.54), port(853), protocol(TCP)
;; DEBUG: TLS, imported 138 certificates from '/etc/ssl/certs/ca-bundle.crt'
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG:  #1, CN=recursor01.dns.lightningwirelabs.com
;; DEBUG:      SHA-256 PIN: pRkLbNTOGLXo3d2RtPmM8hIGB/zySnZCxaDLNlvg0rI=
;; DEBUG:  #2, C=US,O=Let's Encrypt,CN=Let's Encrypt Authority X3
;; DEBUG:      SHA-256 PIN: YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=
;; DEBUG: TLS, skipping certificate PIN check
;; DEBUG: TLS, The certificate is trusted. 
;; TLS session (TLS1.3)-(ECDHE-SECP256R1)-(ECDSA-SECP384R1-SHA384)-(AES-256-GCM)
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 26816
;; Flags: qr rd ra ad; QUERY: 1; ANSWER: 2; AUTHORITY: 0; ADDITIONAL: 1

;; EDNS PSEUDOSECTION:
;; Version: 0; flags: do; UDP size: 512 B; ext-rcode: NOERROR

;; QUESTION SECTION:
;; www.isoc.org.       		IN	A

;; ANSWER SECTION:
www.isoc.org.       	300	IN	A	46.43.36.222
www.isoc.org.       	300	IN	RRSIG	A 7 3 300 20200319085007 20200305085007 29027 isoc.org. e/eOhpAB2WDlcnp7DOpL4+QaMPmKlM5jWvz1eNPG3FGwz8NWwiGdNP6IVLLZqtxW1R/YGULN2jQiQfi/3j19SLFRJkh55TikL43oIT4tyyJpmQZJ3ZbGlaqp984t74PI7xZRrRw6CPE+vSXy3y/eoNswlXPRNqABDV4obq6lmuI=

;; Received 225 B
;; Time 2020-03-05 21:08:57 CET
;; From 81.3.27.54@853(TCP) in 101.1 ms

a look into the “Flags” line shows the ‘ad’ (Authenticated Data) flag which is the indicator that the data was authenticated.

As a first idea.

Best,

Erik

1 Like

Thank you! This helps! What test was run to produce the results below?

Hi Jon,
am using this script

#!/bin/bash -

#
# Test DNS-over-TLS connections configured since the new  Core 141 IPFire DNS system.
# Check will be performed with kdig which strps out information about 
# Certificate validation, DNSSEC, Time and encryption.
# Warning and errors will also be outlined.
#
# ummeegge ipfire.org; 07.02.2020
####################################################################################
#

# Paths
CONFIG="/var/ipfire/dns/servers"
SETTINGS="/var/ipfire/dns/settings"
BUNDLE="/etc/ssl/certs/ca-bundle.crt"

# Text and formatting
COLUMNS="$(tput cols)";
R=$(tput setaf 1);
G=$(tput setaf 2);
O=$(tput setaf 166)
N=$(tput sgr0);
seperator(){ printf -v _hr "%*s" ${COLUMNS} && echo ${_hr// /${1-=}}; }
WELCOME="${b}${O}Will check now your configured DNS-over-TLS servers from '${CONFIG}'${N}"


# Check for DoT forwarder
if ! grep -q 'PROTO=TLS' ${SETTINGS} > /dev/null 2>&1; then
	echo "DNS-over-TLS is not configured yet. Need to quit... "
	exit 1
fi

# Get DoT data and write it to files
HOST="/tmp/host.in"
IP="/tmp/ip.in"
awk -F',' '/enabled/ { print $3 }' ${CONFIG} > ${HOST}
awk -F',' '/enabled/ { print $2 }' ${CONFIG} > ${IP}


# Mainpart
clear
seperator "$@"
echo
printf "%*s\n" $(((${#WELCOME}+COLUMNS)/2)) "${WELCOME}";
while read -u 3 -r ip && read -u 4 -r host; do
	echo
	seperator "$@"
	echo "From Host: ${O}${host}${N} ---- With IP: ${O}${ip}${N} ---- Date: ${O}$(date)${N}"
	echo
	IFS=$'\n'
	check_array=( $(kdig -d @"${ip}" +dnssec +tls-ca=${BUNDLE} +tls-host="${host}" www.isoc.org | \
		grep -oE 'The certificate.*|TLS session.*|ra ad;|\(TCP\) in .*' | sed -e 's/;//g' -e 's/(TCP) //g') )
	for element in "${check_array[@]}"; do
		echo "${element}" | sed -e '/The certificate is trusted./d' -e '/TLS session.*/d' -e '/ra.*/d'
	done
	echo

	# Check TLS
	if echo "${check_array[1]}" | grep -q 'TLS session'; then
		ENC=$(echo "${check_array[1]}" | awk '{ print $3 }' | sed -e 's/(//g' -e 's/)//g')
		echo "${G}The encryption is OK and works with: ${ENC}${N}"
	else
		echo "${R}Encryption do not works, this server seems to be OFF${N}"
		continue

	fi
	echo

	# Check certificate trust
	if [ "${check_array[0]}" = "The certificate is trusted. " ]; then
		echo "${G}The certificate is trusted and OK${N}"
	else
		echo "${R}The certificate is NOT Trusted and NOT OK${N}"
	fi
	echo

	# Check DNSSEC
	if [ "${check_array[2]}" = "ra ad" ]; then
		echo "${G}The DNSSEC validation works and is OK${N}"
	else
		echo "${R}The DNSSEC validation do NOT works and is NOT OK${N}"
	fi

done 3<${IP} 4<${HOST}

echo
seperator
echo
echo "All enabled DNS-over-TLS servers from ${CONFIG} has been tested."

# Clean up
rm -rf ${IP} ${HOST}

# EOF

for this test for a better overview. The script checks all enabled lines under /var/ipfire/dns/servers if DNS-over-TLS is in usage.

Best,

Erik

2 Likes

I’m still digging thru this one… Since DoT servers are a little hard to find here in the US, how would I change this script to test for DNSSEC only if DoT is not available? Is that possible?

From Host: cdns01.comcast.net ---- With IP: 75.75.75.75 ---- Date: Fri 06 Mar 2020 01:34:02 PM CST

;; WARNING: connection timeout for 75.75.75.75@853(TCP)

;; ERROR: failed to query server 75.75.75.75@853(TCP)

Encryption do not works, this server seems to be OFF

For a simple one -->

kdig cdns01.comcast.net +dnssec +multi

if you do not use DoT you can also check this via dig (aslo available in the core system) whereby the syntax is pretty much the same. For a little more explanation --> https://docs.menandmice.com/display/MM/How+to+test+DNSSEC+validation .

Best,

Erik

1 Like

Do you happen to know anything about the first field in each row of “/var/ipfire/dns/servers” ?
The value before ,IP, HOST? What it is? How it’s used?

I believe it is the priority of DNS server used from the Domain Name System webpage.

from the blog:
What you can do with the new DNS features in IPFire

The new UI allows you to enter as many DNS servers as you like. Two is rather conservative and I would recommend to have at least four. The fastest one will always be used, so there is no downside in having a couple more in there, even if they are further away. You will get better resilience against a downtime, too.

Hi all,
the first field is the ID. The first two IDs are reserved for potential configuration of the ISP DNS. Since there are several checks in the background if you configure a new resolver or by checking existing ones the order of /var/ipfire/dns/servers but also /etc/unbound/forward.conf (both are equal in order) depends on how fast the status is clear i think but may there is also more which i do not know…

Best,

Erik