Setting up a flexible and secure local DNS for your home with AdGuard and Unbound

Setting up a flexible and secure local DNS for your home with AdGuard and Unbound
Photo by JJ Ying / Unsplash

Introduction

Setting up a robust home lab requires careful consideration of DNS configurations to ensure ease of use, security, and flexibility. A well-designed DNS setup minimizes manual effort, integrates seamlessly with existing tools, and keeps your services secure. This guide outlines how to achieve a powerful DNS configuration tailored for home lab enthusiasts.

My requirements

  1. Ease of Deployment: Automate the routing of new services to your reverse proxy without dealing with DNS records.
  2. Seamless Operation: Ensure consistent behavior when accessing services at home, via VPN, or from external networks.
  3. Privacy and Security: Avoid leaking of services operating services via DNS records and protecting potentially vulnerable services by putting them behind a reverse proxy.
  4. SSL Integration: Leverage automatic SSL termination for end-user-facing services using Caddy and Let’s Encrypt.
  5. Network-Level Ad Blocking: Support ad and tracker blocking for all devices, including IoT and headless systems.
  6. Dynamic Hostname Resolution: Enable automatic DNS resolution for internal devices through DHCP.

With a good amount of experimentation, I arrived at the following setup. After the diagram, I explain how I arrived at this architecture and why it works really well for me.

My setup

graph TD homerequest["DNS query from home network"] externalrequest["DNS query from public internet"] agh[AdGuard Home DNS] unbound[Unbound DNS] reverseproxy[Caddy reverse proxy] publicdns["Public DNS (i.e., quad9, 1.1.1.1)"] 403[403 Unauthorized] 200[200 OK ] agh -->|all other domains| publicdns subgraph "`**Home**`" subgraph "`**OPNsense**`" agh -->|*.internal.my.tld| unbound agh -->|*.home.my.tld| reverseproxy end homerequest --> agh reverseproxy -->|trusted IP| 200 reverseproxy -->|untrusted IP| 403 unbound ---->|*.internal.my.tld| 192.168.x.x end subgraph "`**Internet**`" publicdns --->|*.home.my.tld| reverseproxy publicdns ---->|Undefined record for *.my.tld| NXDOMAIN externalrequest --->|*.my.tld| publicdns end %% Define styles classDef homeNetworkStyle fill:#f6eac2,stroke:#555,stroke-width:1px; classDef OPNsenseStyle fill:#ffcaaf,stroke:#555,stroke-width:1px; classDef internetStyle fill:#a2e1db,stroke:#555,stroke-width:1px; %% Apply styles to subgraphs class **Home** homeNetworkStyle; class **OPNsense** OPNsenseStyle; class **Internet** internetStyle;

The case for two DNS resolvers

The first thing you may notice is that there are two local DNS resolvers, AdGuard Home (AGH) and Unbound. I chose this setup to strike the right balance between flexibility and ease of management. I have found that having two DNS resolvers can be highly effective, and does not add additional complexity. Here's why I decided to keep both, and why AGH is my primary, and routes to Unbound when certain conditions are met.

AdGuard Home

    • Excels at ad and tracker blocking.
    • Simplifies troubleshooting with detailed logs and an intuitive web interface.
    • Offers flexible rules for routing DNS requests. For instance:
      • Requests for *.home.my.tld are routed to the reverse proxy.
      • Requests for *.internal.my.tld are delegated to Unbound.
    • Supports temporary pausing of ad blocking in a way that's accessible to all household members.

Unbound

    • Integrates deeply with firewalls like OPNsense for DNS resolution.
    • Automatically maps hostnames to internal DNS through DHCP.
    • Does not handle wildcard DNS resolution as expected, but is otherwise very capable.

Subdomain organization

A clear subdomain structure is vital for ensuring that once setup, a complex setup shouldn't make easy things more complex.

End-User Services

  • Use a wildcard DNS record for *.home.my.tld to route all end-user services (i.e., web apps / web UIs) through a reverse proxy like Caddy. This gets you:
    • Automatic SSL termination with Let’s Encrypt.
    • Centralized control over which services are internet-facing versus local-only.
    • Simplified service addition without creating new DNS records for each.
ℹ️
It's worth calling out that automatic SSL generation for a given subdomain requires a publically-resolvable domain name or use of a DNS-01 challenge). Wildcard certificate generation with Let's Encrypt requires the use of a DNS-01 challenge.

Internal Services

    • Assign subdomains like *.internal.my.tld for devices not directly accessed by end users (e.g., MQTT brokers, IP cameras, Raspberry Pi devices).
    • These are automatically created through DHCP or manually defined for custom hostnames.
    • SSL termination is unnecessary as traffic is internal and traffic is isolated through VLAN segmentation.

The workflow

At Home

    • Primary resolver: AdGuard Home.
      • Routes external requests to public DNS servers (e.g., Quad9, Cloudflare, Google DNS).
      • Resolves *.home.my.tld requests directly to the IP of my reverse proxy (which happens to run on my OPNSense box).
      • Delegates *.internal.my.tld requests to Unbound (also running on OPNSense) using the following line in AGH config for Upstream DNS: [/shymoose.com/]127.0.0.1:53053
    • Internal-only devices rely on Unbound for hostname resolution via DHCP.

Away from Home

    • Public DNS resolves external websites.
    • Wildcard *.home.my.tld records point to dynamic DNS (e.g., DuckDNS) for external access to the reverse proxy.
    • Unauthorized services are automatically blocked by the reverse proxy.

Summary

Setting up a dual-resolver DNS infrastructure with AdGuard Home and Unbound provides a powerful foundation for any homelab environment. While it may seem complex at first glance, this architecture offers the perfect balance of security, flexibility, and ease of management. By separating end-user services from internal devices and implementing proper subdomain structure, you can create a maintainable system that grows with your needs while keeping your services secure and accessible. Whether you're just starting your homelab journey or looking to improve an existing setup, this approach to DNS management will serve you well in the long run.