Networking & DNS

Split-horizon DNS explained: different answers inside and outside

What split-horizon (split-brain) DNS is, why offices and private networks use it, how to implement it with BIND views, Unbound or a hosts-file approach, and pitfalls to avoid.

AdvancedDNS and networking3 min read

Split-horizon DNS (also called split-brain DNS) gives different answers to the same question depending on who asks. Users inside your office or private network get a private IP for app.example.com, while the internet gets the public IP. This guide explains when split-horizon DNS helps and how to set it up.

Before you start

  • A DNS server you control for internal clients (BIND, Unbound, or a router/firewall with DNS features).
  • A clear list of names that should resolve differently internally.

Why use split-horizon DNS?

  • Hairpin NAT problems – many routers can't route internal users to the public IP of a server on the same network.
  • Performance – internal traffic stays on the LAN or private network instead of going out and back.
  • Private services – internal-only names (for example intranet.example.com) are never published publicly.
  • Server-to-server traffic – app servers reach the database over its private IP using the same hostname.

Option 1: BIND views

acl internal { 10.0.0.0/8; 192.168.0.0/16; 127.0.0.1; };

view "internal" {
    match-clients { internal; };
    recursion yes;
    zone "example.com" {
        type primary;
        file "/etc/bind/zones/db.example.com.internal";
    };
};

view "external" {
    match-clients { any; };
    recursion no;
    zone "example.com" {
        type primary;
        file "/etc/bind/zones/db.example.com.external";
    };
};

When views are used, every zone must be inside a view. Keep both zone files in sync for records that should be the same.

Option 2: Unbound local overrides

If your public DNS is hosted elsewhere and you only need a few internal overrides, run Unbound as the internal resolver:

server:
    local-zone: "app.example.com." redirect
    local-data: "app.example.com. 300 IN A 10.0.0.20"

All other names resolve normally from the public internet.

Option 3: hosts files (small setups)

For a couple of servers, an /etc/hosts entry like 10.0.0.21 db.example.com on each machine achieves the same effect without a DNS server – but it doesn't scale and is easy to forget.

Pitfalls

  • Drift – internal and external zones get out of sync. Automate generation from one source if possible.
  • VPN and roaming users – laptops switching networks may cache the wrong answer; keep TTLs modest.
  • TLS certificates – certificates must cover the hostname, not the IP, so the same certificate works both inside and outside.
  • DNSSEC – internal answers that differ from signed public data can fail validation on validating clients; serve internal names from an unsigned internal zone.
  • Debugging confusion – always note which resolver you query (dig @10.0.0.1 vs dig @1.1.1.1).

Test it

dig @10.0.0.1 app.example.com +short
dig @1.1.1.1 app.example.com +short

The first should return the private IP, the second the public one.

FAQ: split-horizon DNS

Is split-horizon DNS a security feature?

It keeps internal names out of public DNS, but it is not access control. Protect internal services with firewalls and authentication.

Can cloud providers do split-horizon?

Yes, most offer private DNS zones attached to private networks alongside public zones.

Should I use a fake TLD like .local or .lan internally?

Prefer a subdomain of a domain you own, such as internal.example.com; .local conflicts with mDNS and invented TLDs may become real.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.