Files
infrastructure/docs/09-MIKROTIK-ADGUARD-DOT-DOH.md
XTRM-Unraid 7389a20595
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Document container restart issue and fix
2026-01-25 15:23:00 +02:00

11 KiB

MikroTik AdGuard Home with DoT/DoH

Status: Completed
Implemented: 2026-01-25


Overview

Single DNS endpoint for both internal and external clients with ad blocking and encrypted DNS.

Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                           EXTERNAL                                   │
│                                                                      │
│   Mobile/Remote ──► dns.xtrm-lab.org ──► WAN:853 (DoT)              │
│                                      ──► WAN:8443 (DoH)             │
└─────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                        MikroTik hAP ax³                              │
│                         192.168.31.1                                 │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │                    NAT (DSTNAT)                              │    │
│  │  WAN:853  ──► 172.17.0.2:853  (DoT)                         │    │
│  │  WAN:8443 ──► 172.17.0.2:443  (DoH)                         │    │
│  │  LAN:53   ──► 172.17.0.2:53   (DNS redirect)                │    │
│  │  LAN:3000 ──► 172.17.0.2:80   (Web UI)                      │    │
│  └─────────────────────────────────────────────────────────────┘    │
│                                │                                     │
│                                ▼                                     │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │              AdGuard Home Container                          │    │
│  │              172.17.0.2 (veth-adguard)                       │    │
│  │                                                              │    │
│  │  Ports: 53 (DNS), 80 (HTTP), 443 (HTTPS), 853 (DoT)         │    │
│  │  Storage: usb1/adguard/{conf,work,root}                     │    │
│  └─────────────────────────────────────────────────────────────┘    │
│                                │                                     │
│                                ▼                                     │
│                         Upstream DNS                                 │
│                    ┌──────────────────┐                             │
│                    │ 192.168.31.4     │ ◄── Unraid AdGuard (primary)│
│                    │ 8.8.8.8          │ ◄── Google (fallback)       │
│                    │ 1.1.1.1          │ ◄── Cloudflare (fallback)   │
│                    └──────────────────┘                             │
└─────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                           INTERNAL                                   │
│                                                                      │
│   LAN Clients ──► 192.168.31.1:53 ──► NAT redirect ──► Container    │
│   (192.168.31.0/24)                                                  │
└─────────────────────────────────────────────────────────────────────┘

Network Configuration

Container Network

Component IP Address Interface
MikroTik (gateway) 172.17.0.1/24 veth-adguard
AdGuard container 172.17.0.2/24 veth-adguard

Port Mapping

Service External Port Internal Target Protocol
DNS 53 172.17.0.2:53 UDP/TCP
DoT 853 172.17.0.2:853 TCP
DoH 8443 172.17.0.2:443 TCP
Web UI 3000 172.17.0.2:80 TCP

Routing & NAT Rules

DNS Flow for LAN Clients

1. Client (192.168.31.x) sends DNS query to any IP:53
2. DSTNAT rule intercepts and redirects to 172.17.0.2:53
3. SRCNAT masquerade ensures return traffic goes back through MikroTik
4. AdGuard processes query, checks filters
5. If not cached/blocked, forwards to upstream (192.168.31.4 first)
6. Response returns to client

NAT Rules (in order)

# 1. Exception rules (must be FIRST to prevent loops)
chain=dstnat action=accept protocol=udp src-address=172.17.0.0/24 dst-port=53
    comment="Allow MikroTik AdGuard outbound DNS"

chain=dstnat action=accept protocol=udp src-address=192.168.31.4 dst-port=53
    comment="Allow Unraid AdGuard outbound DNS"

chain=dstnat action=accept protocol=tcp src-address=192.168.31.4 dst-port=53
    comment="Allow Unraid AdGuard outbound DNS TCP"

# 2. LAN DNS redirect
chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53
    protocol=udp src-address=192.168.31.0/24 dst-port=53
    comment="Redirect DNS to MikroTik AdGuard"

chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53
    protocol=tcp src-address=192.168.31.0/24 dst-port=53
    comment="Redirect DNS to MikroTik AdGuard TCP"

# 3. Masquerade for symmetric routing
chain=srcnat action=masquerade protocol=udp src-address=192.168.31.0/24
    dst-address=172.17.0.2 dst-port=53
    comment="Masquerade DNS to MikroTik AdGuard"

chain=srcnat action=masquerade protocol=tcp src-address=192.168.31.0/24
    dst-address=172.17.0.2 dst-port=53
    comment="Masquerade DNS to MikroTik AdGuard TCP"

# 4. External access (DoT/DoH)
chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=853
    protocol=tcp in-interface=eth1_WAN dst-port=853
    comment="DNS over TLS (DoT)"

chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=443
    protocol=tcp in-interface=eth1_WAN dst-port=8443
    comment="DNS over HTTPS (DoH)"

# 5. Web UI access
chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=80
    protocol=tcp dst-address=192.168.31.1 dst-port=3000
    comment="AdGuard Web UI"

Firewall Filter Rules

# Allow traffic to/from container network
chain=input action=accept dst-address=172.17.0.0/24
    comment="Allow container network"

chain=input action=accept src-address=172.17.0.0/24
    comment="Allow from container network"

chain=forward action=accept dst-address=172.17.0.0/24
    comment="Allow to container network"

chain=forward action=accept src-address=172.17.0.0/24
    comment="Allow from container network"

MikroTik DNS Configuration

/ip dns
    servers=172.17.0.2
    allow-remote-requests=yes

Container Configuration

Mounts

Name Source Destination
agh-config usb1/adguard/conf /opt/adguardhome/conf
agh-work usb1/adguard/work /opt/adguardhome/work

Container Settings

  • Image: adguard/adguardhome:latest
  • Version: v0.107.71
  • Root dir: usb1/adguard/root
  • DNS: 8.8.8.8 (for container itself during startup)
  • Start on boot: yes
  • Logging: yes

TLS Configuration

  • Server name: dns.xtrm-lab.org
  • Certificate: Let's Encrypt (ECDSA)
  • Valid until: 2026-03-10
  • Certificate location: /mnt/user/appdata/claude-code/certbot/config/live/dns.xtrm-lab.org/

AdGuard Settings

Credentials

Upstream DNS

  1. 192.168.31.4 (Unraid AdGuard - primary, has filter lists)
  2. 8.8.8.8 (Google - fallback)
  3. 1.1.1.1 (Cloudflare - fallback)

Bootstrap DNS

  • 8.8.8.8
  • 1.1.1.1

Usage

For LAN Clients

No configuration needed - DNS queries are automatically redirected.

For Android (Private DNS)

Settings → Network → Private DNS → dns.xtrm-lab.org

For iOS (DNS over HTTPS)

Use a DNS profile with: https://dns.xtrm-lab.org:8443/dns-query

For Browsers (DoH)

Firefox/Chrome: https://dns.xtrm-lab.org:8443/dns-query

Troubleshooting

Check container status

/container print

Check container logs

:log print where topics~"container"

Test DNS resolution

:resolve google.com server=172.17.0.2

Check NAT rules

/ip firewall nat print where comment~"DNS" or comment~"AdGuard"

Scripts

Setup script: scripts/mikrotik-adguard-setup.rsc

Known Issues

Container fails after restart with "could not load config json"

Symptoms:

  • Container shows status S (stopped)
  • Log shows: could not load config json

Cause: Container metadata/config.json corruption after MikroTik restart.

Fix:

# 1. Remove broken container
/container remove [find name=adguardhome]

# 2. Recreate container (will re-download/extract image)
/container add remote-image=adguard/adguardhome:latest interface=veth-adguard root-dir=usb1/adguard/root logging=yes start-on-boot=yes dns=8.8.8.8 name=adguardhome

# 3. Wait for extraction to complete (check with /container print)

# 4. Add mountlists (note: parameter is "mountlists" not "mounts")
/container set 0 mountlists=agh-config,agh-work

# 5. Start container
/container start 0

# 6. Restore MikroTik DNS
/ip dns set servers=172.17.0.2

Note: The AdGuard configuration in /opt/adguardhome/conf is preserved because it is on a separate mount (usb1/adguard/conf).