Files
infrastructure/docs/17-DNS-ADGUARD-FAILOVER.md
Kaloyan Danchev 4b766145b4 Add AdGuard DNS setup with automatic failover documentation
- docs/16-ADGUARD-VLAN-PLAN.md: Implementation plan for AdGuard on VLANs
- docs/17-DNS-ADGUARD-FAILOVER.md: Complete DNS architecture with:
  - Dual AdGuard setup (MikroTik primary, Unraid secondary)
  - Automatic failover via Netwatch monitoring
  - NAT redirect rules for all VLANs
  - Sync configuration between instances
- docs/wip/CONSOLE-PORT-ETHER5.md: WIP plan for dedicated console port

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 17:22:18 +02:00

13 KiB

DNS Architecture with AdGuard Failover

Created: 2026-01-31 Status: Implemented Backup: adguard-failover-complete-2026-01-31.backup


Overview

Dual AdGuard DNS setup with automatic failover. All DNS queries are filtered through AdGuard for ad-blocking, and if the primary (MikroTik) fails, traffic automatically switches to secondary (Unraid).


Architecture

                            ┌─────────────────────────────────────┐
                            │           INTERNET                   │
                            │                                      │
                            │   External clients (DoT/DoH)         │
                            │   dns.xtrm-lab.org:853 (DoT)        │
                            │   dns.xtrm-lab.org:8443 (DoH)       │
                            └──────────────┬──────────────────────┘
                                           │
                                           ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│                        MikroTik hAP ax³ (192.168.10.1)                       │
│                                                                              │
│  ┌────────────────────────────────────────────────────────────────────────┐  │
│  │                    AdGuard Home (PRIMARY)                              │  │
│  │                    Container: 172.17.0.2                               │  │
│  │                    Web UI: http://192.168.10.1:3000                    │  │
│  │                                                                        │  │
│  │    ┌─────────────┐     ┌─────────────┐     ┌─────────────┐            │  │
│  │    │  Filters    │     │  Blocklists │     │   Clients   │            │  │
│  │    │  (synced)   │     │  143K rules │     │  (synced)   │            │  │
│  │    └─────────────┘     └─────────────┘     └─────────────┘            │  │
│  └────────────────────────────────────────────────────────────────────────┘  │
│                                    │                                         │
│                    Netwatch monitors every 10s                               │
│                                    │                                         │
│                         ┌─────────┴─────────┐                               │
│                         │                   │                               │
│                    Container UP        Container DOWN                        │
│                         │                   │                               │
│                         ▼                   ▼                               │
│                  NAT → 172.17.0.2    NAT → 192.168.10.10                    │
│                  (MikroTik)          (Unraid Failover)                      │
└──────────────────────────────────────────────────────────────────────────────┘
        ▲                            ▲                            ▲
        │                            │                            │
   NAT Redirect                 NAT Redirect                 NAT Redirect
        │                            │                            │
┌───────┴───────┐          ┌────────┴────────┐          ┌────────┴────────┐
│   VLAN 10     │          │    VLAN 20/25   │          │   VLAN 30/40    │
│  Management   │          │  Trusted/Kids   │          │   IoT/CatchAll  │
│ 192.168.10.x  │          │  192.168.20.x   │          │  192.168.30.x   │
│               │          │  192.168.25.x   │          │  192.168.1.x    │
└───────────────┘          └─────────────────┘          └─────────────────┘

AdGuard Instances

Instance Role IP Port Web UI
MikroTik Primary 172.17.0.2 53 http://192.168.10.1:3000
Unraid Secondary/Failover 192.168.10.10 3000 http://192.168.10.10:3000

Credentials (Same for Both)

Username Password
jazzymc 7RqWElENNbZnPW

DNS Redirect Rules

All DNS queries (port 53) from any VLAN are intercepted and redirected:

VLAN Subnet Redirected To
10 192.168.10.0/24 172.17.0.2:53
20 192.168.20.0/24 172.17.0.2:53
25 192.168.25.0/24 172.17.0.2:53
30 192.168.30.0/24 172.17.0.2:53
40 192.168.1.0/24 172.17.0.2:53

Note: Clients don't need any DNS configuration - even if they use 8.8.8.8, traffic is intercepted by NAT.

NAT Rules on MikroTik

# Exception rules (prevent loops) - MUST BE FIRST
/ip firewall nat
add chain=dstnat action=accept protocol=udp src-address=172.17.0.0/24 dst-port=53 comment="[DNS] Allow MikroTik AdGuard outbound"
add chain=dstnat action=accept protocol=udp src-address=192.168.10.10 dst-port=53 comment="[DNS] Allow Unraid AdGuard outbound"

# VLAN redirect rules
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.10.0/24 dst-port=53 comment="[DNS] VLAN10 Mgmt redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.20.0/24 dst-port=53 comment="[DNS] VLAN20 Trusted redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.25.0/24 dst-port=53 comment="[DNS] VLAN25 Kids redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.30.0/24 dst-port=53 comment="[DNS] VLAN30 IoT redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.1.0/24 dst-port=53 comment="[DNS] VLAN40 CatchAll redirect"

# Masquerade for return traffic
add chain=srcnat action=masquerade protocol=udp src-address=192.168.10.0/24 dst-address=172.17.0.2 dst-port=53 comment="[DNS] VLAN10 masquerade"
# ... (similar for other VLANs)

Automatic Failover

How It Works

  1. Netwatch monitors 172.17.0.2 (container IP) every 10 seconds
  2. If ping fails for 3 seconds → status changes to "down"
  3. dns-failover-down script runs → NAT rules switch to Unraid
  4. When ping succeeds again → status changes to "up"
  5. dns-failover-up script runs → NAT rules switch back to MikroTik

Failover Timeline

Event Detection Time Total Switchover
Container stops ~10-13 seconds ~13-16 seconds
Container recovers ~10-13 seconds ~13-16 seconds

Failover Scripts

# dns-failover-down (runs when container is unreachable)
/system script add name=dns-failover-down dont-require-permissions=yes source={
    :log warning "DNS Failover: Switching to Unraid"
    /ip firewall nat set [find where comment~"VLAN" and comment~"redirect"] to-addresses=192.168.10.10 to-ports=3000
}

# dns-failover-up (runs when container is back)
/system script add name=dns-failover-up dont-require-permissions=yes source={
    :log info "DNS Failover: Switching back to MikroTik"
    /ip firewall nat set [find where comment~"VLAN" and comment~"redirect"] to-addresses=172.17.0.2 to-ports=53
}

Netwatch Configuration

/tool netwatch add host=172.17.0.2 interval=10s timeout=3s \
    up-script=dns-failover-up \
    down-script=dns-failover-down \
    comment="AdGuard failover monitor"

Sync Configuration

Settings are synced from Unraid (source of truth) to MikroTik every 30 minutes.

What Syncs

Feature Synced
Filter lists (blocklists)
User rules (custom blocks/allows)
Client settings (per-device rules)
Services (blocked services)
Rewrites (custom DNS entries)
DNS server config
DHCP settings
Query logs/stats

Sync Container

# /mnt/user/appdata/adguard-sync/adguardhome-sync.yaml
cron: "*/30 * * * *"
runOnStart: true

origin:
  url: http://192.168.10.10:3000
  username: jazzymc
  password: 7RqWElENNbZnPW

replicas:
  - url: http://192.168.10.1:3000
    username: jazzymc
    password: 7RqWElENNbZnPW

features:
  dns:
    serverConfig: false
    accessLists: true
    rewrites: true
  filters: true
  clientSettings: true
  services: true

Note: The sync container must be connected to both dockerproxy and br0 networks to reach both AdGuard instances.


Container Configuration (MikroTik)

Container Details

Setting Value
Image adguard/adguardhome:latest
Interface veth-adguard
IP 172.17.0.2/24
Gateway 172.17.0.1
Root dir usb1/adguard/root
Config mount usb1/adguard/conf → /opt/adguardhome/conf
Work mount usb1/adguard/work → /opt/adguardhome/work
Start on boot Yes

Container Commands

# Check status
/container print

# Start container
/container start 0

# Stop container
/container stop 0

# View logs
/log print where topics~"container"

Upstream DNS

Both AdGuard instances use the same upstream:

Upstream Type
https://dns.quad9.net/dns-query Primary (DoH)
9.9.9.9 Bootstrap
149.112.112.112 Bootstrap secondary

Management

Task Where to Do It
Change blocklists Unraid AdGuard (syncs to MikroTik)
Add custom rules Unraid AdGuard
Add client settings Unraid AdGuard
View query logs MikroTik AdGuard (real-time)
Check failover status MikroTik /tool netwatch print

Troubleshooting

Check Failover Status

/tool netwatch print
# STATUS should be "up" normally

Check Current DNS Target

/ip firewall nat print where comment~"VLAN10 Mgmt redirect"
# to-addresses should be 172.17.0.2 (normal) or 192.168.10.10 (failover)

View Failover Logs

/log print where message~"Failover"

Manual Failover Test

# Stop container (triggers failover)
/container stop 0

# Wait 15 seconds, check NAT rules switched to 192.168.10.10

# Start container (triggers recovery)
/container start 0

# Wait 15 seconds, check NAT rules switched back to 172.17.0.2

DNS Not Working

  1. Check container is running: /container print
  2. Check netwatch status: /tool netwatch print
  3. Test DNS directly: :resolve google.com server=172.17.0.2
  4. Check NAT rules: /ip firewall nat print where comment~"DNS"

Sync Not Working

# On Unraid
docker logs adguardhome-sync --tail 20

# Check connectivity
docker exec adguardhome-sync ping -c 2 192.168.10.10
docker exec adguardhome-sync ping -c 2 192.168.10.1

Backups

Backup Description
pre-adguard-2026-01-31 Before AdGuard setup
adguard-container-running-2026-01-31 Container working, before NAT
adguard-synced-2026-01-31 After sync configured
adguard-failover-complete-2026-01-31 Final with failover

Restore Command

/system backup load name=adguard-failover-complete-2026-01-31

Quick Reference

Normal Operation

  • DNS queries → MikroTik AdGuard (172.17.0.2)
  • Ad blocking active
  • ~143,000 filter rules

During Failover

  • DNS queries → Unraid AdGuard (192.168.10.10)
  • Ad blocking still active (same rules synced)
  • Automatic, no manual intervention needed

Recovery

  • Automatic when container comes back up
  • NAT rules switch back to MikroTik
  • No DNS interruption for clients

Document Version: 1.0 Last Updated: 2026-01-31