Self-contained paste for a RouterOS v7 LAN that already has IPv6 SLAAC working. It makes the router the LAN DNS resolver, sends upstream DNS through Cloudflare DoH, advertises the router's own ULA as DNS via RA RDNSS, and stops DHCPv4 from advertising 192.168.88.1 as DNS while keeping admin@192.168.88.1 management working.
Full write-up with topology, rationale, and the rest of the build: https://marfillaster.github.io/mikrotik-home-network
DNS companion/update for:
- https://gist.github.com/marfillaster/7580167fb1721b7a43002daf3382e6e5
- https://gist.github.com/marfillaster/a80d378124db0d879a962ce73d31b345
Three things changed from the earlier revision of this gist, and the write-up explains why each:
- DoH bootstrap is A-only on purpose. IPv4 is up the moment the WAN is; IPv6 only becomes reachable after the WireGuard tunnel (and BFD) converge. Pinning AAAA records for
cloudflare-dns.comwould push the first DoH query onto a half-warm or broken tunnel while the IPv4 path is direct to a nearby Cloudflare PoP. Once DoH is up, normal client queries still resolve and use AAAA records. - RA RDNSS uses
advertise-dns=self, not a hardcodeddns=. The router advertises whatever address it holds on the interface, so the RDNSS can never point at a stale or wrong address and it survives a renumber with nothing to keep in sync. dns-none=yesis uniform. No VLAN hands out a DHCPv4 resolver anymore; DNS is uniformly the ND RDNSS and the router resolves upstream over DoH. Trade-off: a client with no RFC 8106 RDNSS support gets no DNS — acceptable here because every VLAN carries a ULA and the device population supports it.
Replace:
<LAN_BRIDGE>with your LAN bridge, usuallybridge<LAN_ULA>with the router's LAN ULA, for examplefd96:7d0b:7dc2:1::1
# Import CA roots before enabling DoH.
/tool/fetch url=https://curl.se/ca/cacert.pem dst-path=cacert.pem
/certificate/import file-name=cacert.pem passphrase=""
# Router DNS resolver + Cloudflare DoH.
/ip dns
set allow-remote-requests=yes \
max-concurrent-queries=200 \
use-doh-server=https://cloudflare-dns.com/dns-query \
verify-doh-cert=yes
# DoH endpoint bootstrap (A-only on purpose) + local router name.
/ip dns static
add address=104.16.248.249 name=cloudflare-dns.com comment="DoH bootstrap"
add address=104.16.249.249 name=cloudflare-dns.com comment="DoH bootstrap"
# Reachable as the FQDN `router.lan` from any client whose resolver is the
# router. No search-domain magic; type the dot-lan suffix.
add address=<LAN_ULA> name=router.lan type=AAAA comment="LAN ULA"
# Add stable LAN ULA and advertise self as DNS via RA RDNSS.
/ipv6 address
add address=<LAN_ULA>/64 advertise=yes interface=<LAN_BRIDGE> comment="ULA - RFC 4193"
# advertise-dns=self: the router advertises whatever address it holds on the
# interface, so RDNSS survives a renumber with nothing to keep in sync.
/ipv6/nd
add interface=<LAN_BRIDGE> \
advertise-dns=self \
managed-address-configuration=no other-configuration=no \
ra-interval=20s-200s
# Stop DHCPv4 from advertising 192.168.88.1 as DNS; clients use RDNSS instead.
# This does not remove 192.168.88.1 from the bridge.
/ip dhcp-server network
set [find address=192.168.88.0/24] dns-none=yes
Test on the router:
:put [:resolve "cloudflare.com"]
/log/print where message~"DoH|dns"
Test on macOS:
scutil --dns | grep -i 'nameserver\['
dig @<LAN_ULA> cloudflare.com
dig @<LAN_ULA> ipv6.google.com AAAAExpected macOS DNS:
nameserver[0] : <LAN_ULA>
192.168.88.1 should no longer appear as DNS after the Mac renews DHCP or Wi-Fi reconnects.