Split-Horizon DNS

Internal vs external DNS views — how organizations serve different answers to different clients based on network location.

Imagine you work at a company with an internal wiki at wiki.example.com. From the office, it should resolve to an internal IP address (10.0.1.50). From the public internet, it shouldn’t resolve at all — or should point to a VPN gateway. Same name, different answers, depending on who’s asking.

This is split-horizon DNS (also called split-brain DNS or DNS views), and it’s one of the most widely deployed DNS patterns in enterprise networks.

The Core Concept

Split-horizon DNS serves different DNS responses to different clients based on their source network. The DNS server — typically an authoritative server — maintains two or more views of the same zone, each with its own set of records.

External view (public internet):
app.example.com    →    203.0.113.10  (public load balancer)

Internal view (corporate network):
app.example.com    →    10.0.5.20     (internal server)

The decision of which view to serve is typically based on the source IP address of the DNS query. Queries from the corporate network (e.g., 10.0.0.0/8) receive internal records. Everything else gets the external view.

RFC 6950 discusses split-DNS configurations in the context of enterprise networks, noting that it’s a common pattern for providing different resolution behavior for internal and external users.

Why Split-Horizon Exists

Internal Services

The most common use case: companies run internal services (intranets, wikis, monitoring dashboards, admin panels) that should only be accessible from the corporate network. Split-horizon DNS maps these services to internal IPs from the inside while hiding them from the outside.

Avoiding Hairpin NAT

Without split DNS, an internal user accessing app.example.com would:

  1. Resolve app.example.com → public IP 203.0.113.10
  2. Send a packet to 203.0.113.10
  3. The packet hits the corporate firewall
  4. The firewall NATs it back inside to the internal server at 10.0.5.20

This “hairpin” or “NAT reflection” adds latency, wastes firewall resources, and can cause problems with logging (the server sees the firewall’s IP, not the client’s). Split DNS avoids this by resolving directly to the internal IP.

VPN Users

When employees connect via VPN, they should see the internal view. The VPN concentrator typically assigns IP addresses from an internal range, so split-horizon DNS naturally works — the VPN client’s DNS queries come from an internal IP, matching the internal view’s ACL.

Different Public and Private Architectures

Sometimes the internal and external architectures are genuinely different. The public-facing api.example.com might point to a CDN, while internally it points directly to the API servers (bypassing the CDN). The external mail.example.com might point to a cloud email provider, while internally it resolves to an on-premise mail relay.

Implementation with BIND Views

BIND, the most widely deployed DNS server, has native support for views. Here’s a simplified configuration:

acl "internal" {
    10.0.0.0/8;
    172.16.0.0/12;
    192.168.0.0/16;
    localhost;
};

view "internal" {
    match-clients { "internal"; };
    
    zone "example.com" {
        type master;
        file "/etc/bind/zones/internal/example.com.zone";
    };
};

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

The match-clients directive determines which view a query receives. Views are evaluated in order — the first match wins. The internal ACL matches queries from RFC 1918 private addresses, and everything else falls through to the external view.

Each view has its own zone file, which can contain completely different records:

; internal/example.com.zone
wiki.example.com.      IN A    10.0.1.50
app.example.com.       IN A    10.0.5.20
monitoring.example.com. IN A   10.0.2.100

; external/example.com.zone
app.example.com.       IN A    203.0.113.10
www.example.com.       IN A    203.0.113.11
; wiki and monitoring don't exist in external view

Notice that wiki.example.com and monitoring.example.com simply don’t exist in the external zone file. External queries for these names return NXDOMAIN — as far as the outside world knows, they don’t exist.

Cloud-Based Split-Horizon

Modern cloud environments implement split-horizon differently:

AWS Route 53 Private Hosted Zones

AWS allows you to create a private hosted zone associated with specific VPCs. DNS queries originating from within those VPCs receive the private zone’s records. Queries from outside receive the public hosted zone’s records.

Public hosted zone: example.com
  api.example.com → ALB (public-facing)
  
Private hosted zone: example.com (associated with VPC)
  api.example.com → internal NLB
  db.example.com → RDS endpoint

This is effectively split-horizon DNS managed as a service, without running your own DNS servers.

Azure Private DNS Zones

Azure’s equivalent: Private DNS Zones are linked to virtual networks and provide resolution only within those networks. They can override public DNS names — a VNet-linked private zone for example.com will shadow the public zone for VMs in that VNet.

Google Cloud DNS

Google Cloud offers private zones that are visible only within specified VPC networks, and split-horizon is achieved by creating a public zone and a private zone with the same name.

Security Considerations

Split-horizon DNS introduces security nuances that are easy to overlook:

Information Leakage

The internal view often contains names and IP addresses that reveal your internal architecture. If an attacker can trigger DNS queries from inside your network (via compromised devices, SSRF vulnerabilities, or DNS rebinding attacks), they can enumerate your internal infrastructure.

Mitigation: Don’t rely on split-horizon DNS as a security boundary. Use firewalls, network segmentation, and authentication independently of DNS.

DNS Rebinding Attacks

An attacker registers a domain with a short TTL. First resolution points to their server (which serves malicious JavaScript). Second resolution points to an internal IP (e.g., 10.0.1.1). The browser’s same-origin policy is satisfied because the domain hasn’t changed, but the requests now target internal infrastructure.

Split-horizon DNS doesn’t prevent this — the external view resolves the attacker’s domain normally. Defense requires DNS rebinding protection in the resolver (blocking private IPs in external responses).

Zone Transfer Risks

If zone transfers aren’t properly restricted, an external attacker could request a zone transfer and receive… which view? This depends on configuration. Ideally, zone transfers should be restricted by ACL and only permitted to known secondary servers.

view "internal" {
    zone "example.com" {
        allow-transfer { 10.0.0.2; 10.0.0.3; };
    };
};

view "external" {
    zone "example.com" {
        allow-transfer { none; };
    };
};

DNSSEC Complications

Running DNSSEC with split-horizon DNS is tricky. Both views of the zone need to be signed, but they contain different records, so they’ll have different signatures. If a resolver that validated the external view somehow receives an internal response (or vice versa), validation will fail.

This is a well-known operational challenge without a single clean solution. The practical advice: if you need DNSSEC with split-horizon DNS, keep your configuration simple, sign both views independently, and test thoroughly from both internal and external perspectives.

Best Practices

After years of split-horizon deployments going wrong, the community has settled on some best practices:

  1. Keep views synchronized for shared records: If a record should be the same in both views (like MX records for email), use a shared include file or automation to prevent drift.

  2. Use meaningful internal-only names: Instead of overloading app.example.com, consider using a dedicated internal domain like app.internal.example.com or app.corp.example.com. This makes it obvious which names are internal.

  3. Document your views: Split-horizon DNS is invisible — you can’t tell from a query result which view you received. Document what views exist, what ACLs control them, and what records differ.

  4. Monitor both views: Set up monitoring that checks DNS resolution from both internal and external vantage points. A misconfigured ACL could leak internal records externally (or block them internally).

  5. Automate zone management: Manually maintaining two zone files with overlapping records is error-prone. Use configuration management (Ansible, Terraform) or DNS management APIs.

Key Takeaways

  • Split-horizon DNS serves different answers based on the source network of the query
  • Primary use cases: internal services, avoiding hairpin NAT, VPN access, different internal/external architectures
  • BIND views are the traditional implementation; cloud providers offer managed split-horizon via private hosted zones
  • Security risks include information leakage, DNS rebinding, zone transfer exposure, and DNSSEC complications
  • Best practice: don’t rely on split DNS as a security boundary — it’s a convenience feature, not a firewall