1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
#!/bin/bash
#
# Integration tests against external hosts.
#
# The goal is to test how dnss interacts with publicly available services.
#
# These tests use the network and public internet to talk to:
# - the machine's configured DNS server
# - dns.google.com
# - 1.1.1.1.
#
# So the tests are not hermetic and could fail for external reasons.
set -e
# Set traps to kill our subprocesses when we exit (for any reason).
trap ":" TERM # Avoid the EXIT handler from killing bash.
trap "exit 2" INT # Ctrl-C, make sure we fail in that case.
trap "kill 0" EXIT # Kill children on exit.
# The tests are run from the repository root.
cd "$(realpath `dirname ${0}`)/../"
# Build the dnss binary.
if [ "$COVER_DIR" != "" ]; then
go test -covermode=count -coverpkg=./... -c -tags coveragebin
mv dnss.test dnss
else
go build
fi
# Run dnss in the background (sets $PID to its process id).
function dnss() {
# Set the coverage arguments each time, as we don't want the different
# runs to override the generated profile.
if [ "$COVER_DIR" != "" ]; then
COVER_ARGS="-test.run=^TestRunMain$ \
-test.coverprofile=$COVER_DIR/it-`date +%s.%N`.out"
fi
$SYSTEMD_ACTIVATE ./dnss $COVER_ARGS \
-v 3 -monitoring_listen_addr :1900 \
"$@" > .dnss.log 2>&1 &
PID=$!
}
# Wait until there's something listening on the given port.
function wait_until_ready() {
PROTO=$1
PORT=$2
while ! bash -c "true < /dev/$PROTO/localhost/$PORT" 2>/dev/null ; do
sleep 0.01
done
}
# Resolve some queries.
function resolve() {
wait_until_ready tcp 1053
kdig @127.0.0.1:1053 +tcp example.com a > .dig.log
grep -E -q '^example.com.*A' .dig.log
kdig @127.0.0.1:1053 +notcp example.com a > .dig.log
grep -E -q '^example.com.*A' .dig.log
kdig @127.0.0.1:1053 +notcp com.ar NS > .dig.log
grep -E -q '^com.ar.*NS' .dig.log
}
# HTTP GET, using wget.
function get() {
URL=$1
wget -O/dev/null $URL > .wget.log 2>&1
}
echo "## Misc"
# Missing arguments (expect it to fail).
dnss
if wait $PID; then
echo "Expected dnss to fail, but it worked"
exit 1
fi
echo "## Launching HTTPS server"
dnss -enable_https_to_dns \
-testing__insecure_http -https_server_addr "localhost:1999"
HTTP_PID=$PID
mv .dnss.log .dnss.http.log
wait_until_ready tcp 1999
echo "## Autodetect against dnss"
dnss -enable_dns_to_https -dns_listen_addr "localhost:1053" \
-testing__insecure_http \
-https_upstream "http://localhost:1999/dns-query"
resolve
kill $PID
echo "## JSON against dnss"
dnss -enable_dns_to_https -dns_listen_addr "localhost:1053" \
-testing__insecure_http \
-force_mode="JSON" \
-https_upstream "http://localhost:1999/dns-query"
resolve
# Exercise some interesting JSON requests.
get "http://localhost:1999/dns-query?name=test&edns_client_subnet=1.2.3.4/24"
get "http://localhost:1999/dns-query?name=test&edns_client_subnet=2001:700:300::/48"
if get "http://localhost:1999/dns-query?name=test&type=lalala"; then
echo "GET with invalid query did not fail"
exit 1
fi
kill $PID
echo "## DoH against dnss"
dnss -enable_dns_to_https -dns_listen_addr "localhost:1053" \
-testing__insecure_http \
-force_mode="DoH" \
-https_upstream "http://localhost:1999/dns-query"
# Exercise DoH via GET (dnss always uses POST).
get "http://localhost:1999/resolve?&dns=q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB"
if get "http://localhost:1999/resolve?&dns=invalidbase64@"; then
echo "GET with invalid base64 did not fail"
exit 1
fi
if get "http://localhost:1999/resolve?nothing"; then
echo "GET with nonsense query did not fail"
exit 1
fi
resolve
kill $PID
kill $HTTP_PID
echo "## Autodetect against 1.1.1.1"
dnss -enable_dns_to_https -dns_listen_addr "localhost:1053" \
-https_upstream "https://1.1.1.1/dns-query"
resolve
kill $PID
echo "## DoH against 1.1.1.1"
dnss -enable_dns_to_https -dns_listen_addr "localhost:1053" \
-force_mode="DoH" \
-https_upstream "https://1.1.1.1/dns-query"
resolve
kill $PID
echo "## Autodetect against dns.google.com"
dnss -enable_dns_to_https -dns_listen_addr "localhost:1053" \
-https_upstream "https://dns.google.com/resolve"
resolve
kill $PID
echo "## JSON against dns.google.com"
dnss -enable_dns_to_https -dns_listen_addr "localhost:1053" \
-force_mode="JSON" \
-https_upstream "https://dns.google.com/resolve"
resolve
kill $PID
echo "## Defaults"
dnss -enable_dns_to_https -dns_listen_addr "localhost:1053"
resolve
# Take this opportunity to query some URLs, to exercise their code when they
# have requests.
get http://localhost:1900/debug/dnsserver/cache/dump
get http://localhost:1900/debug/dnsserver/cache/flush
kill $PID
# systemd socket activation tests must check one protocol at a time, due to
# systemd-socket-activate not being able to listen on both.
echo "## Socket activation via systemd: TCP"
SYSTEMD_ACTIVATE="systemd-socket-activate -l 1053"
dnss -enable_dns_to_https -dns_listen_addr "systemd"
wait_until_ready tcp 1053
kdig @127.0.0.1:1053 +tcp example.com a > .dig.log
grep -E -q '^example.com.*A' .dig.log
kill $PID
echo "## Socket activation via systemd: UDP"
SYSTEMD_ACTIVATE="systemd-socket-activate -d -l 1053"
dnss -enable_dns_to_https -dns_listen_addr "systemd"
kdig @127.0.0.1:1053 +notcp example.com a > .dig.log
grep -E -q '^example.com.*A' .dig.log
kill $PID
echo SUCCESS
|