- 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>
13 KiB
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
- Netwatch monitors 172.17.0.2 (container IP) every 10 seconds
- If ping fails for 3 seconds → status changes to "down"
- dns-failover-down script runs → NAT rules switch to Unraid
- When ping succeeds again → status changes to "up"
- 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
- Check container is running:
/container print - Check netwatch status:
/tool netwatch print - Test DNS directly:
:resolve google.com server=172.17.0.2 - 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