Skip to content

Latest commit

 

History

History
1162 lines (853 loc) · 29.1 KB

File metadata and controls

1162 lines (853 loc) · 29.1 KB

Troubleshooting Guide

Common issues and their solutions.

Table of Contents

  1. VPN Issues
  2. DNS Issues
  3. Connectivity Issues
  4. Kill Switch Issues
  5. VPN Bypass Issues
  6. Performance Issues
  7. Script & Service Issues
  8. Boot & Startup Issues
  9. Diagnostic Commands

VPN Issues

VPN Won't Connect

Symptoms:

  • awg0 interface exists but no handshake
  • No traffic through tunnel
  • awg show awg0 (or amneziawg show awg0) shows no recent handshake

Diagnosis:

# Check interface exists
ip link show awg0

# Check WireGuard status
awg show awg0

# Look for handshake time
# "latest handshake: X seconds ago" = working
# No handshake = problem

Solutions:

  1. Endpoint route missing:

    # Check if endpoint is routable
    ip route get VPN_SERVER_IP
    
    # Should show: via WAN_GATEWAY dev eth0
    # If shows: dev awg0 = WRONG (infinite loop)
    
    # Fix: Add endpoint route
    ip route add VPN_SERVER_IP via WAN_GATEWAY
  2. Wrong AWG parameters:

    # AWG params MUST match server exactly
    # Check your provider's documentation
    # Common: Jc, Jmin, Jmax, S1, S2, H1-H4
  3. Firewall blocking UDP:

    # Check if WAN allows outbound UDP 51820
    nft list ruleset | grep 51820
    
    # Most ISPs don't block outbound UDP
    # If blocked, try port 443 or 80 on VPN server
  4. Clock skew:

    # WireGuard handshake uses timestamps
    # Check system time
    date
    
    # Sync time
    ntpd -q -p pool.ntp.org

VPN Connects But No Internet

Symptoms:

  • Handshake successful
  • ping 1.1.1.1 fails through awg0
  • curl ipinfo.io/ip times out (or provider test like am.i.mullvad.net)

Diagnosis:

# Check routing
ip route

# Should see:
# default dev awg0  ← All traffic via VPN
# VPN_IP via GATEWAY dev eth0  ← Endpoint reachable

Solutions:

  1. Missing default route:

    ip route del default 2>/dev/null
    ip route add default dev awg0
  2. NAT not enabled:

    # Check masquerade on VPN zone
    uci show firewall | grep vpn
    
    # Should have: masq='1'
    uci set firewall.vpn.masq='1'
    uci commit firewall
    /etc/init.d/firewall restart
  3. AllowedIPs too restrictive:

    # In awg0.conf, Peer section should have:
    AllowedIPs = 0.0.0.0/0, ::/0
    # Not just the server's IP

VPN Keeps Disconnecting

Symptoms:

  • Works initially, then dies
  • Watchdog keeps restarting tunnel

Solutions:

  1. PersistentKeepalive missing:

    # Add to [Peer] section
    PersistentKeepalive = 25
  2. ISP throttling:

    • Try different VPN server
    • Try different port (if provider supports)
    • Increase Jc value for more obfuscation
  3. Memory issues:

    free -m
    # If low on memory, reduce AdGuard cache size

VPN Keeps Restarting During an Outage (ISP/CGNAT Upstream)

Symptoms:

  • No internet, but the WAN gateway still pings
  • Watchdog log loops: handshake stale → full restart → Tunnel restart FAILED
  • Rebooting the router does NOT fix it; service returns only when the ISP recovers
  • Common on CGNAT WANs (RFC 6598, 100.64.0.0/10), where the gateway is the ISP's edge

Cause: The ISP's upstream path is down but the (CGNAT) gateway stays pingable. A gateway-only check can't tell this apart from a VPN fault, and the tunnel-path connectivity check only tests the VPN — so the watchdog thrashes the tunnel pointlessly.

Diagnosis:

WAN_IP=$(ip -4 addr show dev eth0 | awk '/inet / {sub(/\/.*/,"",$2); print $2; exit}')
GW=$(ip route show dev eth0 | awk '/default/{print $3; exit}')
ping -c2 "$GW"                       # gateway — usually UP
ping -c2 -I "$WAN_IP" 1.1.1.1        # raw WAN to internet — DOWN during this outage

If the gateway pings but raw-WAN 1.1.1.1 fails, it's an ISP-side outage — the VPN can't fix it.

Solution: The bundled awg-watchdog.sh includes Gate 1b (check_raw_wan_public): it probes public IPs over the raw WAN path (bypass table, forced by a WAN-source policy rule) and, when the gateway is up but raw WAN can't reach the internet, logs ISP upstream/CGNAT outage and skips the restart instead of thrashing. It auto-recovers the moment the ISP path returns. Beyond (optionally) asking the ISP to reset the connection, no action is needed. If these recur, ask the ISP for a public IP (off CGNAT).


VPN Down After Failover, or "0 B received" on One Server (Per-Server Keys)

Symptoms:

  • A VPN device is WiFi-connected and DNS resolves, but nothing loads
  • awg show awg0 shows transfer: 0 B received and NO latest handshake
  • WAN and raw WAN both reach the internet (so it's NOT the ISP — contrast the section above)
  • Often appears after a server failover, or after the provider retires/rotates a server

Cause: Each WireGuard server has its OWN public key — with Mullvad this holds even within a city. If servers.conf uses - (reuse the base key) for a failover server, the watchdog switches the endpoint but keeps the wrong key, so the handshake never completes. A decommissioned server IP does the same (the endpoint is dead). Either way the tunnel sits with 0 bytes received while everything upstream looks fine.

Diagnosis:

awg show awg0 | grep -E "endpoint|latest handshake|transfer"   # 0 B received, no handshake
grep -E "^(Endpoint|PublicKey)=" /etc/amneziawg/awg0.conf      # right key for THIS endpoint?
# Is the endpoint still a live server? (empty result = decommissioned — pick another)
curl -s https://api.mullvad.net/www/relays/all/ | grep -o '"<endpoint-ip>"'

Solution: Give every server in servers.conf its OWN public key in column 4 (never - for a failover server); the bundled switch_server rewrites both Endpoint= and PublicKey= per server. Refresh the list against your provider's live server list and drop decommissioned IPs. Save servers.conf with LF (not CRLF) line endings — a trailing CR corrupts the last column (the key). Manual recovery: set Endpoint/PublicKey to any active server, then ip link del awg0; ACTION=ifup INTERFACE=wan /etc/hotplug.d/iface/99-awg.


DNS Issues

DNS Not Resolving

Symptoms:

  • nslookup google.com fails
  • Websites don't load by name
  • IPs work (ping 1.1.1.1 succeeds)

Diagnosis:

# Check what DNS client is using
cat /etc/resolv.conf

# Test AdGuard directly
nslookup google.com 192.168.1.5

# Test upstream (use your VPN provider's DNS)
# Mullvad: 100.64.0.4 | IVPN: 10.0.254.1 | Proton: 10.2.0.1
nslookup google.com VPN_PROVIDER_DNS_IP

Solutions:

  1. AdGuard not running:

    # Check service status
    AdGuardHome -s status
    
    # Restart if needed
    AdGuardHome -s restart
  2. Wrong DNS pushed via DHCP:

    # Check DHCP options
    uci show dhcp | grep dhcp_option
    
    # Fix: Push AdGuard IP
    uci delete dhcp.lan.dhcp_option
    uci add_list dhcp.lan.dhcp_option='6,192.168.1.5'
    uci commit dhcp
    /etc/init.d/dnsmasq restart
    
    # Clients need to renew DHCP lease
  3. AdGuard upstream unreachable:

    # Test DoH upstream (use your provider's DoH URL)
    # Mullvad: adblock.dns.mullvad.net | IVPN: dns.ivpn.net | Proton: dns.protonvpn.net
    curl -v 'https://YOUR_PROVIDER_DOH_HOST/dns-query?dns=AAABAAABAAAAAAAA'
    
    # If fails, VPN might be down
    # Check VPN first

AdGuard Hung Silently (No Logs, All DNS Broken)

Symptoms:

  • VPN tunnel is healthy (handshake fresh, transfer counters moving)
  • Every device on the network loses internet at the same moment
  • AdGuard journal stops emitting entries entirely
  • ISP confirms the WAN side is fine
  • Only a full reboot of the AdGuard host restores DNS

Why it happens: The pattern observed in production: AdGuard's local PTR lookups time out against the router's dnsmasq, dnsproxy goroutines pile up waiting on multi-second i/o timeouts, the service drifts into an unresponsive state with no error logged, and DNS resolution hangs for every client. Because AdGuard is the only resolver clients reach (DHCP option 6), the entire network appears offline even though packets still flow.

Diagnosis:

# Did AdGuard stop logging entirely while the host stayed up?
journalctl -u AdGuardHome --since '1 hour ago' | tail
# A multi-hour gap with no entries is the smoking gun.

# Is the process still around?
ps -ef | grep -i AdGuardHome    # bare metal
docker ps | grep adguard         # docker
pct list | grep 101              # lxc / proxmox

# Can you resolve through AdGuard at all?
dig @192.168.1.5 +tries=1 +time=5 cloudflare.com

Solutions:

  1. Immediate fix: restart the AdGuard deployment.

    # Bare metal (systemd)
    sudo systemctl restart AdGuardHome
    
    # Docker
    docker restart adguardhome
    
    # LXC (Proxmox)
    sudo pct restart 101
  2. Prevent recurrence: install the DNS health watchdog (adguard/adguard-watchdog.sh + adguard/adguard-watchdog.service). It probes AdGuard every 60 seconds via dig and restarts the deployment after 3 consecutive failures — typically recovering within ~3 minutes instead of "whenever a human notices."

  3. Add persistent journaling (if not already enabled) so the next incident leaves evidence:

    sudo mkdir -p /var/log/journal
    sudo sed -i 's/^#*Storage=.*/Storage=persistent/' /etc/systemd/journald.conf
    sudo systemctl restart systemd-journald
  4. Consider a monthly preventive AdGuard refresh (scripts/monthly-adguard-refresh.cron) — it restarts only AdGuard on the first Sunday each month (long uptimes of 60+ days correlate with this hang). Do NOT use an unattended full host reboot for this on a CGNAT/DS-Lite WAN: dropping the WAN can hang the carrier session for hours (see AdGuard Keeps Restarting During an Outage below, and pitfall #24).

AdGuard Keeps Restarting During an Outage (ISP/CGNAT Upstream)

Symptoms:

  • No internet, and AdGuard is restarting in a loop with no recoveries
  • adguard-watchdog.log shows repeated Restarting with DNS never recovering
  • Common on CGNAT WANs (RFC 6598, 100.64.0.0/10), where the carrier session stalls on reconnect

Cause: During a total upstream/ISP outage, AdGuard's encrypted-DNS upstream is unreachable, so every DNS probe fails — but the failure is upstream, not AdGuard. A watchdog without an upstream check reads this as an AdGuard hang and hard-restarts the container every few minutes, pointlessly; each restart also drops DNS and wipes the cache.

Diagnosis:

# From the AdGuard host — is the public internet reachable at all?
ping -n -c2 1.1.1.1        # all packets lost during this outage = upstream down, not AdGuard
tail /var/log/adguard-watchdog.log

If the host can't reach 1.1.1.1, it's an upstream outage — restarting AdGuard can't fix it.

Solution: The bundled adguard/adguard-watchdog.sh includes an upstream-reachability gate (check_upstream): before restarting it ICMP-probes UPSTREAM_PROBES over the host's default route and, when nothing is reachable, logs the outage and skips the restart (the log line reads upstream internet unreachable ... Skipping restart) instead of thrashing. It auto-recovers when the upstream returns. If these recur on CGNAT, ask the ISP to fix the reconnection (or request a public IP). See pitfall #23.

Ads Still Showing

Symptoms:

  • Some ads getting through
  • AdGuard dashboard shows queries but no blocks

Solutions:

  1. Add more blocklists:

    • AdGuard UI → Filters → DNS blocklists
    • Add: EasyList, EasyPrivacy, StevenBlack hosts
  2. Device using hardcoded DNS:

    # Some devices ignore DHCP DNS (Chromecast, etc.)
    # Block DNS to external servers
    
    # In firewall, add rule:
    uci add firewall rule
    uci set firewall.@rule[-1].name='Block-External-DNS'
    uci set firewall.@rule[-1].src='lan'
    uci set firewall.@rule[-1].dest='vpn'
    uci set firewall.@rule[-1].dest_port='53'
    uci set firewall.@rule[-1].proto='tcp udp'
    uci set firewall.@rule[-1].target='REJECT'
    uci commit firewall
    /etc/init.d/firewall restart
  3. Browser DNS-over-HTTPS:

    • Browsers like Firefox have built-in DoH
    • Disable in browser settings
    • Or use AdGuard's DNS rewrites to block DoH endpoints

DNS Leaking

Symptoms:

  • DNS leak test shows ISP DNS
  • ipleak.net shows wrong DNS servers

Solutions:

  1. Router using ISP DNS:

    # Check router's DNS
    uci show network | grep dns
    
    # Fix: Set to VPN provider DNS
    # Mullvad: 100.64.0.4 | IVPN: 10.0.254.1 | Proton: 10.2.0.1
    uci set network.lan.dns='VPN_PROVIDER_DNS_IP'
    uci commit network
    /etc/init.d/network restart
  2. IPv6 DNS leak:

    # Disable IPv6 completely
    uci set network.wan.ipv6='0'
    uci set network.lan.ipv6='0'
    echo 'net.ipv6.conf.all.disable_ipv6=1' >> /etc/sysctl.conf
    sysctl -p

Connectivity Issues

No Internet at All

Diagnosis flowchart:

Can ping router (192.168.1.1)?
├── No → Check physical connection, DHCP
└── Yes
    └── Can ping VPN internal IP?
        ├── No → VPN tunnel down
        └── Yes
            └── Can ping 1.1.1.1?
                ├── No → Routing issue
                └── Yes
                    └── Can resolve DNS?
                        ├── No → DNS issue
                        └── Yes → Should work!

LAN Devices Can't Reach Each Other

Symptoms:

  • Can't ping other LAN devices
  • Can't access LAN services (NAS, printer)

Solutions:

  1. Bridge misconfiguration:

    # Check bridge
    brctl show
    
    # All LAN ports should be in br-lan
  2. Firewall blocking LAN:

    # LAN zone should allow all
    uci show firewall | grep -A4 "zone\[0\]"
    # input=ACCEPT, forward=ACCEPT

Can't Access Router Web UI

Symptoms:

  • SSH works
  • HTTP/HTTPS doesn't load

Solutions:

  1. Check service running:

    netstat -tlnp | grep uhttpd
  2. HTTPS redirect but no certificate:

    # Install SSL
    opkg install luci-ssl
    
    # Or disable redirect
    uci set uhttpd.main.redirect_https='0'
    uci commit uhttpd
    /etc/init.d/uhttpd restart
  3. Wrong port:

    # Check listen port
    uci show uhttpd | grep listen
    
    # Default: 80 (HTTP), 443 (HTTPS)
    # If changed, use correct port in URL

Kill Switch Issues

Kill Switch Not Working

Symptoms:

  • Internet works when VPN is down
  • Real IP exposed when VPN fails

Diagnosis:

# Bring VPN down
ip link set awg0 down

# Try to reach internet
curl ifconfig.me
# Should fail/timeout, NOT show your real IP

# If it shows your IP, kill switch is broken

Solutions:

  1. LAN→WAN forwarding exists:

    # Check for unwanted forwarding
    uci show firewall | grep forwarding
    
    # Should only have lan→vpn
    # Remove any lan→wan
    uci delete firewall.@forwarding[X]  # Replace X with index
    uci commit firewall
    /etc/init.d/firewall restart
  2. Default route pointing to WAN:

    # Check routes
    ip route
    
    # If you see: default via WAN_GATEWAY dev eth0
    # That's wrong when VPN should be default
    
    # Fix routing in startup scripts
  3. Masquerade on WAN zone:

    # WAN zone should NOT have masq if you don't want fallback
    uci show firewall | grep wan
    
    # Actually, masq on WAN is fine - the forwarding rules prevent it
    # The key is: NO lan→wan forwarding rule

Can't Access Anything When VPN Down (Even LAN)

Symptoms:

  • Kill switch too aggressive
  • Can't even SSH to router when VPN fails

This is actually WRONG behavior. LAN access should always work.

Solutions:

  1. LAN zone input not ACCEPT:

    uci show firewall | grep -A4 zone.*lan
    
    # Must have: input='ACCEPT'
    uci set firewall.@zone[0].input='ACCEPT'
    uci commit firewall
    /etc/init.d/firewall restart
  2. Default policy too strict:

    # Default input should be REJECT (not DROP)
    # DROP silently fails, REJECT sends response
    uci set firewall.@defaults[0].input='REJECT'

VPN Bypass Issues

Bypass Device Still Going Through VPN

Symptoms:

  • Added device to bypass list but still shows VPN IP
  • curl https://am.i.mullvad.net/connected returns "You are connected"

Diagnosis:

# Check policy rules exist
ip rule show | grep 100
# Should list your bypass IPs

# Check table 100 has WAN route
ip route show table 100
# Should show: default via <WAN_GW> dev eth0

# Check firewall rule exists
uci show firewall | grep -A5 'Bypass'

Solutions:

  1. Policy rule missing:

    # Add rule
    ip rule add from 192.168.1.X lookup 100 priority 100
    
    # Make persistent in /etc/rc.local
  2. Table 100 empty or wrong:

    # Check if hotplug created table 100
    ip route show table 100
    
    # If empty, VPN tunnel may not be fully up
    # Restart VPN to recreate table 100
    ACTION=ifup INTERFACE=wan /etc/hotplug.d/iface/99-awg
  3. Firewall rule missing:

    # Check for lan→wan ACCEPT for this IP
    uci show firewall | grep 'src_ip.*192.168.1.X'
    
    # Add if missing
    uci add firewall rule
    uci set firewall.@rule[-1].name='Bypass-DeviceName'
    uci set firewall.@rule[-1].src='lan'
    uci set firewall.@rule[-1].src_ip='192.168.1.X'
    uci set firewall.@rule[-1].dest='wan'
    uci set firewall.@rule[-1].target='ACCEPT'
    uci commit firewall
    /etc/init.d/firewall restart
  4. Wrong priority order:

    ip rule show
    
    # Rules with lower priority number checked first
    # Bypass rules (priority 100) must come before main (32766)

Bypass Device Has No Internet

Symptoms:

  • Device was working, added to bypass, now no internet
  • Can't reach anything from bypass device

Diagnosis:

# From bypass device (or via SSH proxying)
ping -c 3 1.1.1.1          # Test raw IP connectivity
ping -c 3 google.com        # Test DNS

# From router
traceroute -n 1.1.1.1 -s 192.168.1.X  # Trace from bypass IP

Solutions:

  1. WAN gateway changed (DHCP):

    # Check current WAN gateway
    ip route show dev eth0 | grep default
    
    # Check table 100 gateway matches
    ip route show table 100
    
    # If different, recreate table 100
    ip route replace default via <NEW_GW> dev eth0 table 100
  2. Firewall blocking (no rule):

    # Must have BOTH policy rule AND firewall rule
    # Check firewall
    iptables -L FORWARD -n -v | grep 192.168.1.X
  3. DNS not working for bypass device:

    # If bypass device uses AdGuard for DNS, AdGuard must also bypass
    # OR bypass device uses external DNS directly
    
    # Check AdGuard is in bypass list
    ip rule show | grep 192.168.1.5
    
    # If not, add it
    ip rule add from 192.168.1.5 lookup 100 priority 100

Table 100 Not Created

Symptoms:

  • ip route show table 100 returns nothing
  • Bypass not working even though rules exist

Diagnosis:

# Check hotplug script exists and is executable
ls -la /etc/hotplug.d/iface/99-awg

# Check hotplug ran
logread | grep awg-hotplug

# Check VPN is up
ip link show awg0

Solutions:

  1. VPN not started:

    # Table 100 is created when VPN starts
    # Start VPN manually
    ACTION=ifup INTERFACE=wan /etc/hotplug.d/iface/99-awg
  2. Hotplug script not executable:

    chmod +x /etc/hotplug.d/iface/99-awg
  3. WAN gateway detection failed:

    # Check gateway
    ip route show dev eth0 | grep default
    uci get network.wan.gateway
    
    # If empty, hotplug can't create table 100
    # Set static gateway or fix DHCP

Bypass Device Loses Internet When VPN Restarts

Symptoms:

  • Bypass works until VPN reconnects
  • After VPN restart, bypass stops working

Solutions:

  1. Table 100 recreated without WAN route:

    # Check table 100 after VPN restart
    ip route show table 100
    
    # If empty or wrong, hotplug may not be updating correctly
    # Check hotplug script has dynamic gateway detection
  2. Policy rules not persistent:

    # Rules in rc.local only run at boot
    # VPN restart doesn't re-run rc.local
    
    # Check rc.local uses "add" not "replace"
    # "add" fails silently if rule exists (safe)
    # This is correct behavior - rules persist across VPN restarts
  3. Watchdog using old gateway:

    # Check watchdog configuration
    grep -i gateway /etc/awg-watchdog.sh
    
    # If hardcoded, update to dynamic detection

DNS Not Working for Bypass Devices

Symptoms:

  • Bypass device can ping IPs but not domains
  • DNS queries timing out

Diagnosis:

# From bypass device
nslookup google.com 192.168.1.5    # Test AdGuard
nslookup google.com 1.1.1.1         # Test external DNS

Solutions:

  1. AdGuard not in bypass list:

    # If bypass device queries AdGuard, and AdGuard routes via VPN,
    # AdGuard's upstream queries go via VPN.
    # If VPN is slow/down, DNS fails for bypass devices.
    
    # FIX: Add AdGuard to bypass
    ip rule add from 192.168.1.5 lookup 100 priority 100
    
    # Add to /etc/rc.local for persistence
  2. AdGuard upstream unreachable:

    # If AdGuard uses DoH to VPN provider (e.g., Mullvad)
    # and AdGuard is in bypass, HTTPS to Mullvad still works
    # (it's encrypted, doesn't need VPN tunnel)
    
    # Verify AdGuard bypass is working
    curl -s https://am.i.mullvad.net/connected
    # From AdGuard container - should show "not connected"
  3. Use external DNS for bypass devices:

    # Alternative: Configure bypass devices to use external DNS directly
    # e.g., 1.1.1.1, 8.8.8.8, or VPN provider's DNS
    
    # This bypasses AdGuard entirely for bypass devices

Performance Issues

Slow Speeds

Expected overhead:

  • VPN: 5-15% reduction from encryption
  • AmneziaWG: Additional 5% from obfuscation
  • Geographic distance: +20-100ms latency

Diagnosis:

# Test without VPN (temporarily)
ip link set awg0 down
speedtest-cli

# Test with VPN
ip link set awg0 up
speedtest-cli

# Compare results

Solutions:

  1. Choose closer VPN server:

    • Use server in your region
    • Less distance = less latency
  2. Reduce AWG overhead:

    # Lower Jc (fewer junk packets)
    Jc = 2
    
    # Smaller junk size
    Jmin = 20
    Jmax = 40
  3. MTU optimization:

    # Find optimal MTU
    ping -c 5 -M do -s 1400 1.1.1.1
    
    # Reduce if fragmentation
    ip link set awg0 mtu 1380
  4. Hardware crypto:

    # Check if available
    grep -m1 'aes\|neon' /proc/cpuinfo
    
    # Modern ARM/x86 has hardware acceleration

High Latency

Normal latency ranges:

  • Same country: 20-50ms
  • Same continent: 50-150ms
  • Intercontinental: 150-300ms

Solutions:

  1. DNS latency:

    # Test DNS response time
    time nslookup google.com
    
    # If slow, check AdGuard upstream
    # Use closer DNS server
  2. Bufferbloat:

    # Install SQM (Smart Queue Management)
    opkg install luci-app-sqm
    
    # Configure for your connection speed

Script & Service Issues

Watchdog Crash-Loops on Boot

Symptoms:

  • logread | grep awg shows: awg-watchdog crash loop N crashes
  • VPN tunnel never comes up after boot
  • procd gives up restarting the watchdog

Common causes:

  1. Wrong VPN_IP:

    # Check what the scripts think the IP should be
    grep 'VPN_IP=' /etc/awg-watchdog.sh /etc/hotplug.d/iface/99-awg
    
    # Check what the actual tunnel IP is (if tunnel is up)
    ip addr show awg0 | grep inet
    
    # They MUST match. If not, update the scripts:
    # VPN_IP must match the Address from your VPN provider's config
  2. Script corruption — shebang:

    # Check for corrupted shebang (backslash-bang)
    head -1 /etc/awg-watchdog.sh /etc/hotplug.d/iface/99-awg
    # Should show: #!/bin/sh
    # NOT: #\!/bin/sh
    
    # Fix:
    sed -i '1s|^#\\!|#!|' /etc/awg-watchdog.sh /etc/hotplug.d/iface/99-awg
  3. Script corruption — conditionals:

    # Check for escaped bangs in conditionals
    grep '\\!' /etc/awg-watchdog.sh /etc/hotplug.d/iface/99-awg
    # Should return NOTHING
    
    # Fix:
    sed -i 's/\\!/!/g' /etc/awg-watchdog.sh /etc/hotplug.d/iface/99-awg

How corruption happens: Some text editors (especially when editing over SSH or copying between systems) escape ! characters. The shell interprets \! literally, breaking conditionals like if ! command and shebangs like #!/bin/sh.

Changes to Watchdog Script Not Taking Effect

Symptom: You fixed the script, but the same error keeps appearing in logs.

Root cause: procd runs the watchdog as a daemon. The running process uses the old script loaded into memory. Editing the file on disk does NOT affect the running daemon.

Fix:

# ALWAYS restart the service after editing the script
/etc/init.d/awg-watchdog restart

# Verify the new process is running
ps | grep awg-watchdog | grep -v grep

This applies to any procd-managed service on OpenWrt, not just the watchdog.

AmneziaWG Command Not Found

Symptom: amneziawg: not found or awg: not found

Cause: The command name depends on how AmneziaWG was installed:

Source Command
OpenWrt packages (awg-openwrt) awg
Built from source amneziawg

Fix: Check which one you have:

which awg amneziawg 2>/dev/null

The watchdog and hotplug scripts auto-detect the available command. If you're running commands manually, use whichever is installed.


Boot & Startup Issues

AdGuard DNS Fails After Boot (VM/Container Deployments)

Symptoms:

  • AdGuard container is running but eth0 has no IP
  • DNS resolution fails for all devices
  • Network appears down despite VPN tunnel being up

Root cause: Boot timing race condition. If AdGuard runs in a separate VM or container and uses DHCP, it may request an IP before the router's DHCP server (dnsmasq) is ready.

Diagnosis:

# Check if AdGuard's interface has an IP
# (run inside the AdGuard VM/container)
ip addr show eth0 | grep 'inet '

# If no IP shown, the race condition hit

Solutions:

  1. Use static IP instead of DHCP (recommended):

    In the AdGuard VM/container, configure a static IP via systemd-networkd:

    File: /etc/systemd/network/eth0.network

    [Match]
    Name=eth0
    
    [Network]
    Address=192.168.1.5/24
    Gateway=192.168.1.1
    DNS=127.0.0.1

    Then restart: systemctl restart systemd-networkd

    This eliminates the DHCP dependency entirely.

  2. Add startup delay (if DHCP is required):

    For Proxmox containers:

    pct set <CTID> -startup order=2,up=30

    This waits 30 seconds after starting the container, giving the router time to boot its DHCP server.

  3. Manual recovery:

    # If it already happened, restart networking
    systemctl restart systemd-networkd
    # Or bring interface up manually
    ip link set eth0 up

Smart TV / Streaming Broken Despite VPN Working

Symptoms:

  • YouTube, Netflix, or other streaming apps fail on Smart TVs
  • VPN is connected and working for other devices
  • Pinging IPs works, but some apps break

Root cause: AdGuard is returning IPv6 (AAAA) DNS records, but the VPN tunnel is IPv4-only. Devices try to connect over IPv6, which has no VPN route.

Fix: Disable AAAA records in AdGuard Home:

In /opt/AdGuardHome/AdGuardHome.yaml:

dns:
  aaaa_disabled: true

Restart AdGuard Home after the change.


Diagnostic Commands

System Status

# System overview
uptime
free -m
df -h

# Network interfaces
ip -br addr
ip -br link

# Routing table
ip route

# Active connections
netstat -tn

VPN Status

# WireGuard status
awg show awg0

# Check handshake time
awg show awg0 | grep 'latest handshake'

# Traffic statistics
awg show awg0 | grep 'transfer'

# Interface details
ip addr show awg0

Firewall Status

# UCI config
uci show firewall

# Active nftables rules
nft list ruleset

# Connection tracking
cat /proc/net/nf_conntrack | wc -l

DNS Status

# Test resolution
nslookup google.com
dig google.com @192.168.1.5

# AdGuard status
AdGuardHome -s status

# AdGuard logs
tail -f /opt/AdGuardHome/data/querylog.json

Logs

# System log
logread

# Kernel messages
dmesg | tail -50

# Watchdog log
tail -f /var/log/awg-watchdog.log

# Firewall log (if enabled)
logread | grep firewall

Network Testing

# Ping test
ping -c 5 1.1.1.1

# Ping through VPN interface
ping -c 5 -I awg0 1.1.1.1

# Check external IP (should show VPN exit IP, not ISP IP)
curl ifconfig.me
curl ipinfo.io/ip

# Provider-specific VPN check (Mullvad only)
# curl https://am.i.mullvad.net/connected

# DNS leak test
curl https://bash.ws/dnsleak/test/

Getting Help

If you're still stuck:

  1. Collect diagnostic output:

    ip route
    awg show awg0
    uci show firewall
    logread | tail -100
  2. Check logs for errors

  3. Search issues on GitHub

  4. Open new issue with diagnostics