/
/
/
1#!/bin/bash
2# ==============================================================================
3# DNS Test Script
4# ==============================================================================
5#
6# Description: Comprehensive DNS functionality testing script
7# Usage: ./dns-test.sh [basic|full|latency|security|debug]
8#
9# This script is automatically generated by Ansible - DO NOT EDIT MANUALLY
10# Template: dns-test.sh.j2
11#
12# ==============================================================================
13
14set -euo pipefail
15
16# Configuration
17DNS_SERVER="127.0.0.1"
18DNS_PORT={{ pihole_dns_port }}
19TEST_DOMAINS=(
20 "google.com"
21 "github.com"
22 "microsoft.com"
23 "amazon.com"
24 "cloudflare.com"
25 "wikipedia.org"
26 "stackoverflow.com"
27 "reddit.com"
28 "twitter.com"
29 "netflix.com"
30)
31
32BLOCKED_DOMAINS=(
33 "doubleclick.net"
34 "googleadservices.com"
35 "googlesyndication.com"
36 "adservice.google.com"
37 "ads.youtube.com"
38)
39
40LOCAL_DOMAINS=(
41 "localhost"
42 "pi.hole"
43 "pihole.local"
44)
45
46LOG_FILE="/var/log/dns-test.log"
47TIMEOUT=3
48RETRIES=2
49
50# Logging function
51log() {
52 echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "${LOG_FILE}"
53}
54
55# Test DNS resolution for a domain
56test_domain() {
57 local domain="$1"
58 local expected_result="${2:-success}"
59
60 log "Testing domain: ${domain} (expected: ${expected_result})"
61
62 local start_time=$(date +%s%N)
63
64 if dig +short +time=${TIMEOUT} +tries=${RETRIES} @${DNS_SERVER} -p ${DNS_PORT} "${domain}" >/dev/null 2>&1; then
65 local end_time=$(date +%s%N)
66 local duration=$(( (end_time - start_time) / 1000000 ))
67
68 if [[ "${expected_result}" == "success" ]]; then
69 log "â SUCCESS: ${domain} resolved in ${duration}ms"
70 return 0
71 else
72 log "â UNEXPECTED: ${domain} resolved (should be blocked) in ${duration}ms"
73 return 1
74 fi
75 else
76 local end_time=$(date +%s%N)
77 local duration=$(( (end_time - start_time) / 1000000 ))
78
79 if [[ "${expected_result}" == "blocked" ]]; then
80 log "â SUCCESS: ${domain} correctly blocked in ${duration}ms"
81 return 0
82 else
83 log "â FAILURE: ${domain} failed to resolve in ${duration}ms"
84 return 1
85 fi
86 fi
87}
88
89# Test DNS latency
90test_latency() {
91 local domain="$1"
92 local iterations="${2:-5}"
93
94 local total_time=0
95 local successes=0
96 local min_time=999999
97 local max_time=0
98
99 log "Testing latency for ${domain} (${iterations} iterations)"
100
101 for ((i=1; i<=iterations; i++)); do
102 local start_time=$(date +%s%N)
103
104 if dig +short +time=${TIMEOUT} +tries=1 @${DNS_SERVER} -p ${DNS_PORT} "${domain}" >/dev/null 2>&1; then
105 local end_time=$(date +%s%N)
106 local duration=$(( (end_time - start_time) / 1000000 ))
107
108 total_time=$((total_time + duration))
109 successes=$((successes + 1))
110
111 if [[ ${duration} -lt ${min_time} ]]; then
112 min_time=${duration}
113 fi
114
115 if [[ ${duration} -gt ${max_time} ]]; then
116 max_time=${duration}
117 fi
118
119 log " Iteration ${i}: ${duration}ms"
120 else
121 log " Iteration ${i}: FAILED"
122 fi
123
124 sleep 0.1
125 done
126
127 if [[ ${successes} -gt 0 ]]; then
128 local avg_time=$((total_time / successes))
129 log " Latency summary: min=${min_time}ms, avg=${avg_time}ms, max=${max_time}ms, success_rate=$((successes * 100 / iterations))%"
130 else
131 log " Latency test failed for ${domain}"
132 fi
133}
134
135# Test DNSSEC validation
136test_dnssec() {
137 local dnssec_domains=(
138 "isc.org"
139 "dnssec-failed.org"
140 "cloudflare.com"
141 )
142
143 log "Testing DNSSEC validation"
144
145 for domain in "${dnssec_domains[@]}"; do
146 local result=$(dig +dnssec +short @${DNS_SERVER} -p ${DNS_PORT} "${domain}" 2>&1)
147
148 if echo "${result}" | grep -q "ad flag"; then
149 log "â DNSSEC: ${domain} validated successfully"
150 elif echo "${result}" | grep -q "SERVFAIL"; then
151 log "â DNSSEC: ${domain} correctly failed validation"
152 else
153 log "? DNSSEC: ${domain} - no validation information"
154 fi
155 done
156}
157
158# Test DNS over TCP
159test_tcp() {
160 log "Testing DNS over TCP"
161
162 for domain in "${TEST_DOMAINS[@]:0:3}"; do
163 if dig +short +tcp +time=${TIMEOUT} @${DNS_SERVER} -p ${DNS_PORT} "${domain}" >/dev/null 2>&1; then
164 log "â TCP: ${domain} resolved successfully over TCP"
165 else
166 log "â TCP: ${domain} failed over TCP"
167 fi
168 done
169}
170
171# Test reverse DNS
172test_reverse_dns() {
173 log "Testing reverse DNS lookup"
174
175 # Test common IP addresses
176 local test_ips=(
177 "8.8.8.8"
178 "1.1.1.1"
179 "9.9.9.9"
180 )
181
182 for ip in "${test_ips[@]}"; do
183 if dig +short -x ${ip} @${DNS_SERVER} -p ${DNS_PORT} >/dev/null 2>&1; then
184 log "â Reverse DNS: ${ip} resolved successfully"
185 else
186 log "â Reverse DNS: ${ip} failed"
187 fi
188 done
189}
190
191# Test DNS cache functionality
192test_cache() {
193 log "Testing DNS cache functionality"
194
195 local test_domain="google.com"
196
197 # First query (should be cached)
198 local start_time1=$(date +%s%N)
199 dig +short @${DNS_SERVER} -p ${DNS_PORT} "${test_domain}" >/dev/null 2>&1
200 local end_time1=$(date +%s%N)
201 local duration1=$(( (end_time1 - start_time1) / 1000000 ))
202
203 # Immediate second query (should be faster from cache)
204 local start_time2=$(date +%s%N)
205 dig +short @${DNS_SERVER} -p ${DNS_PORT} "${test_domain}" >/dev/null 2>&1
206 local end_time2=$(date +%s%N)
207 local duration2=$(( (end_time2 - start_time2) / 1000000 ))
208
209 if [[ ${duration2} -lt ${duration1} ]]; then
210 log "â Cache: Second query faster (${duration2}ms vs ${duration1}ms) - caching working"
211 else
212 log "? Cache: No significant speed improvement (${duration2}ms vs ${duration1}ms)"
213 fi
214}
215
216# Basic functionality test
217basic_test() {
218 local failures=0
219
220 log "Starting basic DNS functionality test"
221
222 for domain in "${TEST_DOMAINS[@]:0:5}"; do
223 if ! test_domain "${domain}" "success"; then
224 failures=$((failures + 1))
225 fi
226 done
227
228 for domain in "${BLOCKED_DOMAINS[@]:0:3}"; do
229 if ! test_domain "${domain}" "blocked"; then
230 failures=$((failures + 1))
231 fi
232 done
233
234 if [[ ${failures} -eq 0 ]]; then
235 log "â BASIC TEST: All tests passed"
236 return 0
237 else
238 log "â BASIC TEST: ${failures} test(s) failed"
239 return 1
240 fi
241}
242
243# Full comprehensive test
244full_test() {
245 local failures=0
246
247 log "Starting comprehensive DNS test"
248
249 # Test regular domains
250 for domain in "${TEST_DOMAINS[@]}"; do
251 if ! test_domain "${domain}" "success"; then
252 failures=$((failures + 1))
253 fi
254 done
255
256 # Test blocked domains
257 for domain in "${BLOCKED_DOMAINS[@]}"; do
258 if ! test_domain "${domain}" "blocked"; then
259 failures=$((failures + 1))
260 fi
261 done
262
263 # Test local domains
264 for domain in "${LOCAL_DOMAINS[@]}"; do
265 if ! test_domain "${domain}" "success"; then
266 failures=$((failures + 1))
267 fi
268 done
269
270 # Additional tests
271 test_tcp || failures=$((failures + 1))
272 test_reverse_dns || failures=$((failures + 1))
273 test_cache || failures=$((failures + 1))
274 test_dnssec || failures=$((failures + 1))
275
276 if [[ ${failures} -eq 0 ]]; then
277 log "â FULL TEST: All tests passed"
278 return 0
279 else
280 log "â FULL TEST: ${failures} test(s) failed"
281 return 1
282 fi
283}
284
285# Latency test only
286latency_test() {
287 log "Starting DNS latency test"
288
289 for domain in "${TEST_DOMAINS[@]:0:3}"; do
290 test_latency "${domain}" 5
291 done
292}
293
294# Security test only
295security_test() {
296 log "Starting DNS security test"
297
298 # Test blocked domains
299 for domain in "${BLOCKED_DOMAINS[@]}"; do
300 test_domain "${domain}" "blocked"
301 done
302
303 # Test DNSSEC
304 test_dnssec
305
306 # Test NXDOMAIN handling
307 test_domain "nonexistent-domain-$(date +%s).test" "blocked"
308}
309
310# Debug test with verbose output
311debug_test() {
312 log "Starting debug DNS test"
313
314 echo "=== DNS SERVER CONFIGURATION ==="
315 echo "DNS Server: ${DNS_SERVER}:${DNS_PORT}"
316 echo "Timeout: ${TIMEOUT}s"
317 echo "Retries: ${RETRIES}"
318 echo ""
319
320 echo "=== BASIC CONNECTIVITY ==="
321 if nc -z -w 1 ${DNS_SERVER} ${DNS_PORT} 2>/dev/null; then
322 echo "â DNS port is accessible"
323 else
324 echo "â DNS port is not accessible"
325 fi
326
327 echo ""
328 echo "=== DIG COMMAND TEST ==="
329 dig +short +time=2 @${DNS_SERVER} -p ${DNS_PORT} google.com
330
331 echo ""
332 echo "=== DETAILED QUERY ==="
333 dig +nocmd +noall +answer +multiline @${DNS_SERVER} -p ${DNS_PORT} google.com
334}
335
336# Show usage
337usage() {
338 cat << EOF
339DNS Test Script
340
341Usage: $0 [test_type]
342
343Test Types:
344 basic Basic functionality test (default)
345 full Comprehensive test including latency and security
346 latency Latency measurement test
347 security Security and blocking test
348 debug Debug information with verbose output
349 help Show this help message
350
351Examples:
352 $0 basic
353 $0 full
354 $0 latency
355 $0 security
356 $0 debug
357
358Configuration:
359 DNS Server: ${DNS_SERVER}:${DNS_PORT}
360 Timeout: ${TIMEOUT}s
361 Retries: ${RETRIES}
362EOF
363}
364
365# Main execution
366main() {
367 local test_type="${1:-basic}"
368
369 log "Starting DNS test: ${test_type}"
370
371 case "${test_type}" in
372 basic)
373 basic_test
374 ;;
375 full)
376 full_test
377 ;;
378 latency)
379 latency_test
380 ;;
381 security)
382 security_test
383 ;;
384 debug)
385 debug_test
386 ;;
387 help|*)
388 usage
389 ;;
390 esac
391
392 log "DNS test completed: ${test_type}"
393}
394
395# Run main function with all arguments
396main "$@"