Sync all scripts from website downloads — 352 scripts total

Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
This commit is contained in:
2026-05-25 03:31:08 +02:00
parent dbd6bf0324
commit a1a17e81a1
332 changed files with 174509 additions and 1106 deletions
+500
View File
@@ -0,0 +1,500 @@
#!/usr/bin/env bash
#####################################################################################
#### dns-smoke-tests.sh — Verify DNS infrastructure is healthy ####
#### Checks resolution, zone transfers, SOA, DNSSEC, response time, DoT. ####
#### ####
#### Author: Phil Connor ####
#### Contact: contact@mylinux.work ####
#### License: MIT ####
#### Version: 1.0 ####
#### ####
#### Usage: ./dns-smoke-tests.sh ####
#### DNS_SERVER=192.168.1.1 DOMAIN=example.com ./dns-smoke-tests.sh ####
#### ####
#### See --help for all options. ####
#####################################################################################
set -euo pipefail
# ── Defaults ──────────────────────────────────────────────────────────
DNS_SERVER="${DNS_SERVER:-}"
DOMAIN="${DOMAIN:-example.com}"
REVERSE_IP="${REVERSE_IP:-}"
ZONE="${ZONE:-}"
ZONE_MASTER="${ZONE_MASTER:-}"
DNSSEC_DOMAIN="${DNSSEC_DOMAIN:-}"
DOT_SERVER="${DOT_SERVER:-}"
MAX_RESPONSE_MS="${MAX_RESPONSE_MS:-500}"
TEST_RECORDS="${TEST_RECORDS:-}"
OUTPUT_FORMAT="${OUTPUT_FORMAT:-text}"
VERBOSE="${VERBOSE:-false}"
COLOR="${COLOR:-auto}"
# ── State ─────────────────────────────────────────────────────────────
PASS=0; FAIL=0; SKIP=0; TOTAL=0
RESULTS=()
START_TIME=""
# ── Dig tool detection ───────────────────────────────────────────────
DIG_CMD=""
detect_dig() {
if command -v dig >/dev/null 2>&1; then
DIG_CMD="dig"
elif command -v drill >/dev/null 2>&1; then
DIG_CMD="drill"
else
err "Neither dig nor drill found. Install dnsutils or ldns."
exit 1
fi
verbose "Using ${DIG_CMD} for DNS queries"
}
# ── Colors ────────────────────────────────────────────────────────────
setup_colors() {
if [[ "$COLOR" == "never" ]]; then
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" RESET=""
return
fi
if [[ "$COLOR" == "always" ]] || [[ -t 1 ]]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
RESET='\033[0m'
else
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" RESET=""
fi
}
# ── Logging ───────────────────────────────────────────────────────────
log() { echo -e "${BLUE}[INFO]${RESET} $*"; }
warn() { echo -e "${YELLOW}[WARN]${RESET} $*" >&2; }
err() { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
verbose() { if [[ "$VERBOSE" == "true" ]]; then echo -e "${BLUE}[DEBUG]${RESET} $*"; fi; }
# ── Test Result Recording ─────────────────────────────────────────────
record_pass() {
local name="$1" detail="${2:-}"
((PASS++)) || true; ((TOTAL++)) || true
RESULTS+=("PASS|${name}|${detail}")
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then echo "ok ${TOTAL} - ${name}${detail:+ (${detail})}"
else echo -e " ${GREEN}${RESET} ${name}${detail:+ — ${detail}}"; fi
}
record_fail() {
local name="$1" detail="${2:-}"
((FAIL++)) || true; ((TOTAL++)) || true
RESULTS+=("FAIL|${name}|${detail}")
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then
echo "not ok ${TOTAL} - ${name}"
[[ -n "$detail" ]] && echo " # ${detail}"
else echo -e " ${RED}${RESET} ${name}${detail:+ — ${detail}}"; fi
}
record_skip() {
local name="$1" reason="${2:-}"
((SKIP++)) || true; ((TOTAL++)) || true
RESULTS+=("SKIP|${name}|${reason}")
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then echo "ok ${TOTAL} - ${name} # SKIP ${reason}"
else echo -e " ${YELLOW}${RESET} ${name}${reason:+ — ${reason}}"; fi
}
# ── Helpers ───────────────────────────────────────────────────────────
has_cmd() { command -v "$1" >/dev/null 2>&1; }
# Build dig command with optional @server
dig_cmd() {
if [[ -n "$DNS_SERVER" ]]; then
"$DIG_CMD" "@${DNS_SERVER}" "$@"
else
"$DIG_CMD" "$@"
fi
}
# ── Output Functions ──────────────────────────────────────────────────
section_header() {
local name="$1"
if [[ "$OUTPUT_FORMAT" == "text" ]]; then
echo ""
echo -e "${BOLD}${name}${RESET}"
fi
}
print_header() {
if [[ "$OUTPUT_FORMAT" == "text" ]]; then
echo ""
echo -e "${BOLD}DNS Smoke Tests${RESET}"
echo "Domain: ${DOMAIN}"
[[ -n "$DNS_SERVER" ]] && echo "Server: ${DNS_SERVER}" || echo "Server: (system resolver)"
echo "Time: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
fi
}
print_tap_header() {
echo "TAP version 13"
}
print_summary() {
local end_time; end_time=$(date +%s)
local duration=$(( end_time - START_TIME ))
echo ""
echo -e "${BOLD}────────────────────────────────────────${RESET}"
echo -e "${BOLD}Summary${RESET} ${DOMAIN} ${DNS_SERVER:-(system resolver)}"
echo -e " ${GREEN}${PASS} passed${RESET} ${RED}${FAIL} failed${RESET} ${YELLOW}${SKIP} skipped${RESET} (${duration}s)"
echo -e "${BOLD}────────────────────────────────────────${RESET}"
if [[ $FAIL -eq 0 ]]; then echo -e "${GREEN}${BOLD}All tests passed.${RESET}"
else echo -e "${RED}${BOLD}${FAIL} test(s) failed.${RESET}"; fi
}
print_tap_footer() {
echo "1..${TOTAL}"
echo "# pass ${PASS}"
echo "# fail ${FAIL}"
echo "# skip ${SKIP}"
}
# ══════════════════════════════════════════════════════════════════════
# TESTS
# ══════════════════════════════════════════════════════════════════════
# ── 1. Resolver Reachable ─────────────────────────────────────────────
test_resolver_reachable() {
section_header "Connectivity"
local output
output=$(dig_cmd +short +time=5 +tries=1 "${DOMAIN}" A 2>&1) || true
if [[ -n "$output" ]] && ! echo "$output" | grep -qi "timed out\|connection refused\|no servers\|SERVFAIL"; then
record_pass "Resolver reachable" "${DNS_SERVER:-(system resolver)}"
else
record_fail "Resolver reachable" "${DNS_SERVER:-(system resolver)}${output:-no response}"
fi
}
# ── 2. Forward Resolution (A) ────────────────────────────────────────
test_forward_resolution() {
section_header "Resolution"
local output
output=$(dig_cmd +short "${DOMAIN}" A 2>/dev/null) || true
if [[ -n "$output" ]]; then
local first_ip
first_ip=$(echo "$output" | head -1)
record_pass "Forward resolution (${DOMAIN} A)" "${first_ip}"
else
record_fail "Forward resolution (${DOMAIN} A)" "no A record returned"
fi
}
# ── 3. AAAA Resolution ───────────────────────────────────────────────
test_aaaa_resolution() {
local output
output=$(dig_cmd +short "${DOMAIN}" AAAA 2>/dev/null) || true
if [[ -n "$output" ]]; then
local first_ip
first_ip=$(echo "$output" | head -1)
record_pass "AAAA resolution (${DOMAIN})" "${first_ip}"
else
record_skip "AAAA resolution (${DOMAIN})" "no AAAA record"
fi
}
# ── 4. MX Resolution ─────────────────────────────────────────────────
test_mx_resolution() {
local output
output=$(dig_cmd +short "${DOMAIN}" MX 2>/dev/null) || true
if [[ -n "$output" ]]; then
local first_mx
first_mx=$(echo "$output" | head -1)
record_pass "MX resolution (${DOMAIN})" "${first_mx}"
else
record_skip "MX resolution (${DOMAIN})" "no MX record"
fi
}
# ── 5. Reverse Lookup ────────────────────────────────────────────────
test_reverse_lookup() {
if [[ -z "$REVERSE_IP" ]]; then
record_skip "Reverse lookup" "REVERSE_IP not set"
return
fi
local output
output=$(dig_cmd +short -x "${REVERSE_IP}" 2>/dev/null) || true
if [[ -n "$output" ]]; then
record_pass "Reverse lookup (${REVERSE_IP})" "${output}"
else
record_fail "Reverse lookup (${REVERSE_IP})" "no PTR record returned"
fi
}
# ── 6. Response Time ─────────────────────────────────────────────────
test_response_time() {
section_header "Performance"
local output query_time
output=$(dig_cmd "${DOMAIN}" A 2>/dev/null) || true
# dig outputs "Query time: 12 msec" or ";; Query time: 12 msec"
query_time=$(echo "$output" | grep -i "query time" | grep -oP '[0-9]+' | head -1) || true
if [[ -z "$query_time" ]]; then
# drill outputs ";; Query time: 0 msec"
query_time=$(echo "$output" | grep -i "query time" | awk '{print $4}') || true
fi
if [[ -n "$query_time" ]]; then
if [[ "$query_time" -le "$MAX_RESPONSE_MS" ]]; then
record_pass "Response time" "${query_time}ms (<= ${MAX_RESPONSE_MS}ms)"
else
record_fail "Response time" "${query_time}ms (> ${MAX_RESPONSE_MS}ms)"
fi
else
record_fail "Response time" "could not parse query time"
fi
}
# ── 7. Authoritative Answer ──────────────────────────────────────────
test_authoritative_answer() {
section_header "Authority"
local output
output=$(dig_cmd "${DOMAIN}" A 2>/dev/null) || true
if echo "$output" | grep -q "flags:.*aa"; then
record_pass "Authoritative answer (${DOMAIN})" "AA flag set"
else
record_fail "Authoritative answer (${DOMAIN})" "AA flag not set — server is not authoritative"
fi
}
# ── 8. SOA Serial ────────────────────────────────────────────────────
test_soa_serial() {
local output serial
output=$(dig_cmd +short "${DOMAIN}" SOA 2>/dev/null) || true
if [[ -z "$output" ]]; then
record_fail "SOA serial (${DOMAIN})" "no SOA record returned"
return
fi
# SOA format: ns1.example.com. admin.example.com. 2026051201 3600 900 604800 86400
serial=$(echo "$output" | awk '{print $3}') || true
if [[ -z "$serial" ]]; then
record_fail "SOA serial (${DOMAIN})" "could not parse serial"
elif [[ "$serial" == "0" ]]; then
record_fail "SOA serial (${DOMAIN})" "serial is 0"
else
record_pass "SOA serial (${DOMAIN})" "${serial}"
fi
}
# ── 9. SOA Consistency ───────────────────────────────────────────────
test_soa_consistency() {
if [[ -z "$ZONE_MASTER" ]]; then
record_skip "SOA consistency" "ZONE_MASTER not set"
return
fi
local serial_local serial_master
# Get serial from configured server
serial_local=$(dig_cmd +short "${DOMAIN}" SOA 2>/dev/null | awk '{print $3}') || true
# Get serial from master
serial_master=$("$DIG_CMD" "@${ZONE_MASTER}" +short "${DOMAIN}" SOA 2>/dev/null | awk '{print $3}') || true
if [[ -z "$serial_local" || -z "$serial_master" ]]; then
record_fail "SOA consistency" "could not retrieve serials (local=${serial_local:-?}, master=${serial_master:-?})"
return
fi
if [[ "$serial_local" == "$serial_master" ]]; then
record_pass "SOA consistency" "serial ${serial_local} matches across servers"
else
record_fail "SOA consistency" "serial mismatch — local=${serial_local}, master=${serial_master}"
fi
}
# ── 10. Zone Transfer ────────────────────────────────────────────────
test_zone_transfer() {
section_header "Zone Transfer"
if [[ -z "$ZONE" ]]; then
record_skip "Zone transfer (AXFR)" "ZONE not set"
return
fi
local output exit_code=0
output=$(dig_cmd AXFR "${ZONE}" 2>&1) || exit_code=$?
# Check if transfer returned records
local record_count
record_count=$(echo "$output" | grep -c "^${ZONE}" 2>/dev/null) || record_count=0
if [[ $record_count -gt 0 ]]; then
record_pass "Zone transfer (${ZONE})" "${record_count} records transferred"
elif echo "$output" | grep -qi "transfer failed\|refused\|REFUSED"; then
record_pass "Zone transfer (${ZONE})" "AXFR refused (expected on production)"
else
record_fail "Zone transfer (${ZONE})" "transfer failed — ${output:0:100}"
fi
}
# ── 11. DNSSEC Validation ────────────────────────────────────────────
test_dnssec_validation() {
section_header "DNSSEC"
if [[ -z "$DNSSEC_DOMAIN" ]]; then
record_skip "DNSSEC validation" "DNSSEC_DOMAIN not set"
return
fi
local output
output=$(dig_cmd +dnssec +short "${DNSSEC_DOMAIN}" A 2>/dev/null) || true
# Check for AD flag in full output
local full_output
full_output=$(dig_cmd +dnssec "${DNSSEC_DOMAIN}" A 2>/dev/null) || true
if echo "$full_output" | grep -q "flags:.*ad"; then
record_pass "DNSSEC validation (${DNSSEC_DOMAIN})" "AD flag set"
elif [[ -n "$output" ]]; then
record_fail "DNSSEC validation (${DNSSEC_DOMAIN})" "response received but AD flag not set"
else
record_fail "DNSSEC validation (${DNSSEC_DOMAIN})" "no response"
fi
}
# ── 12. DNS-over-TLS ─────────────────────────────────────────────────
test_dot() {
section_header "DNS-over-TLS"
if [[ -z "$DOT_SERVER" ]]; then
record_skip "DNS-over-TLS" "DOT_SERVER not set"
return
fi
if ! has_cmd openssl; then
record_skip "DNS-over-TLS" "openssl not installed"
return
fi
local output exit_code=0
output=$(echo "" | openssl s_client -connect "${DOT_SERVER}:853" -servername "${DOT_SERVER}" 2>&1) || exit_code=$?
if echo "$output" | grep -qi "connected\|verify return"; then
# Extract certificate info if available
local cn
cn=$(echo "$output" | grep -oP 'CN\s*=\s*\K[^,/]+' | head -1) || true
record_pass "DNS-over-TLS (${DOT_SERVER}:853)" "TLS handshake OK${cn:+ — CN=${cn}}"
else
record_fail "DNS-over-TLS (${DOT_SERVER}:853)" "TLS handshake failed"
fi
}
# ── 13. Custom Record Checks ─────────────────────────────────────────
test_custom_records() {
if [[ -z "$TEST_RECORDS" ]]; then return; fi
section_header "Custom Records"
local IFS=','
for entry in $TEST_RECORDS; do
local name type expected
name=$(echo "$entry" | cut -d: -f1)
type=$(echo "$entry" | cut -d: -f2)
expected=$(echo "$entry" | cut -d: -f3-)
if [[ -z "$name" || -z "$type" ]]; then
record_fail "Custom record" "invalid entry: ${entry}"
continue
fi
local output
output=$(dig_cmd +short "${name}" "${type}" 2>/dev/null) || true
if [[ -z "$output" ]]; then
record_fail "Custom record (${name} ${type})" "no record returned"
elif [[ -n "$expected" ]]; then
if echo "$output" | grep -q "$expected"; then
record_pass "Custom record (${name} ${type})" "${output}"
else
record_fail "Custom record (${name} ${type})" "expected '${expected}', got '${output}'"
fi
else
record_pass "Custom record (${name} ${type})" "${output}"
fi
done
}
# ── 14. Recursive Resolution ─────────────────────────────────────────
test_recursive_resolution() {
section_header "Recursion"
local output
output=$(dig_cmd +short "google.com" A 2>/dev/null) || true
if [[ -n "$output" ]]; then
local first_ip
first_ip=$(echo "$output" | head -1)
record_pass "Recursive resolution (google.com)" "${first_ip}"
else
record_fail "Recursive resolution (google.com)" "could not resolve external domain"
fi
}
# ══════════════════════════════════════════════════════════════════════
# MAIN
# ══════════════════════════════════════════════════════════════════════
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
Smoke-test DNS infrastructure. Checks resolution, zone transfers, SOA
consistency, DNSSEC, response time, and DNS-over-TLS.
Environment variables:
DNS_SERVER DNS server to query (default: system resolver)
DOMAIN Domain to test resolution (default: example.com)
REVERSE_IP IP for reverse (PTR) lookup (skip if empty)
ZONE Zone for AXFR transfer test (skip if empty)
ZONE_MASTER Second nameserver for SOA serial comparison (skip if empty)
DNSSEC_DOMAIN Domain to validate DNSSEC (skip if empty)
DOT_SERVER DNS-over-TLS server to test (skip if empty)
MAX_RESPONSE_MS Max acceptable response time in ms (default: 500)
TEST_RECORDS Comma-separated name:type:expected for custom checks
OUTPUT_FORMAT Output: text (default), tap
COLOR Color: auto (default), always, never
VERBOSE Show debug output (default: false)
Options:
--server SERVER Set DNS_SERVER
--domain DOMAIN Set DOMAIN
--format FORMAT Output: text (default), tap
--verbose Show debug output
--no-color Disable colored output
--help Show this help
Examples:
DNS_SERVER=192.168.1.1 DOMAIN=corp.local ./$(basename "$0")
DNSSEC_DOMAIN=example.com DOT_SERVER=1.1.1.1 ./$(basename "$0")
EOF
}
main() {
while [[ $# -gt 0 ]]; do
case "$1" in
--server) DNS_SERVER="$2"; shift ;;
--domain) DOMAIN="$2"; shift ;;
--format) OUTPUT_FORMAT="$2"; shift ;;
--verbose) VERBOSE=true ;;
--no-color) COLOR=never ;;
--help|-h) usage; exit 0 ;;
*) err "Unknown option: $1"; usage; exit 1 ;;
esac
shift
done
setup_colors
detect_dig
START_TIME=$(date +%s)
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then
print_tap_header
else
print_header
fi
test_resolver_reachable
test_forward_resolution
test_aaaa_resolution
test_mx_resolution
test_reverse_lookup
test_response_time
test_authoritative_answer
test_soa_serial
test_soa_consistency
test_zone_transfer
test_dnssec_validation
test_dot
test_custom_records
test_recursive_resolution
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then
print_tap_footer
else
print_summary
fi
[[ $FAIL -eq 0 ]] && exit 0 || exit 1
}
main "$@"