Post

OPNsense 26.1: Unbound DNS Returns with Improved Stability

The good news for OPNsense users: DNS issues are resolved in version 26.1, and Unbound is back to working flawlessly. Learn how to properly configure Unbound with dnsmasq integration for optimal DNS resolution and local hostname registration.

OPNsense 26.1: Unbound DNS Returns with Improved Stability

Great news! If you’re one of the many who migrated to dnsmasq due to DNS issues in OPNsense 25.7, you can now safely move back. OPNsense 26.1 resolves all the DNS problems that plagued version 25.7, and Unbound is working flawlessly again.

I spent weeks troubleshooting the 25.7 DNS failures in my homelab—watching websites timeout randomly, devices losing connection, and then mysteriously recovering after a cache flush. It was infuriating. The jump to dnsmasq-only was frustrating too, losing features like DNSSEC validation and detailed statistics. But the good news? We can now have the best of both worlds again.

This post covers the proper way to configure Unbound in OPNsense 26.1 based on official documentation and lessons learned from the migration mess. I’ll explain the hybrid architecture that finally works reliably, walk you through the setup step-by-step, and share the gotchas I discovered along the way.


✅ What’s Fixed in OPNsense 26.1?

The core problem in 25.7 was a fundamental conflict between how the new dnsmasq-based DHCP service worked and how Unbound tried to handle internal DNS queries. When OPNsense switched from ISC DHCP to dnsmasq, the integration points broke apart. Unbound couldn’t reliably register or resolve DHCP hostnames, and the interaction between the two services caused cascading failures.

OPNsense 26.1 fixed this with several critical updates:

  • Proper integration between Unbound and dnsmasq is now clearly documented and tested
  • Query forwarding works correctly, allowing Unbound to cleanly delegate local domain lookups to dnsmasq
  • DHCP hostname registration is seamless when configured properly
  • No more intermittent DNS failures or mysterious cache-related issues
  • All Unbound features are back and functioning correctly

The OPNsense team has officially recommended a hybrid approach that combines the strengths of both services: Unbound as the primary recursive resolver with dnsmasq handling DHCP hostname registration and local DNS authority.


🏗️ Architecture: Why Unbound + Dnsmasq Works

When I first tried Unbound-only in 25.7, it worked for external DNS but failed on local hostnames. When I tried dnsmasq-only, it worked fine for both, but I lost advanced features. The elegant solution in 26.1 divides responsibilities: let each service do what it’s best at.

Think of it like this: Unbound is a sophisticated DNS librarian that can actually look up answers by walking through the entire DNS tree. Dnsmasq is a fast postal worker who knows exactly which local letters go to which house. You want both in your network.

Unbound (The Recursive Resolver)

  • Primary DNS entry point listening on port 53 (what your clients connect to)
  • Handles the heavy lifting of recursive DNS resolution for internet domains
  • Maintains an intelligent cache with prefetching and eviction
  • Validates DNSSEC signatures to prevent DNS spoofing
  • Forwards local domain queries (like laptop.lan.internal) to dnsmasq
  • By default, recursively queries authoritative nameservers (more secure/private than using upstream DNS)
  • Optionally can forward to upstream DNS servers if you prefer (see Step 1b for when this matters)

Dnsmasq (The Local Authority)

  • DHCP server that assigns IPs and collects hostname information
  • Authoritative DNS forwarder listening on non-standard port 53053 (internal use only)
  • Automatically registers DHCP clients’ hostnames as they join the network
  • Maintains the “living” list of local devices that are currently active
  • Returns NXDOMAIN (“not found”) for unknown local hosts—critical for troubleshooting typos

How The Magic Happens (Data Flow)

For local domain queries (e.g., ping laptop.lan.internal):

  1. Your laptop sends a DNS query to Unbound on port 53
  2. Unbound checks: “Is this a local domain I know about?” → Yes, lan.internal is configured as local
  3. Unbound forwards the query to dnsmasq on port 53053
  4. Dnsmasq looks in its DHCP lease database: “Oh, I just assigned an IP to a device named ‘laptop’ this morning”
  5. Dnsmasq responds with the IP address
  6. Unbound caches this answer and passes it back to your client
  7. Next time someone asks about laptop.lan.internal, Unbound answers from its cache (instant!)

For external domain queries (e.g., ping google.com):

  1. Your browser sends a DNS query to Unbound on port 53
  2. Unbound checks: “Is this a local domain?” → No, this is for the internet
  3. Unbound recursively resolves by walking the DNS tree:
    • “Root servers, who knows about .com?”
    • .com servers, who knows about google.com?”
    • “Google’s servers, what’s the IP for google.com?”
  4. Unbound caches the result and responds to your client
  5. Unbound also validates the answer with DNSSEC if enabled (security!)
  6. OR, if configured for forwarding mode (Step 1b), Unbound asks an upstream DNS server instead

The key insight: Unbound stays in charge of responding to your clients. Dnsmasq is really just a back-end database of local hostname-to-IP mappings.


📋 Step-by-Step Configuration Guide

Step 1: Configure Unbound DNS as Primary Resolver

First, make Unbound the entry point for all DNS queries in your network. This was broken in 25.7, but 26.1 gets this right:

  1. Navigate to Services → Unbound DNS → General
  2. Enable Unbound as your primary DNS authority:
    • Enable: Checked (turn it on)
    • Listen Port: 53 (the standard DNS port that clients expect)
    • Interface: Select your LAN interface (typically LAN—this is where your home devices connect)

A crucial note about recursive vs. forwarding: By default, Unbound is a recursive resolver, which means it will contact root servers and walk down the DNS tree to answer questions. This is the secure choice—no upstream DNS provider can see your DNS queries, and you validate answers with DNSSEC. This is what I’d recommend for a privacy-focused homelab.

However, if you have a slow internet connection or prefer letting someone else handle DNS recursion, you can configure Unbound to forward queries upstream. See Step 1b below for that option.

Step 1b: Optional - Configure Upstream DNS Servers (Forwarding Mode)

If you prefer Unbound to forward all external queries to upstream DNS servers instead of recursively resolving:

  1. Go to Services → Unbound DNS → General → DNS Query Forwarding
  2. Add a catch-all forwarding rule:
Field Value Purpose
Domain . (dot) Catch-all for all domains not in internal zones
Server IP 1.1.1.1 Cloudflare (or your preferred DNS: 8.8.8.8, 9.9.9.9, etc.)
Server Port 53 Standard DNS port
  1. Add additional servers for redundancy:
    • Add separate entries for 8.8.8.8 and 9.9.9.9

Note: If you use forwarding mode, queries will have slightly lower latency but less privacy. Recursive mode is recommended for privacy-conscious users.

Step 2: Configure Dnsmasq for DHCP and Local DNS

This is where the magic happens for local networks. Dnsmasq will handle DHCP (giving IPs to your devices) and maintain the local hostname registry (knowing who just got an IP). This must run on a non-standard port (53053) because Unbound is using port 53:

  1. Go to Services → Dnsmasq DNS & DHCP → General
  2. Enable dnsmasq and set the port:
    • Enable: Checked (turn it on)
    • Listen Port: 53053 (critical: non-standard port so it doesn’t conflict with Unbound on port 53)
    • Interface: Select interfaces (e.g., LAN and GUEST if you have separate networks)
  3. DNS Configuration options (these control how dnsmasq handles queries):
    • Do not forward to system DNS: Checked (prevents circular queries with system DNS)
    • Do not forward private reverse lookups: Checked (local reverse DNS stays local)
    • DHCP fqdn: Checked (✨ Key option: registers clients with their full domain name when they request an IP)
    • DHCP default domain: internal (the domain suffix for DHCP clients—adjust if you prefer something else)
    • DHCP register firewall rules: Checked (automatically opens firewall for new DHCP clients)

Pro tip from experience: The DHCP fqdn option is the secret sauce. With it enabled, when your laptop requests a DHCP lease and announces its hostname, dnsmasq automatically creates a DNS entry like laptop.internal. Without it, you get DHCP IPs but no hostname resolution—the problem we had in 25.7.

Step 3: Configure Unbound Query Forwarding

This is the crucial step that connects Unbound and dnsmasq. You’re telling Unbound: “When someone asks about a device in our local domain, ask dnsmasq instead of looking on the internet.” This is what 25.7 couldn’t do properly—in 26.1, it works flawlessly.

  1. Go to Services → Unbound DNS → Query Forwarding
  2. Create entries to delegate local domain authority to dnsmasq:
Field Value Purpose
Domain lan.internal Your local domain
Server IP 127.0.0.1 Localhost (dnsmasq)
Server Port 53053 Dnsmasq port
  1. Add reverse lookup forwarding (for PTR records—the “reverse” lookups):
Field Value Purpose
Domain 1.168.192.in-addr.arpa Reverse DNS for 192.168.1.x
Server IP 127.0.0.1 Localhost (dnsmasq is local)
Server Port 53053 Dnsmasq’s port

Reverse DNS explanation: When something asks “What device is at IP 192.168.1.100?”, that’s a reverse lookup. Dnsmasq handles this for your local DHCP clients. Adjust the domain if you use a different subnet:

  • For 192.168.1.x, use 1.168.192.in-addr.arpa
  • For 10.0.0.x, use 0.0.10.in-addr.arpa
  • For 172.16.0.x, use 0.16.172.in-addr.arpa

Important note: Get these domain names exactly right, or reverse lookups will fail silently.

Step 4: Configure DHCP Ranges in Dnsmasq

Set up DHCP ranges with automatic DNS registration:

  1. Go to Services → Dnsmasq DNS & DHCP → DHCP ranges
  2. Add a range for your LAN:
Field Value Example
Interface LAN Your main network interface
Start address 192.168.1.100 First DHCP IP
End address 192.168.1.199 Last DHCP IP
Domain lan.internal Matches your local domain
Lease time 86400 24 hours (in seconds)

Important: The domain you set here must match the domain you configured for Unbound query forwarding.

Step 5: Verify System DNS Settings

OPNsense itself (the firewall) needs to know where to find DNS too. Since Unbound is running locally on the firewall, just point to localhost:

  1. Go to System → Settings → General
  2. Configure DNS for the OPNsense system itself:
    • Primary DNS: 127.0.0.1 (Unbound on this very firewall)
    • Delete any other DNS server entries (they’re not needed)
    • Uncheck: “Allow DNS server list to be overridden by DHCP/PPP on WAN” (this prevents your ISP pushing in their DNS servers)

Why this matters: If OPNsense tries to use your ISP’s DNS while Unbound is bootstrapping, or if your ISP’s DNS becomes your fallback, it undermines the whole setup. Keep everything pointed to localhost.


🧪 Testing Your Configuration

Before you consider this “done,” test everything. I’ve seen configurations that look right in the UI but fail in practice. The good news is testing is easy—just use the dig or nslookup commands from any device on your network.

Test Internet Resolution

First, verify that Unbound can actually reach the internet and resolve common domains:

1
2
3
4
5
6
7
8
9
10
11
# Basic test from any device on your network
nslookup google.com
nslookup cloudflare.com

# Explicitly query your OPNsense to confirm it's responding
dig @192.168.1.1 google.com

# In the response you'll see:
# - SERVER: 192.168.1.1 (YOUR OPNsense, good!)
# - ANSWER showing google.com's IP (should be there)
# - QUERY TIME: should be <100ms if from cache, <500ms if recursive

If you get “connection refused” or timeouts, Unbound might not be running. Check Services → Unbound DNS and verify it’s enabled and has no errors in the log.

Test Local Hostname Resolution

This is the critical test—can you reach devices on your network by name? From any device (laptop, phone, etc.):

1
2
3
4
5
6
7
8
9
10
11
12
13
# Full domain name lookups
ping laptop.lan.internal
nslookup server.lan.internal
dig @192.168.1.1 nas.lan.internal

# Short name lookups (should work—your OS adds the domain suffix)
ping laptop
nslookup server

# Expected:
# - Queries should resolve to your DHCP-assigned IPs
# - First query might take 1-2ms, subsequent ones <1ms (cached)
# - If it fails, check the Unbound/Dnsmasq logs below

If this doesn’t work, the problem is 90% of the time a domain mismatch (see Step 4 notes above) or firewall rules blocking DNS traffic on port 53.

Verify DHCP Registration in the Logs

Dnsmasq logs every DNS query and registration. If things aren’t working, the logs tell you why:

  1. Navigate to Services → Dnsmasq DNS & DHCP → Log
  2. Look for DHCP lease entries showing hostname registration
  3. You should see something like:
    1
    2
    3
    
    DHCPREQUEST(lan) aa:bb:cc:dd:ee:ff
    DHCPACK(lan) 192.168.1.100 aa:bb:cc:dd:ee:ff laptop
    added laptop.lan.internal from DHCP
    
  4. Verify clients are actually using your OPNsense for DNS:
    • Windows: ipconfig /all or nslookup -debug google.com (look for server IP)
    • macOS: scutil --dns grep -A 5 DNS
    • Linux: cat /etc/resolv.conf or systemctl status systemd-resolved
    • Should show DNS server: 192.168.1.1 (your OPNsense LAN IP)

Troubleshooting the logs: If you see queries failing or dnsmasq saying “forwarding to…,” that’s good—it’s delegating to Unbound. If you see dnsmasq returning errors for your local domain, the query forwarding chain is broken.

Monitor Query Forwarding Between Services

Unbound has its own logs. If you want to see the actual forwarding in action:

  1. Go to Services → Unbound DNS → Diagnostics
  2. Enable “Log Queries” for debugging (only temporarily—this is verbose!)
  3. Check the log for forwarding messages
  4. You should see entries like:
    1
    2
    
    [timestamp] info: query forwarding for lan.internal to 127.0.0.1#53053
    [timestamp] info: cached laptop.lan.internal
    

If you see Unbound not forwarding local domains, that’s your cue to double-check that the “lan.internal” forwarding rule exists in Services → Unbound DNS → Query Forwarding.


🚨 Troubleshooting

DNS Resolution Still Failing

If you’re still experiencing DNS issues after all this setup:

  1. First: Is Unbound even running?
    1
    2
    
    ssh admin@192.168.1.1
    netstat -tupln | grep unbound
    

    You should see both 127.0.0.1:53 and your LAN IP like 192.168.1.1:53. If not, Unbound didn’t start.

    Unbound startup issues usually mean:

    • Port 53 is already in use by another service (check if dnsmasq DNS is disabled if you want Unbound on 53)
    • Syntax error in the config (check Services → Unbound DNS → Diagnostics for errors)
    • Memory issues on very low-resource devices
  2. Check dnsmasq is listening on port 53053:
    1
    
    netstat -tupln | grep dnsmasq
    

    You should see 127.0.0.1:53053. If not, dnsmasq DNS feature isn’t enabled.

  3. Flush DNS cache on the client device, then test again:
    • Windows: ipconfig /flushdns then ipconfig /renew
    • macOS: sudo dscacheutil -flushcache and sudo killall -HUP mDNSResponder
    • Linux: systemctl restart systemd-resolved
    • iOS/Android: Toggle airplane mode
  4. Restart services from the OPNsense UI (always try this first):
    • Services → Unbound DNS → (hamburger menu) → Restart
    • Services → Dnsmasq DNS & DHCP → (hamburger menu) → Restart
    • Wait 10 seconds for both to fully come back online

Pro tip: If DNS works then stops, check firewall rules (System → Firewall → Rules) to ensure nothing is blocking port 53.

Local Hostnames Not Resolving

The classic symptom: ping google.com works but ping laptop.local doesn’t.

Quick checks:

  • DHCP fqdn enabled in dnsmasq? (Services → Dnsmasq DNS & DHCP → General)
  • Domain name matches between DHCP ranges and Unbound forwarding?
  • Client device has a hostname set? (Windows/macOS/Linux all have this)
  • Check logs: Services → Dnsmasq DNS & DHCP → Log

Most common issue: Domain mismatch. If DHCP assigns laptop.lan.internal but Unbound forwards laptop.internal, they never match.

Query Forwarding Not Working

If by-name DNS fails but by-IP works:

  • Check Unbound Query Forwarding rules exist (Services → Unbound DNS → Query Forwarding)
  • Verify domain names match exactly between forwards and DHCP ranges
  • Check dnsmasq is actually listening on 53053
  • Review logs in both services

🔄 Reverting from Dnsmasq-Only to Unbound

If you previously migrated to dnsmasq-only due to 25.7 issues, here’s how to go back:

  1. Disable dnsmasq as primary DNS:
    • Services → Dnsmasq DNS & DHCP → General
    • Set Listen Port to 53053
    • Apply changes (keeps DHCP running)
  2. Enable Unbound as primary:
    • Services → Unbound DNS → General
    • Enable: Checked
    • Listen Port: 53
    • Apply changes
  3. Configure Unbound to forward local domains:
    • Services → Unbound DNS → Query Forwarding
    • Add entries for your local domain(s) pointing to dnsmasq on 53053
    • Apply changes
  4. Update your DHCP configuration if needed:
    • Ensure the domain in DHCP ranges matches the forwarding domains
    • Verify firewall rules are created for your interfaces
  5. Test DNS resolution thoroughly:
    • External: nslookup google.com
    • Local: nslookup laptop.lan.internal

🧠 Final Thoughts: It All Makes Sense Now

When I upgraded to OPNsense 25.7 and DNS broke, I felt betrayed by software I’d trusted. Then dnsmasq-only “fixed” it, but I kept feeling like I’d downgraded. Now with 26.1, it finally clicks.

The real victory isn’t that Unbound is back. It’s that I now understand why it broke, why the workaround helped, and why 26.1 finally got it right. That understanding makes me a better homelab operator.

What this means for you:

If you’ve been running dnsmasq-only since 25.7, upgrade to 26.1 and follow this guide. You get back all the features you lost (DNSSEC, blocklists, advanced statistics) without the pain of chasing some complicated alternative setup. It’s the sweet spot.

If you’re setting up OPNsense for the first time on 26.1, don’t start with dnsmasq-only “because it’s simpler.” Follow this hybrid approach from the start. Yes, it’s slightly more complex, but you get better security, better control, and better performance.

The DNS Foundation You Now Have

  • 🔒 Security: DNSSEC validation protects against DNS spoofing
  • 🏡 Local control: Your network’s hostnames stay local; they’re never sent to upstream providers
  • 📊 Visibility: Unbound statistics show you exactly what’s happening with DNS
  • 🚫 Protection: Blocklists automatically protect against malware and ad domains
  • Performance: Advanced caching means after two weeks of operation, 60-70% of your DNS queries are answered instantly
  • 🔄 Reliability: When one piece breaks, you can debug it in isolation

This isn’t just a working DNS setup. This is a foundation that will stay stable for years. That’s what I wanted from OPNsense, and that’s what 26.1 finally delivers.


📚 Additional Resources

For more detailed information, refer to:




Want to help fuel more posts? You know what to do:

Buy Me a Coffee at ko-fi.com
This post is licensed under CC BY 4.0 by the author.