| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- #!/usr/bin/env bash
- # net-ops :: linux/dns-audit.sh
- # Deep DNS forensics for Linux. Use when probe.sh shows rung 4 (dig) PASS
- # but rung 5 (getent / resolvectl) FAIL.
- set -u
- # shellcheck source=../_lib/redact.sh
- source "$(dirname "$0")/../_lib/redact.sh"
- parse_redact_flag "$@"
- maybe_redact_self "$@"
- echo "=== /etc/nsswitch.conf (hosts line) ==="
- grep "^hosts:" /etc/nsswitch.conf 2>/dev/null || echo " (no hosts entry)"
- echo
- echo "=== /etc/resolv.conf ==="
- if [[ -L /etc/resolv.conf ]]; then
- echo " Type: symlink -> $(readlink /etc/resolv.conf)"
- else
- echo " Type: regular file"
- fi
- echo " Modified: $(stat -c '%y' /etc/resolv.conf 2>/dev/null || stat -f '%Sm' /etc/resolv.conf 2>/dev/null)"
- echo " --- contents ---"
- cat /etc/resolv.conf 2>/dev/null | sed 's/^/ /'
- echo
- echo "=== systemd-resolved ==="
- if systemctl is-active systemd-resolved >/dev/null 2>&1; then
- echo " Service: active"
- echo " --- resolvectl status ---"
- resolvectl status 2>/dev/null | sed 's/^/ /'
- else
- echo " Service: inactive or not installed"
- fi
- echo
- echo "=== NetworkManager DNS config ==="
- if command -v nmcli >/dev/null 2>&1; then
- echo " --- nmcli dev show (DNS lines) ---"
- nmcli dev show 2>/dev/null | grep -E 'DEVICE|IP4.DNS|IP6.DNS|DOMAIN' | sed 's/^/ /'
- echo
- echo " --- NetworkManager dns mode ---"
- awk '/\[main\]/,/\[/{if(/^dns/) print}' /etc/NetworkManager/NetworkManager.conf 2>/dev/null | sed 's/^/ /' || true
- ls -la /etc/NetworkManager/conf.d/ 2>/dev/null | sed 's/^/ /' || true
- else
- echo " nmcli not installed"
- fi
- echo
- echo "=== dnsmasq ==="
- if pgrep -x dnsmasq >/dev/null; then
- pid=$(pgrep -x dnsmasq | head -1)
- echo " Running, PID $pid"
- ps -o command -p "$pid" 2>/dev/null | sed 's/^/ /'
- else
- echo " not running"
- fi
- for d in /etc/dnsmasq.d /etc/NetworkManager/dnsmasq.d; do
- [[ -d "$d" ]] && { echo " $d contents:"; ls "$d" 2>/dev/null | sed 's/^/ /'; }
- done
- echo
- echo "=== Local DNS listeners ==="
- ss -tulnp 2>/dev/null | awk 'NR==1 || $5 ~ /:53$/' | sed 's/^/ /'
- echo
- echo "=== /etc/hosts (non-comment) ==="
- grep -vE '^\s*(#|$)' /etc/hosts 2>/dev/null | sed 's/^/ /' || echo " (no custom entries)"
- echo
- echo "=== VPN / WireGuard interfaces ==="
- ip -br link 2>/dev/null | awk '/^(wg|tun|tap|nordlynx|proton|mullvad|nextdns)/' | sed 's/^/ /' || true
- if command -v wg >/dev/null 2>&1; then
- echo " --- wg show ---"
- wg show 2>/dev/null | sed 's/^/ /' | head -30 || true
- fi
- echo
- echo "=== ATTRIBUTION HINTS ==="
- # Inspect nameservers visible across the stack for known patterns
- ns_list=$( {
- awk '/^nameserver/{print $2}' /etc/resolv.conf 2>/dev/null
- resolvectl status 2>/dev/null | awk '/Current DNS Server:|DNS Servers:/{for(i=4;i<=NF;i++)print $i}'
- nmcli -t -f IP4.DNS,IP6.DNS dev show 2>/dev/null | awk -F: '{print $2}'
- } | sort -u | grep -v '^$' )
- while read -r n; do
- [[ -z "$n" ]] && continue
- case "$n" in
- 10.2.0.*) echo " $n :: likely Proton VPN gateway" ;;
- 10.64.0.*) echo " $n :: likely Mullvad gateway" ;;
- 10.211.*|10.212.*) echo " $n :: likely Cisco AnyConnect" ;;
- 100.100.100.100) echo " $n :: Tailscale MagicDNS (expected)" ;;
- 127.0.0.53) echo " $n :: systemd-resolved stub (expected on most systems)" ;;
- 127.0.0.1|127.0.0.2) echo " $n :: local DNS proxy (dnsmasq, NextDNS, AdGuard, etc.)" ;;
- esac
- done <<< "$ns_list"
|